📄 useradd.c
字号:
{ if (((expire = strtol (optarg, &cp, 10)) == 0 && *cp) || expire < -1) { fprintf (stderr, _("%s: Expiredate `%s' is no date and no integer value >= -1.\n"), program, optarg); return E_BAD_ARG; } } dflt.expire = expire; } break; case 'f': { long int inactive; char *cp; inactive = strtol (optarg, &cp, 10); if (*cp != '\0') /* invalid number */ { fprintf (stderr, _("%s: Invalid numeric argument `%s' for `-f'.\n"), program, optarg); return E_BAD_ARG; } dflt.inactive = inactive; } break; case 'G': /* Only save the arguments for later checking. We can find a -P <path> option later. */ new_groups_arg = optarg; break; case 'g': new_group = optarg; break; case 'k': if (access (optarg, F_OK) != 0) { fprintf (stderr, _("%s: Skel directory `%s' does not exist.\n"), program, optarg); return E_BAD_ARG; } skeldir = strdup (optarg); break; case 'M': /* This is the default: don't create users home dir. Ignored for RedHat/PLD useradd compatibility. */ break; case 'm': create_homedir = 1; break; case 'o': non_unique = 1; break; case 'P': files_etc_dir = strdup (optarg); have_extrapath = 1; /* If -P option is used, set use_service to "files" if not already set through an option. If we don't limitate to service files, we can get trouble finding the right source. */ if (!use_service) use_service = "files"; break; case 'p': /* set encrypted password */ if (strcspn (optarg, ":\n") != strlen (optarg)) { fprintf (stderr, _("%s: Invalid characters in password `%s'.\n"), program, optarg); return E_BAD_ARG; } new_password = optarg; break; case 'r': system_account = 1; break; case 's': if (strcspn (optarg, ",=\":*\n") != strlen (optarg) || *optarg != '/') { fprintf (stderr, _("%s: Invalid shell `%s'.\n"), program, optarg); return E_BAD_ARG; } new_shell = optarg; break; case 'u': if (strtoid (optarg, &new_uid) == -1) /* invalid number */ { fprintf (stderr, _("%s: Invalid numeric argument `%s' for User ID.\n"), program, optarg); return E_BAD_ARG; } know_uid = 1; break; case '\251': case '\252': if (!modify_defaults) { print_error (program); return E_USAGE; } break; case '\253': if (use_service != NULL) { print_usage (stderr, program); return E_BAD_ARG; } if (strcasecmp (optarg, "files") == 0) use_service = "files";#ifdef USE_LDAP else if (strcasecmp (optarg, "ldap") == 0) use_service = "ldap";#endif else { fprintf (stderr, _("Service `%s' not supported.\n"), optarg); print_usage (stderr, program); return E_BAD_ARG; } break; case '\255': print_help (program); return 0; case 'v': print_version (program, "2005"); return 0; case '\254': print_usage (stdout, program); return 0; default: print_error (program); return E_USAGE; } } if (new_group) { int retval; gid_t gid; if ((retval = convert_grpopt_to_name (new_group, NULL, &gid, use_service)) != 0) return retval; dflt.group = gid; } if (new_groups_arg) { char *arg = new_groups_arg; unsigned int errors = 0, i, j; j = 1; for (i = 0; i < strlen (arg); i++) if (arg[i] == ',') ++j; new_groups = malloc (sizeof (char *) * j); new_groupscnt = 0; do { char *cp = strchr (arg, ','); if (cp) *cp++ = '\0'; if (arg && *arg) { if (convert_grpopt_to_name (arg, &new_groups[new_groupscnt], NULL, use_service) != 0) ++errors; else { new_groupscnt++; if (new_groupscnt > j) abort (); } } arg = cp; } while (arg); if (errors) { /* XXX This is more a guess than something else. */ if (files_etc_dir) return E_NOTFOUND; else return E_BAD_ARG; } if (modify_defaults) { dflt.groupscnt = new_groupscnt; dflt.groups = new_groups; } } argc -= optind; argv += optind; if (argc > 1) { fprintf (stderr, _("%s: Too many arguments.\n"), program); print_error (program); return E_USAGE; } else if (argc == 0 && !modify_defaults) { fprintf (stderr, _("%s: Too few arguments.\n"), program); print_error (program); return E_USAGE; } else if (skeldir && !(create_homedir || modify_defaults)) { print_usage (stderr, program); return E_USAGE; } else { int buflen = 256; char *buffer = alloca (buflen); struct passwd resultbuf; struct passwd *pw; /* Determine our own user name for PAM authentication. */ while (getpwuid_r (getuid (), &resultbuf, buffer, buflen, &pw) != 0 && errno == ERANGE) { errno = 0; buflen += 256; buffer = alloca (buflen); } if (!pw) { sec_log (program, MSG_NO_ACCOUNT_FOUND, getuid ()); fprintf (stderr, _("%s: Cannot determine your user name.\n"), program); return E_UNKNOWN_USER; } if (do_authentication (program, pw->pw_name, NULL) != 0) { sec_log (program, MSG_PERMISSION_DENIED, pw->pw_name, pw->pw_uid, getuid ()); return E_NOPERM; } } if (modify_defaults) { /* -D option was given and we plan to modify entries in /etc/default/useradd. */ if (new_home) dflt.home = new_home; if (new_shell) dflt.shell = new_shell; if (skeldir) dflt.skel = skeldir; if (write_defaults (useradd_default_file, &dflt) != 0) { sec_log (program, MSG_UPDATING_DEFAULT_CONFIG_FAILED, useradd_default_file, getuid ()); fprintf (stderr, _("%s: Writing of `%s' was not successful.\n"), program, useradd_default_file); return E_LOGIN_DEFS; } sec_log (program, MSG_CONFIG_DEFAULTS_CHANGED, dflt.group, new_home, dflt.shell, dflt.inactive, date2str(DAY*dflt.expire), getuid ()); return E_SUCCESS; } /* After this, we can start creating the new account. */ if (know_uid && !non_unique) { if (getpwuid (new_uid) != NULL || (have_extrapath && files_getpwuid (new_uid) != NULL)) { sec_log (program, MSG_UID_NOT_UNIQUE, new_uid, getuid ()); fprintf (stderr, _("%s: UID %u is not unique.\n"), program, new_uid); return E_UID_IN_USE; } } new_account = argv[0]; if (check_name (new_account) != 0) { sec_log (program, MSG_USER_NAME_INVALID, new_account, getuid ()); fprintf (stderr, _("%s: Invalid account name `%s'.\n"), program, new_account); return E_BAD_ARG; } if (system_account && new_shell == NULL) new_shell = "/bin/false"; /* Lock passwd file, so that a concurrent useradd process will not add the user a second time or a second user with the same uid. */ if ((use_service == NULL || strcmp (use_service, "files") == 0) && lock_database () != 0) { sec_log (program, MSG_PASSWD_FILE_ALREADY_LOCKED); fputs (_("Cannot lock password file: already locked.\n"), stderr); return E_PWDBUSY; } else if (getpwnam (new_account) != NULL || (have_extrapath && files_getpwnam (new_account) != NULL)) { /* User does already exists. */ sec_log (program, MSG_USER_ALREADY_EXISTS, new_account, getuid ()); fprintf (stderr, _("%s: Account `%s' already exists.\n"), program, new_account); return E_NAME_IN_USE; } else { user_t pw_data; char homebuf[strlen (dflt.home) + strlen (new_account) + 2]; char shadowfile[strlen (files_etc_dir) + 8]; char *cp; unsigned int i; int retval = E_SUCCESS; memset (&pw_data, 0, sizeof (pw_data)); /* check if we have shadow support. */ cp = stpcpy (shadowfile, files_etc_dir); strcpy (cp, "/shadow"); pw_data.use_shadow = (access (shadowfile, F_OK) == 0); if (use_service) { if (strcmp (use_service, "files") == 0) pw_data.service = S_LOCAL; else if (strcmp (use_service, "ldap") == 0) pw_data.service = S_LDAP; } else pw_data.service = S_LOCAL; pw_data.todo = DO_CREATE; if (new_home == NULL) { snprintf (homebuf, sizeof (homebuf), "%s/%s", dflt.home, new_account); new_home = homebuf; } pw_data.pw.pw_name = new_account; if (pw_data.use_shadow) pw_data.pw.pw_passwd = "x"; else pw_data.pw.pw_passwd = new_password; pw_data.pw.pw_uid = know_uid ? new_uid : find_free_uid (system_account, have_extrapath); pw_data.pw.pw_gid = dflt.group; pw_data.pw.pw_gecos = new_comment; pw_data.pw.pw_dir = new_home; pw_data.pw.pw_shell = new_shell ? : dflt.shell; if (pw_data.use_shadow) { pw_data.sp.sp_namp = new_account; pw_data.sp.sp_pwdp = new_password; pw_data.sp.sp_lstchg = time ((time_t *) 0) / (24L * 3600L); pw_data.sp.sp_min = getlogindefs_num ("PASS_MIN_DAYS", -1); pw_data.sp.sp_max = getlogindefs_num ("PASS_MAX_DAYS", -1); pw_data.sp.sp_warn = getlogindefs_num ("PASS_WARN_AGE", -1); pw_data.sp.sp_inact = dflt.inactive; pw_data.sp.sp_expire = dflt.expire; pw_data.sp.sp_flag = -1; } sec_log (program, MSG_NEW_USER_ADDED, pw_data.pw.pw_name, (unsigned int) pw_data.pw.pw_uid, (unsigned int) pw_data.pw.pw_gid, pw_data.pw.pw_dir, pw_data.pw.pw_shell, getuid ()); /* Clear old log entries, but only if this UID is not shared with another account. */ if (getpwuid (pw_data.pw.pw_uid) == NULL && (!have_extrapath || files_getpwuid (pw_data.pw.pw_uid) == NULL)) { int fd; if ((fd = open ("/var/log/faillog", O_RDWR)) >= 0) { struct faillog fl; memset (&fl, 0, sizeof (fl)); if ((lseek (fd, (off_t) sizeof (fl) * pw_data.pw.pw_uid, SEEK_SET) == (off_t)-1) || (write (fd, &fl, sizeof (fl)) == -1)) fprintf (stderr, _("%s: Error: Cannot clear old faillog entry: %s\n"), program, strerror (errno)); close (fd); } if ((fd = open (_PATH_LASTLOG, O_RDWR, 0)) >= 0) { struct lastlog ll; memset (&ll, 0, sizeof (ll)); if ((lseek (fd, (off_t) sizeof (ll) * pw_data.pw.pw_uid, SEEK_SET) == (off_t)-1) || (write (fd, &ll, sizeof (ll)) == -1)) fprintf (stderr, _("%s: Error: Cannot clear old lastlog entry: %s\n"), program, strerror (errno)); close (fd); } }#ifdef USE_LDAP if (pw_data.service == S_LDAP) { if (binddn == NULL) { binddn = get_caller_dn (); if (binddn == NULL) { fprintf (stderr, _("%s: Cannot add user to LDAP database without DN.\n"), program); } else pw_data.binddn = strdup (binddn); } else pw_data.binddn = strdup (binddn); if (pw_data.oldclearpwd == NULL) { cp = get_ldap_password (pw_data.binddn); if (cp) pw_data.oldclearpwd = strdup (cp); else { fprintf (stderr, _("%s: User not added to LDAP database.\n"), program); return E_FAILURE; } } }#endif if (write_user_data (&pw_data, 1) != 0) return E_FAILURE; /* If user does not specify extra secondary groups, add the default one. With one exception: Don't add default extra groups to system accounts. */ if (new_groups == NULL && !system_account) { new_groupscnt = dflt.groupscnt; new_groups = dflt.groups; } for (i = 0; i < new_groupscnt; i++) { group_t *gr_data = find_group_data (new_groups[i], 0, use_service); if (gr_data == NULL || gr_data->service == S_NONE) { if (use_service == NULL) fprintf (stderr, _("%s: ERROR: Cannot find group `%s' anymore!\n"), program, new_groups[i]); else fprintf (stderr, _("%s: Cannot find group `%s' in service `%s', ignored.\n"), program, new_groups[i], use_service); retval = E_NOTFOUND; } else { gr_data->todo = DO_MODIFY;#ifdef USE_LDAP if (gr_data->service == S_LDAP) { if (binddn == NULL) { binddn = get_caller_dn (); if (binddn == NULL) { fprintf (stderr, _("%s: Cannot add user to groups stored in LDAP database without DN.\n"), program); } } if (binddn == NULL) { fprintf (stderr, _("%s: User not added to LDAP group `%s'.\n"), program, gr_data->gr.gr_name); free_group_t (gr_data); retval = E_GRP_UPDATE; continue; } gr_data->binddn = strdup (binddn); if (pw_data.oldclearpwd == NULL) { cp = get_ldap_password (binddn); if (cp) pw_data.oldclearpwd = strdup (cp); else { fprintf (stderr, _("%s: User not added to LDAP group `%s'.\n"), program, gr_data->gr.gr_name); free_group_t (gr_data); retval = E_GRP_UPDATE; continue; } } if (pw_data.oldclearpwd) gr_data->oldclearpwd = strdup (pw_data.oldclearpwd); }#endif gr_data->new_gr_mem = add_gr_mem (pw_data.pw.pw_name, gr_data->gr.gr_mem); if (write_group_data (gr_data, 1) != 0) { fprintf (stderr, _("%s: User not added to LDAP group `%s'.\n"), program, gr_data->gr.gr_name); retval = E_GRP_UPDATE; } else { sec_log (program, MSG_USER_ADDED_TO_GROUP, pw_data.pw.pw_name, gr_data->gr.gr_name, gr_data->gr.gr_gid, getuid ()); } } free_group_t (gr_data); }#ifdef HAVE_NSCD_FLUSH_CACHE /* flush NSCD cache, else creating of home directory could fail because of unknown user. */ nscd_flush_cache ("passwd"); nscd_flush_cache ("group");#endif if (use_service == NULL || strcmp (use_service, "files") == 0) ulckpwdf (); if (dflt.create_mail_spool) { int ret = create_mail_file (pw_data.pw.pw_name, pw_data.pw.pw_uid, pw_data.pw.pw_gid); if (ret != 0) return ret; sec_log (program, MSG_MAIL_FILE_CREATED, pw_data.pw.pw_name, getuid ()); } if (create_homedir) { int ret = create_home_directory (new_home, pw_data.pw.pw_uid, pw_data.pw.pw_gid, skeldir ? : dflt.skel); if (ret != 0) return ret; sec_log (program, MSG_HOME_DIR_CREATED, pw_data.pw.pw_name, pw_data.pw.pw_uid, new_home, getuid ()); } i = call_script ("USERADD_CMD", pw_data.pw.pw_name, pw_data.pw.pw_uid, pw_data.pw.pw_gid, pw_data.pw.pw_dir, program); if (i != 0) { fprintf (stderr, _("%s: USERADD_CMD fails with exit code %d.\n"), program, i); retval = E_FAILURE; } return retval; } return E_SUCCESS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -