Magellan Linux

Diff of /trunk/mkinitrd-magellan/busybox/loginutils/adduser.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 532 by niro, Sat Sep 1 22:45:15 2007 UTC revision 816 by niro, Fri Apr 24 18:33:46 2009 UTC
# Line 8  Line 8 
8   * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.   * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
9   */   */
10    
11  #include "busybox.h"  #include "libbb.h"
12    
13  #define DONT_SET_PASS (1 << 4)  #define OPT_DONT_SET_PASS  (1 << 4)
14  #define DONT_MAKE_HOME (1 << 6)  #define OPT_SYSTEM_ACCOUNT (1 << 5)
15    #define OPT_DONT_MAKE_HOME (1 << 6)
16    
17    
18  /* remix */  /* remix */
19  /* EDR recoded such that the uid may be passed in *p */  /* recoded such that the uid may be passed in *p */
20  static int passwd_study(const char *filename, struct passwd *p)  static void passwd_study(struct passwd *p)
21  {  {
22   struct passwd *pw;   int max;
  FILE *passwd;  
23    
24   const int min = 500;   if (getpwnam(p->pw_name))
25   const int max = 65000;   bb_error_msg_and_die("login '%s' is in use", p->pw_name);
26    
27   passwd = xfopen(filename, "r");   if (option_mask32 & OPT_SYSTEM_ACCOUNT) {
28     p->pw_uid = 0;
29   /* EDR if uid is out of bounds, set to min */   max = 999;
30   if ((p->pw_uid > max) || (p->pw_uid < min))   } else {
31   p->pw_uid = min;   p->pw_uid = 1000;
32     max = 64999;
  /* stuff to do:  
  * make sure login isn't taken;  
  * find free uid and gid;  
  */  
  while ((pw = fgetpwent(passwd))) {  
  if (strcmp(pw->pw_name, p->pw_name) == 0) {  
  /* return 0; */  
  return 1;  
  }  
  if ((pw->pw_uid >= p->pw_uid) && (pw->pw_uid < max)  
  && (pw->pw_uid >= min)) {  
  p->pw_uid = pw->pw_uid + 1;  
  }  
33   }   }
34    
35   if (p->pw_gid == 0) {   /* check for a free uid (and maybe gid) */
36   /* EDR check for an already existing gid */   while (getpwuid(p->pw_uid) || (!p->pw_gid && getgrgid(p->pw_uid)))
37   while (getgrgid(p->pw_uid) != NULL)   p->pw_uid++;
  p->pw_uid++;  
   
  /* EDR also check for an existing group definition */  
  if (getgrnam(p->pw_name) != NULL)  
  return 3;  
38    
39   /* EDR create new gid always = uid */   if (!p->pw_gid) {
40     /* new gid = uid */
41   p->pw_gid = p->pw_uid;   p->pw_gid = p->pw_uid;
42     if (getgrnam(p->pw_name))
43     bb_error_msg_and_die("group name '%s' is in use", p->pw_name);
44   }   }
45    
46   /* EDR bounds check */   if (p->pw_uid > max)
47   if ((p->pw_uid > max) || (p->pw_uid < min))   bb_error_msg_and_die("no free uids left");
  return 2;  
   
  /* return 1; */  
  return 0;  
48  }  }
49    
50  static void addgroup_wrapper(struct passwd *p)  static void addgroup_wrapper(struct passwd *p)
51  {  {
52   char *cmd;   char *cmd;
53    
54   cmd = xasprintf("addgroup -g %d \"%s\"", p->pw_gid, p->pw_name);   cmd = xasprintf("addgroup -g %u '%s'", (unsigned)p->pw_gid, p->pw_name);
55   system(cmd);   system(cmd);
56   free(cmd);   free(cmd);
57  }  }
58    
59  static void passwd_wrapper(const char *login) ATTRIBUTE_NORETURN;  static void passwd_wrapper(const char *login) NORETURN;
60    
61  static void passwd_wrapper(const char *login)  static void passwd_wrapper(const char *login)
62  {  {
63   static const char prog[] = "passwd";   static const char prog[] ALIGN1 = "passwd";
64   execlp(prog, prog, login, NULL);  
65   bb_error_msg_and_die("failed to execute '%s', you must set the password for '%s' manually", prog, login);   BB_EXECLP(prog, prog, login, NULL);
66     bb_error_msg_and_die("cannot execute %s, you must set password manually", prog);
67  }  }
68    
69  /* putpwent(3) remix */  #if ENABLE_FEATURE_ADDUSER_LONG_OPTIONS
70  static int adduser(struct passwd *p, unsigned long flags)  static const char adduser_longopts[] ALIGN1 =
71     "home\0"                Required_argument "h"
72     "gecos\0"               Required_argument "g"
73     "shell\0"               Required_argument "s"
74     "ingroup\0"             Required_argument "G"
75     "disabled-password\0"   No_argument       "D"
76     "empty-password\0"      No_argument       "D"
77     "system\0"              No_argument       "S"
78     "no-create-home\0"      No_argument       "H"
79     ;
80    #endif
81    
82    /*
83     * adduser will take a login_name as its first parameter.
84     * home, shell, gecos:
85     * can be customized via command-line parameters.
86     */
87    int adduser_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
88    int adduser_main(int argc UNUSED_PARAM, char **argv)
89  {  {
90     struct passwd pw;
91     const char *usegroup = NULL;
92   FILE *file;   FILE *file;
  int addgroup = !p->pw_gid;  
93    
94   /* make sure everything is kosher and setup uid && gid */  #if ENABLE_FEATURE_ADDUSER_LONG_OPTIONS
95   file = xfopen(bb_path_passwd_file, "a");   applet_long_options = adduser_longopts;
96   fseek(file, 0, SEEK_END);  #endif
97    
98     /* got root? */
99     if (geteuid()) {
100     bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
101     }
102    
103     pw.pw_gecos = (char *)"Linux User,,,";
104     pw.pw_shell = (char *)DEFAULT_SHELL;
105     pw.pw_dir = NULL;
106    
107     /* exactly one non-option arg */
108     opt_complementary = "=1";
109     getopt32(argv, "h:g:s:G:DSH", &pw.pw_dir, &pw.pw_gecos, &pw.pw_shell, &usegroup);
110     argv += optind;
111    
112     /* fill in the passwd struct */
113     pw.pw_name = argv[0];
114     die_if_bad_username(pw.pw_name);
115     if (!pw.pw_dir) {
116     /* create string for $HOME if not specified already */
117     pw.pw_dir = xasprintf("/home/%s", argv[0]);
118     }
119     pw.pw_passwd = (char *)"x";
120     pw.pw_gid = usegroup ? xgroup2gid(usegroup) : 0; /* exits on failure */
121    
122   switch (passwd_study(bb_path_passwd_file, p)) {   /* make sure everything is kosher and setup uid && maybe gid */
123   case 1:   passwd_study(&pw);
  bb_error_msg_and_die("%s: login already in use", p->pw_name);  
  case 2:  
  bb_error_msg_and_die("illegal uid or no uids left");  
  case 3:  
  bb_error_msg_and_die("%s: group name already in use", p->pw_name);  
  }  
124    
125   /* add to passwd */   /* add to passwd */
126   if (putpwent(p, file) == -1) {   file = xfopen(bb_path_passwd_file, "a");
127     //fseek(file, 0, SEEK_END); /* paranoia, "a" should ensure that anyway */
128     if (putpwent(&pw, file) != 0) {
129   bb_perror_nomsg_and_die();   bb_perror_nomsg_and_die();
130   }   }
131     /* do fclose even if !ENABLE_FEATURE_CLEAN_UP.
132     * We will exec passwd, files must be flushed & closed before that! */
133   fclose(file);   fclose(file);
134    
135  #if ENABLE_FEATURE_SHADOWPASSWDS  #if ENABLE_FEATURE_SHADOWPASSWDS
136   /* add to shadow if necessary */   /* add to shadow if necessary */
137   file = xfopen(bb_path_shadow_file, "a");   file = fopen_or_warn(bb_path_shadow_file, "a");
138   fseek(file, 0, SEEK_END);   if (file) {
139   fprintf(file, "%s:!:%ld:%d:%d:%d:::\n",   //fseek(file, 0, SEEK_END);
140   p->pw_name,             /* username */   fprintf(file, "%s:!:%u:0:99999:7:::\n",
141   time(NULL) / 86400,     /* sp->sp_lstchg */   pw.pw_name,             /* username */
142   0,                      /* sp->sp_min */   (unsigned)(time(NULL) / 86400) /* sp->sp_lstchg */
143   99999,                  /* sp->sp_max */   /*0,*/                  /* sp->sp_min */
144   7);                     /* sp->sp_warn */   /*99999,*/              /* sp->sp_max */
145   fclose(file);   /*7*/                   /* sp->sp_warn */
146     );
147     fclose(file);
148     }
149  #endif  #endif
150    
151   /* add to group */   /* add to group */
152   /* addgroup should be responsible for dealing w/ gshadow */   /* addgroup should be responsible for dealing w/ gshadow */
153   /* if using a pre-existing group, don't create one */   /* if using a pre-existing group, don't create one */
154   if (addgroup) addgroup_wrapper(p);   if (!usegroup)
155     addgroup_wrapper(&pw);
156    
157   /* Clear the umask for this process so it doesn't   /* Clear the umask for this process so it doesn't
158   * * screw up the permissions on the mkdir and chown. */   * screw up the permissions on the mkdir and chown. */
159   umask(0);   umask(0);
160   if (!(flags & DONT_MAKE_HOME)) {   if (!(option_mask32 & OPT_DONT_MAKE_HOME)) {
161   /* Set the owner and group so it is owned by the new user,   /* Set the owner and group so it is owned by the new user,
162     then fix up the permissions to 2755. Can't do it before     then fix up the permissions to 2755. Can't do it before
163     since chown will clear the setgid bit */     since chown will clear the setgid bit */
164   if (mkdir(p->pw_dir, 0755)   if (mkdir(pw.pw_dir, 0755)
165   || chown(p->pw_dir, p->pw_uid, p->pw_gid)   || chown(pw.pw_dir, pw.pw_uid, pw.pw_gid)
166   || chmod(p->pw_dir, 02755)) {   || chmod(pw.pw_dir, 02755) /* set setgid bit on homedir */
167   bb_perror_msg("%s", p->pw_dir);   ) {
168     bb_simple_perror_msg(pw.pw_dir);
169   }   }
170   }   }
171    
172   if (!(flags & DONT_SET_PASS)) {   if (!(option_mask32 & OPT_DONT_SET_PASS)) {
173   /* interactively set passwd */   /* interactively set passwd */
174   passwd_wrapper(p->pw_name);   passwd_wrapper(pw.pw_name);
175   }   }
176    
177   return 0;   return 0;
178  }  }
   
 /*  
  * adduser will take a login_name as its first parameter.  
  *  
  * home  
  * shell  
  * gecos  
  *  
  * can be customized via command-line parameters.  
  */  
 int adduser_main(int argc, char **argv)  
 {  
  struct passwd pw;  
  const char *usegroup = NULL;  
  unsigned long flags;  
   
  /* got root? */  
  if (geteuid()) {  
  bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);  
  }  
   
  pw.pw_gecos = "Linux User,,,";  
  pw.pw_shell = (char *)DEFAULT_SHELL;  
  pw.pw_dir = NULL;  
   
  /* check for min, max and missing args and exit on error */  
  opt_complementary = "-1:?1:?";  
  flags = getopt32(argc, argv, "h:g:s:G:DSH", &pw.pw_dir, &pw.pw_gecos, &pw.pw_shell, &usegroup);  
   
  /* create string for $HOME if not specified already */  
  if (!pw.pw_dir) {  
  snprintf(bb_common_bufsiz1, BUFSIZ, "/home/%s", argv[optind]);  
  pw.pw_dir = bb_common_bufsiz1;  
  }  
   
  /* create a passwd struct */  
  pw.pw_name = argv[optind];  
  pw.pw_passwd = "x";  
  pw.pw_uid = 0;  
  pw.pw_gid = usegroup ? xgroup2gid(usegroup) : 0; /* exits on failure */  
   
  /* grand finale */  
  return adduser(&pw, flags);  
 }  

Legend:
Removed from v.532  
changed lines
  Added in v.816