home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / system / admin / new_su.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-06  |  4.2 KB  |  169 lines

  1. /*
  2. * su.c 1.0
  3. * Modified by tim lashua from James Wiegand's Berkeley based su.
  4. *
  5. * This su now takes the shell from the  password file instead of always
  6. * using a default shell. If no shell is specified in the password file,
  7. * /bin/sh is used. The -l or --login options can be used to invoke the
  8. * shell as if it were a login shell. Options to log all su activity or
  9. * just su to root have been added. I don't know what the standard
  10. * format for a sulog is, if there is one. The sulog created by this su
  11. * has the following format: there are three colon seperated fields 
  12. * containing, respectively, the login name of the person running su, 
  13. * the login name of the person being su'd, and the time and date.
  14. *
  15. * I have compiled this with gcc 2.1 on Linux 0.95c+ with the following
  16. * options: 
  17. *         -O -Wall -fstrength-reduce -static
  18. *
  19. */
  20.  
  21.  
  22.  
  23. #include <getopt.h>
  24. #include <pwd.h>
  25. #include <stdio.h>
  26. #include <string.h>
  27. #include <stdlib.h>
  28. #include <unistd.h>
  29.  
  30. /* the max path length (+1) for the shell, and home directory */
  31. #define SUPATHLEN 60
  32. #define USERLEN 9   /* maximum user name length + 1 */
  33. #define FAILURE -1
  34.  
  35. #define DEF_SHELL "/bin/sh" /* default shell if none is in /etc/passwd */
  36. #define LOG_FILE "/usr/adm/sulog"
  37. #define LOG_ROOT_ONLY 0 /* true if you only want su's to root logged */
  38. #define LOG_ALL 0    /* true if you want to log all su's */
  39.  
  40. struct option longopts[] = 
  41.   {
  42.     {"login", 0, NULL, 'l'},
  43.     {NULL, 0, NULL, 0}
  44.   };
  45.  
  46. int main(int argc, char **argv)
  47. {
  48. struct passwd *pwd;
  49. char *p;
  50. uid_t cur_uid;
  51. int  ch, login = 0;
  52.  
  53. char *new_user, username[USERLEN], *nargv[4], **np;
  54. char new_home_env[SUPATHLEN + 5]; /* + HOME= */
  55. char new_shell_env[SUPATHLEN + 6]; /* + SHELL= */
  56. char new_shell[SUPATHLEN];
  57.  
  58. FILE *logfile;
  59. long su_time;
  60. np = &nargv[3];
  61. *np-- = NULL;
  62.  
  63. while ((ch = getopt_long( argc, argv, "l", longopts, (int *) 0 )) != EOF)
  64.   switch((char)ch){
  65.   case 'l':
  66.     login = 1;
  67.     break;
  68.   case '?':
  69.   default:
  70.     fprintf(stderr, "Usage: su [-l] [--login] username \n");
  71.     exit(1);
  72.   }
  73.  
  74. argv += optind;
  75. errno = 0;
  76.  
  77. /* get current login password entry */
  78. cur_uid = getuid(); 
  79. pwd = getpwuid(cur_uid);
  80.  
  81. if(pwd == NULL){
  82.   fprintf(stderr, "su: invalid login\n"); 
  83.   exit(1);
  84. }
  85.  
  86. strcpy( username, pwd->pw_name ); /* store current login name */
  87.  
  88. /* get target login information, default to root */
  89. new_user = *argv ? *argv : "root";
  90.     
  91. pwd = getpwnam(new_user); /* get password entry for 'new_user' */
  92. if(pwd == NULL)
  93.   {
  94.     fprintf(stderr, "su: unknown login %s\n", new_user);
  95.     exit(1);
  96.   }
  97.  
  98. su_time = time(NULL); /* the time this program was run */
  99.  
  100. if(LOG_ALL){    /* log all attempts to su to a valid user */
  101.   logfile = fopen(LOG_FILE, "a");
  102.     fprintf(logfile,  "%s:%s:%s", username, new_user, \
  103.         asctime(localtime(&su_time)));
  104.   fclose(logfile);
  105. }
  106. else if(LOG_ROOT_ONLY){        /* log attempts to su root */
  107.   if (!strcmp(new_user, "root")){
  108.     logfile = fopen(LOG_FILE, "a");
  109.     fprintf(logfile,  "%s:%s:%s", username, new_user, \
  110.         asctime(localtime(&su_time)));
  111.     fclose(logfile);
  112.   }
  113. }
  114.  
  115.  /* if a password is required, check it */
  116.  /* a password is required if the current user is not root and the */
  117.  /* 'new_user' has a password */
  118.  
  119. if(cur_uid){    /* if current user isn't root */
  120.   if(*pwd->pw_passwd){
  121.     p = getpass("Password:");
  122.     if(strcmp(pwd->pw_passwd, crypt(p, pwd->pw_passwd))){
  123.       fprintf(stderr, "Sorry\n");
  124.       exit(1);
  125.     }
  126.   }
  127. }
  128.  
  129. /* set user and group id */
  130.  
  131. if(setgid(pwd->pw_gid) == FAILURE ){
  132.   perror("su: setgid");
  133.   exit(1);
  134. }
  135.  
  136. if(setuid( pwd->pw_uid) == FAILURE ){
  137.   perror("su: setuid");
  138.   exit(1);
  139. }
  140.  
  141.  /* determine which shell to execute. get the users shell from the */
  142.  /* entry in /etc/passwd, if no shell is specified there use /bin/sh */
  143.  
  144. strcpy(new_shell, pwd->pw_shell);
  145.  
  146. if (!(new_shell[0] == '/')){
  147.   strcpy(new_shell, DEF_SHELL);
  148.   fprintf(stderr, "su: no shell. using %s\n", DEF_SHELL);
  149. }
  150.  
  151. /* get and reset the environment variables HOME  and SHELL */
  152. strcpy(new_home_env, "HOME=");
  153. strcat(new_home_env, pwd->pw_dir);
  154. putenv(new_home_env);
  155.  
  156. strcpy(new_shell_env, "SHELL=");
  157. strcat(new_shell_env, new_shell);
  158. putenv(new_shell_env);
  159.  
  160. /* should this be treated as a login shell ? */
  161. *np = login ? "-su" : "su"; 
  162.  
  163. /* start the new shell */
  164. execv(new_shell, np);
  165.  
  166. return(0);
  167.  
  168. }
  169.