pw_user.c (5e779680a9ad885a3d749047f205b08e4506bf23) | pw_user.c (1dcc6ec750ce84c42fee6fb29a88c20b3b91f4ed) |
---|---|
1/*- 2 * Copyright (C) 1996 3 * David L. Nugent. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 8 unchanged lines hidden (view full) --- 17 * ARE DISCLAIMED. IN NO EVENT SHALL DAVID L. NUGENT OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. | 1/*- 2 * Copyright (C) 1996 3 * David L. Nugent. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 8 unchanged lines hidden (view full) --- 17 * ARE DISCLAIMED. IN NO EVENT SHALL DAVID L. NUGENT OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. |
25 * 26 * $Id: pw_user.c,v 1.21 1997/06/14 00:23:49 ache Exp $ | |
27 */ 28 | 25 */ 26 |
29#include <unistd.h> 30#include <fcntl.h> | 27#ifndef lint 28static const char rcsid[] = 29 "$Id$"; 30#endif /* not lint */ 31 |
31#include <ctype.h> | 32#include <ctype.h> |
32#include <paths.h> | 33#include <err.h> 34#include <fcntl.h> |
33#include <sys/param.h> 34#include <dirent.h> | 35#include <sys/param.h> 36#include <dirent.h> |
37#include <paths.h> |
|
35#include <termios.h> 36#include <sys/types.h> 37#include <sys/time.h> 38#include <sys/resource.h> | 38#include <termios.h> 39#include <sys/types.h> 40#include <sys/time.h> 41#include <sys/resource.h> |
42#include <unistd.h> |
|
39#include <utmp.h> 40#if defined(USE_MD5RAND) 41#include <md5.h> 42#endif 43#include "pw.h" 44#include "bitmap.h" 45#include "pwupd.h" 46 --- 103 unchanged lines hidden (view full) --- 150 */ 151 if (arg != NULL || getarg(args, 'm') != NULL) { 152 int l = strlen(cnf->home); 153 154 if (l > 1 && cnf->home[l-1] == '/') /* Shave off any trailing path delimiter */ 155 cnf->home[--l] = '\0'; 156 157 if (l < 2 || *cnf->home != '/') /* Check for absolute path name */ | 43#include <utmp.h> 44#if defined(USE_MD5RAND) 45#include <md5.h> 46#endif 47#include "pw.h" 48#include "bitmap.h" 49#include "pwupd.h" 50 --- 103 unchanged lines hidden (view full) --- 154 */ 155 if (arg != NULL || getarg(args, 'm') != NULL) { 156 int l = strlen(cnf->home); 157 158 if (l > 1 && cnf->home[l-1] == '/') /* Shave off any trailing path delimiter */ 159 cnf->home[--l] = '\0'; 160 161 if (l < 2 || *cnf->home != '/') /* Check for absolute path name */ |
158 cmderr(EX_DATAERR, "invalid base directory for home '%s'\n", cnf->home); | 162 errx(EX_DATAERR, "invalid base directory for home '%s'", cnf->home); |
159 160 if (stat(cnf->home, &st) == -1) { 161 char dbuf[MAXPATHLEN]; 162 163 /* 164 * This is a kludge especially for Joerg :) 165 * If the home directory would be created in the root partition, then 166 * we really create it under /usr which is likely to have more space. --- 13 unchanged lines hidden (view full) --- 180 if (stat(dbuf, &st) == -1) { 181 while ((p = strchr(++p, '/')) != NULL) { 182 *p = '\0'; 183 if (stat(dbuf, &st) == -1) { 184 if (mkdir(dbuf, 0755) == -1) 185 goto direrr; 186 chown(dbuf, 0, 0); 187 } else if (!S_ISDIR(st.st_mode)) | 163 164 if (stat(cnf->home, &st) == -1) { 165 char dbuf[MAXPATHLEN]; 166 167 /* 168 * This is a kludge especially for Joerg :) 169 * If the home directory would be created in the root partition, then 170 * we really create it under /usr which is likely to have more space. --- 13 unchanged lines hidden (view full) --- 184 if (stat(dbuf, &st) == -1) { 185 while ((p = strchr(++p, '/')) != NULL) { 186 *p = '\0'; 187 if (stat(dbuf, &st) == -1) { 188 if (mkdir(dbuf, 0755) == -1) 189 goto direrr; 190 chown(dbuf, 0, 0); 191 } else if (!S_ISDIR(st.st_mode)) |
188 cmderr(EX_OSFILE, "'%s' (root home parent) is not a directory\n", dbuf); | 192 errx(EX_OSFILE, "'%s' (root home parent) is not a directory", dbuf); |
189 *p = '/'; 190 } 191 } 192 if (stat(dbuf, &st) == -1) { 193 if (mkdir(dbuf, 0755) == -1) { | 193 *p = '/'; 194 } 195 } 196 if (stat(dbuf, &st) == -1) { 197 if (mkdir(dbuf, 0755) == -1) { |
194 direrr: cmderr(EX_OSFILE, "mkdir '%s': %s\n", dbuf, strerror(errno)); | 198 direrr: err(EX_OSFILE, "mkdir '%s'", dbuf); |
195 } 196 chown(dbuf, 0, 0); 197 } 198 } else if (!S_ISDIR(st.st_mode)) | 199 } 200 chown(dbuf, 0, 0); 201 } 202 } else if (!S_ISDIR(st.st_mode)) |
199 cmderr(EX_OSFILE, "root home `%s' is not a directory\n", cnf->home); | 203 errx(EX_OSFILE, "root home `%s' is not a directory", cnf->home); |
200 } 201 202 203 if ((arg = getarg(args, 'e')) != NULL) 204 cnf->expire_days = atoi(arg->val); 205 206 if ((arg = getarg(args, 'y')) != NULL) 207 cnf->nispasswd = arg->val; 208 209 if ((arg = getarg(args, 'p')) != NULL && arg->val) 210 cnf->password_days = atoi(arg->val); 211 212 if ((arg = getarg(args, 'g')) != NULL) { 213 p = arg->val; 214 if ((grp = getgrnam(p)) == NULL) { 215 if (!isdigit(*p) || (grp = getgrgid((gid_t) atoi(p))) == NULL) | 204 } 205 206 207 if ((arg = getarg(args, 'e')) != NULL) 208 cnf->expire_days = atoi(arg->val); 209 210 if ((arg = getarg(args, 'y')) != NULL) 211 cnf->nispasswd = arg->val; 212 213 if ((arg = getarg(args, 'p')) != NULL && arg->val) 214 cnf->password_days = atoi(arg->val); 215 216 if ((arg = getarg(args, 'g')) != NULL) { 217 p = arg->val; 218 if ((grp = getgrnam(p)) == NULL) { 219 if (!isdigit(*p) || (grp = getgrgid((gid_t) atoi(p))) == NULL) |
216 cmderr(EX_NOUSER, "group `%s' does not exist\n", p); | 220 errx(EX_NOUSER, "group `%s' does not exist", p); |
217 } 218 cnf->default_group = newstr(grp->gr_name); 219 } 220 if ((arg = getarg(args, 'L')) != NULL) 221 cnf->default_class = pw_checkname((u_char *)arg->val, 0); 222 223 if ((arg = getarg(args, 'G')) != NULL && arg->val) { 224 int i = 0; 225 226 for (p = strtok(arg->val, ", \t"); p != NULL; p = strtok(NULL, ", \t")) { 227 if ((grp = getgrnam(p)) == NULL) { 228 if (!isdigit(*p) || (grp = getgrgid((gid_t) atoi(p))) == NULL) | 221 } 222 cnf->default_group = newstr(grp->gr_name); 223 } 224 if ((arg = getarg(args, 'L')) != NULL) 225 cnf->default_class = pw_checkname((u_char *)arg->val, 0); 226 227 if ((arg = getarg(args, 'G')) != NULL && arg->val) { 228 int i = 0; 229 230 for (p = strtok(arg->val, ", \t"); p != NULL; p = strtok(NULL, ", \t")) { 231 if ((grp = getgrnam(p)) == NULL) { 232 if (!isdigit(*p) || (grp = getgrgid((gid_t) atoi(p))) == NULL) |
229 cmderr(EX_NOUSER, "group `%s' does not exist\n", p); | 233 errx(EX_NOUSER, "group `%s' does not exist", p); |
230 } 231 if (extendarray(&cnf->groups, &cnf->numgroups, i + 2) != -1) 232 cnf->groups[i++] = newstr(grp->gr_name); 233 } 234 while (i < cnf->numgroups) 235 cnf->groups[i++] = NULL; 236 } 237 if ((arg = getarg(args, 'k')) != NULL) { 238 if (stat(cnf->dotdir = arg->val, &st) == -1 || !S_ISDIR(st.st_mode)) | 234 } 235 if (extendarray(&cnf->groups, &cnf->numgroups, i + 2) != -1) 236 cnf->groups[i++] = newstr(grp->gr_name); 237 } 238 while (i < cnf->numgroups) 239 cnf->groups[i++] = NULL; 240 } 241 if ((arg = getarg(args, 'k')) != NULL) { 242 if (stat(cnf->dotdir = arg->val, &st) == -1 || !S_ISDIR(st.st_mode)) |
239 cmderr(EX_OSFILE, "skeleton `%s' is not a directory or does not exist\n", cnf->dotdir); | 243 errx(EX_OSFILE, "skeleton `%s' is not a directory or does not exist", cnf->dotdir); |
240 } 241 if ((arg = getarg(args, 's')) != NULL) 242 cnf->shell_default = arg->val; 243 244 if (mode == M_ADD && getarg(args, 'D')) { 245 if (getarg(args, 'n') != NULL) | 244 } 245 if ((arg = getarg(args, 's')) != NULL) 246 cnf->shell_default = arg->val; 247 248 if (mode == M_ADD && getarg(args, 'D')) { 249 if (getarg(args, 'n') != NULL) |
246 cmderr(EX_DATAERR, "can't combine `-D' with `-n name'\n"); | 250 errx(EX_DATAERR, "can't combine `-D' with `-n name'"); |
247 if ((arg = getarg(args, 'u')) != NULL && (p = strtok(arg->val, ", \t")) != NULL) { 248 if ((cnf->min_uid = (uid_t) atoi(p)) == 0) 249 cnf->min_uid = 1000; 250 if ((p = strtok(NULL, " ,\t")) == NULL || (cnf->max_uid = (uid_t) atoi(p)) < cnf->min_uid) 251 cnf->max_uid = 32000; 252 } 253 if ((arg = getarg(args, 'i')) != NULL && (p = strtok(arg->val, ", \t")) != NULL) { 254 if ((cnf->min_gid = (gid_t) atoi(p)) == 0) 255 cnf->min_gid = 1000; 256 if ((p = strtok(NULL, " ,\t")) == NULL || (cnf->max_gid = (gid_t) atoi(p)) < cnf->min_gid) 257 cnf->max_gid = 32000; 258 } 259 if ((arg = getarg(args, 'w')) != NULL) 260 cnf->default_password = boolean_val(arg->val, cnf->default_password); 261 262 arg = getarg(args, 'C'); 263 if (write_userconfig(arg ? arg->val : NULL)) 264 return EXIT_SUCCESS; | 251 if ((arg = getarg(args, 'u')) != NULL && (p = strtok(arg->val, ", \t")) != NULL) { 252 if ((cnf->min_uid = (uid_t) atoi(p)) == 0) 253 cnf->min_uid = 1000; 254 if ((p = strtok(NULL, " ,\t")) == NULL || (cnf->max_uid = (uid_t) atoi(p)) < cnf->min_uid) 255 cnf->max_uid = 32000; 256 } 257 if ((arg = getarg(args, 'i')) != NULL && (p = strtok(arg->val, ", \t")) != NULL) { 258 if ((cnf->min_gid = (gid_t) atoi(p)) == 0) 259 cnf->min_gid = 1000; 260 if ((p = strtok(NULL, " ,\t")) == NULL || (cnf->max_gid = (gid_t) atoi(p)) < cnf->min_gid) 261 cnf->max_gid = 32000; 262 } 263 if ((arg = getarg(args, 'w')) != NULL) 264 cnf->default_password = boolean_val(arg->val, cnf->default_password); 265 266 arg = getarg(args, 'C'); 267 if (write_userconfig(arg ? arg->val : NULL)) 268 return EXIT_SUCCESS; |
265 perror("config update"); | 269 warn("config update"); |
266 return EX_IOERR; 267 } 268 if (mode == M_PRINT && getarg(args, 'a')) { 269 int pretty = getarg(args, 'P') != NULL; 270 271 setpwent(); 272 while ((pwd = getpwent()) != NULL) 273 print_user(pwd, pretty); 274 endpwent(); 275 return EXIT_SUCCESS; 276 } 277 if ((a_name = getarg(args, 'n')) != NULL) 278 pwd = getpwnam(pw_checkname((u_char *)a_name->val, 0)); 279 a_uid = getarg(args, 'u'); 280 281 if (a_uid == NULL) { 282 if (a_name == NULL) | 270 return EX_IOERR; 271 } 272 if (mode == M_PRINT && getarg(args, 'a')) { 273 int pretty = getarg(args, 'P') != NULL; 274 275 setpwent(); 276 while ((pwd = getpwent()) != NULL) 277 print_user(pwd, pretty); 278 endpwent(); 279 return EXIT_SUCCESS; 280 } 281 if ((a_name = getarg(args, 'n')) != NULL) 282 pwd = getpwnam(pw_checkname((u_char *)a_name->val, 0)); 283 a_uid = getarg(args, 'u'); 284 285 if (a_uid == NULL) { 286 if (a_name == NULL) |
283 cmderr(EX_DATAERR, "user name or id required\n"); | 287 errx(EX_DATAERR, "user name or id required"); |
284 285 /* 286 * Determine whether 'n' switch is name or uid - we don't 287 * really don't really care which we have, but we need to 288 * know. 289 */ 290 if (mode != M_ADD && pwd == NULL && isdigit(*a_name->val) && atoi(a_name->val) > 0) { /* Assume uid */ 291 (a_uid = a_name)->ch = 'u'; --- 9 unchanged lines hidden (view full) --- 301 302 if (pwd == NULL) { 303 if (mode == M_PRINT && getarg(args, 'F')) { 304 fakeuser.pw_name = a_name ? a_name->val : "nouser"; 305 fakeuser.pw_uid = a_uid ? (uid_t) atol(a_uid->val) : -1; 306 return print_user(&fakeuser, getarg(args, 'P') != NULL); 307 } 308 if (a_name == NULL) | 288 289 /* 290 * Determine whether 'n' switch is name or uid - we don't 291 * really don't really care which we have, but we need to 292 * know. 293 */ 294 if (mode != M_ADD && pwd == NULL && isdigit(*a_name->val) && atoi(a_name->val) > 0) { /* Assume uid */ 295 (a_uid = a_name)->ch = 'u'; --- 9 unchanged lines hidden (view full) --- 305 306 if (pwd == NULL) { 307 if (mode == M_PRINT && getarg(args, 'F')) { 308 fakeuser.pw_name = a_name ? a_name->val : "nouser"; 309 fakeuser.pw_uid = a_uid ? (uid_t) atol(a_uid->val) : -1; 310 return print_user(&fakeuser, getarg(args, 'P') != NULL); 311 } 312 if (a_name == NULL) |
309 cmderr(EX_NOUSER, "no such uid `%s'\n", a_uid->val); 310 cmderr(EX_NOUSER, "no such user `%s'\n", a_name->val); | 313 errx(EX_NOUSER, "no such uid `%s'", a_uid->val); 314 errx(EX_NOUSER, "no such user `%s'", a_name->val); |
311 } 312 if (a_name == NULL) /* May be needed later */ 313 a_name = addarg(args, 'n', newstr(pwd->pw_name)); 314 315 /* 316 * Handle deletions now 317 */ 318 if (mode == M_DELETE) { 319 char file[MAXPATHLEN]; 320 char home[MAXPATHLEN]; 321 uid_t uid = pwd->pw_uid; 322 323 if (strcmp(pwd->pw_name, "root") == 0) | 315 } 316 if (a_name == NULL) /* May be needed later */ 317 a_name = addarg(args, 'n', newstr(pwd->pw_name)); 318 319 /* 320 * Handle deletions now 321 */ 322 if (mode == M_DELETE) { 323 char file[MAXPATHLEN]; 324 char home[MAXPATHLEN]; 325 uid_t uid = pwd->pw_uid; 326 327 if (strcmp(pwd->pw_name, "root") == 0) |
324 cmderr(EX_DATAERR, "cannot remove user 'root'\n"); | 328 errx(EX_DATAERR, "cannot remove user 'root'"); |
325 326 /* 327 * Remove skey record from /etc/skeykeys 328 */ 329 330 rmskey(pwd->pw_name); 331 332 /* --- 8 unchanged lines hidden (view full) --- 341 * Save these for later, since contents of pwd may be 342 * invalidated by deletion 343 */ 344 sprintf(file, "%s/%s", _PATH_MAILDIR, pwd->pw_name); 345 strncpy(home, pwd->pw_dir, sizeof home); 346 home[sizeof home - 1] = '\0'; 347 348 if (!delpwent(pwd)) | 329 330 /* 331 * Remove skey record from /etc/skeykeys 332 */ 333 334 rmskey(pwd->pw_name); 335 336 /* --- 8 unchanged lines hidden (view full) --- 345 * Save these for later, since contents of pwd may be 346 * invalidated by deletion 347 */ 348 sprintf(file, "%s/%s", _PATH_MAILDIR, pwd->pw_name); 349 strncpy(home, pwd->pw_dir, sizeof home); 350 home[sizeof home - 1] = '\0'; 351 352 if (!delpwent(pwd)) |
349 cmderr(EX_IOERR, "Error updating passwd file: %s\n", strerror(errno)); | 353 err(EX_IOERR, "error updating passwd file"); |
350 351 if (cnf->nispasswd && *cnf->nispasswd=='/' && !delnispwent(cnf->nispasswd, a_name->val)) | 354 355 if (cnf->nispasswd && *cnf->nispasswd=='/' && !delnispwent(cnf->nispasswd, a_name->val)) |
352 perror("WARNING: NIS passwd update"); | 356 warn("WARNING: NIS passwd update"); |
353 354 editgroups(a_name->val, NULL); 355 356 pw_log(cnf, mode, W_USER, "%s(%ld) account removed", a_name->val, (long) uid); 357 358 /* 359 * Remove mail file 360 */ --- 20 unchanged lines hidden (view full) --- 381 } else if (mode == M_PRINT) 382 return print_user(pwd, getarg(args, 'P') != NULL); 383 384 /* 385 * The rest is edit code 386 */ 387 if ((arg = getarg(args, 'l')) != NULL) { 388 if (strcmp(pwd->pw_name, "root") == 0) | 357 358 editgroups(a_name->val, NULL); 359 360 pw_log(cnf, mode, W_USER, "%s(%ld) account removed", a_name->val, (long) uid); 361 362 /* 363 * Remove mail file 364 */ --- 20 unchanged lines hidden (view full) --- 385 } else if (mode == M_PRINT) 386 return print_user(pwd, getarg(args, 'P') != NULL); 387 388 /* 389 * The rest is edit code 390 */ 391 if ((arg = getarg(args, 'l')) != NULL) { 392 if (strcmp(pwd->pw_name, "root") == 0) |
389 cmderr(EX_DATAERR, "can't rename `root' account\n"); | 393 errx(EX_DATAERR, "can't rename `root' account"); |
390 pwd->pw_name = pw_checkname((u_char *)arg->val, 0); 391 } 392 if ((arg = getarg(args, 'u')) != NULL && isdigit(*arg->val)) { 393 pwd->pw_uid = (uid_t) atol(arg->val); 394 if (pwd->pw_uid != 0 && strcmp(pwd->pw_name, "root") == 0) | 394 pwd->pw_name = pw_checkname((u_char *)arg->val, 0); 395 } 396 if ((arg = getarg(args, 'u')) != NULL && isdigit(*arg->val)) { 397 pwd->pw_uid = (uid_t) atol(arg->val); 398 if (pwd->pw_uid != 0 && strcmp(pwd->pw_name, "root") == 0) |
395 cmderr(EX_DATAERR, "can't change uid of `root' account\n"); | 399 errx(EX_DATAERR, "can't change uid of `root' account"); |
396 if (pwd->pw_uid == 0 && strcmp(pwd->pw_name, "root") != 0) | 400 if (pwd->pw_uid == 0 && strcmp(pwd->pw_name, "root") != 0) |
397 fprintf(stderr, "WARNING: account `%s' will have a uid of 0 (superuser access!)\n", pwd->pw_name); | 401 warnx("WARNING: account `%s' will have a uid of 0 (superuser access!)", pwd->pw_name); |
398 } 399 if ((arg = getarg(args, 'g')) != NULL && pwd->pw_uid != 0) /* Already checked this */ 400 pwd->pw_gid = (gid_t) getgrnam(cnf->default_group)->gr_gid; 401 402 if ((arg = getarg(args, 'p')) != NULL) { 403 if (*arg->val == '\0' || strcmp(arg->val, "0") == 0) 404 pwd->pw_change = 0; 405 else { 406 time_t now = time(NULL); 407 time_t expire = parse_date(now, arg->val); 408 409 if (now == expire) | 402 } 403 if ((arg = getarg(args, 'g')) != NULL && pwd->pw_uid != 0) /* Already checked this */ 404 pwd->pw_gid = (gid_t) getgrnam(cnf->default_group)->gr_gid; 405 406 if ((arg = getarg(args, 'p')) != NULL) { 407 if (*arg->val == '\0' || strcmp(arg->val, "0") == 0) 408 pwd->pw_change = 0; 409 else { 410 time_t now = time(NULL); 411 time_t expire = parse_date(now, arg->val); 412 413 if (now == expire) |
410 cmderr(EX_DATAERR, "Invalid password change date `%s'\n", arg->val); | 414 errx(EX_DATAERR, "invalid password change date `%s'", arg->val); |
411 pwd->pw_change = expire; 412 } 413 } 414 if ((arg = getarg(args, 'e')) != NULL) { 415 if (*arg->val == '\0' || strcmp(arg->val, "0") == 0) 416 pwd->pw_expire = 0; 417 else { 418 time_t now = time(NULL); 419 time_t expire = parse_date(now, arg->val); 420 421 if (now == expire) | 415 pwd->pw_change = expire; 416 } 417 } 418 if ((arg = getarg(args, 'e')) != NULL) { 419 if (*arg->val == '\0' || strcmp(arg->val, "0") == 0) 420 pwd->pw_expire = 0; 421 else { 422 time_t now = time(NULL); 423 time_t expire = parse_date(now, arg->val); 424 425 if (now == expire) |
422 cmderr(EX_DATAERR, "Invalid account expiry date `%s'\n", arg->val); | 426 errx(EX_DATAERR, "invalid account expiry date `%s'", arg->val); |
423 pwd->pw_expire = expire; 424 } 425 } 426 if ((arg = getarg(args, 's')) != NULL) 427 pwd->pw_shell = shell_path(cnf->shelldir, cnf->shells, arg->val); 428 429 if (getarg(args, 'L')) 430 pwd->pw_class = cnf->default_class; 431 432 if ((arg = getarg(args, 'd')) != NULL) { 433 if (stat(pwd->pw_dir = arg->val, &st) == -1) { 434 if (getarg(args, 'm') == NULL && strcmp(pwd->pw_dir, "/nonexistent") != 0) | 427 pwd->pw_expire = expire; 428 } 429 } 430 if ((arg = getarg(args, 's')) != NULL) 431 pwd->pw_shell = shell_path(cnf->shelldir, cnf->shells, arg->val); 432 433 if (getarg(args, 'L')) 434 pwd->pw_class = cnf->default_class; 435 436 if ((arg = getarg(args, 'd')) != NULL) { 437 if (stat(pwd->pw_dir = arg->val, &st) == -1) { 438 if (getarg(args, 'm') == NULL && strcmp(pwd->pw_dir, "/nonexistent") != 0) |
435 fprintf(stderr, "WARNING: home `%s' does not exist\n", pwd->pw_dir); | 439 warnx("WARNING: home `%s' does not exist", pwd->pw_dir); |
436 } else if (!S_ISDIR(st.st_mode)) | 440 } else if (!S_ISDIR(st.st_mode)) |
437 fprintf(stderr, "WARNING: home `%s' is not a directory\n", pwd->pw_dir); | 441 warnx("WARNING: home `%s' is not a directory", pwd->pw_dir); |
438 } 439 440 if ((arg = getarg(args, 'w')) != NULL && getarg(args, 'h') == NULL) 441 pwd->pw_passwd = pw_password(cnf, args, pwd->pw_name); 442 443 } else { 444 if (a_name == NULL) /* Required */ | 442 } 443 444 if ((arg = getarg(args, 'w')) != NULL && getarg(args, 'h') == NULL) 445 pwd->pw_passwd = pw_password(cnf, args, pwd->pw_name); 446 447 } else { 448 if (a_name == NULL) /* Required */ |
445 cmderr(EX_DATAERR, "login name required\n"); | 449 errx(EX_DATAERR, "login name required"); |
446 else if ((pwd = getpwnam(a_name->val)) != NULL) /* Exists */ | 450 else if ((pwd = getpwnam(a_name->val)) != NULL) /* Exists */ |
447 cmderr(EX_DATAERR, "login name `%s' already exists\n", a_name->val); | 451 errx(EX_DATAERR, "login name `%s' already exists", a_name->val); |
448 449 /* 450 * Now, set up defaults for a new user 451 */ 452 pwd = &fakeuser; 453 pwd->pw_name = a_name->val; 454 pwd->pw_class = cnf->default_class ? cnf->default_class : ""; 455 pwd->pw_passwd = pw_password(cnf, args, pwd->pw_name); 456 pwd->pw_uid = pw_uidpolicy(cnf, args); 457 pwd->pw_gid = pw_gidpolicy(cnf, args, pwd->pw_name, (gid_t) pwd->pw_uid); 458 pwd->pw_change = pw_pwdpolicy(cnf, args); 459 pwd->pw_expire = pw_exppolicy(cnf, args); 460 pwd->pw_dir = pw_homepolicy(cnf, args, pwd->pw_name); 461 pwd->pw_shell = pw_shellpolicy(cnf, args, NULL); 462 463 if (pwd->pw_uid == 0 && strcmp(pwd->pw_name, "root") != 0) | 452 453 /* 454 * Now, set up defaults for a new user 455 */ 456 pwd = &fakeuser; 457 pwd->pw_name = a_name->val; 458 pwd->pw_class = cnf->default_class ? cnf->default_class : ""; 459 pwd->pw_passwd = pw_password(cnf, args, pwd->pw_name); 460 pwd->pw_uid = pw_uidpolicy(cnf, args); 461 pwd->pw_gid = pw_gidpolicy(cnf, args, pwd->pw_name, (gid_t) pwd->pw_uid); 462 pwd->pw_change = pw_pwdpolicy(cnf, args); 463 pwd->pw_expire = pw_exppolicy(cnf, args); 464 pwd->pw_dir = pw_homepolicy(cnf, args, pwd->pw_name); 465 pwd->pw_shell = pw_shellpolicy(cnf, args, NULL); 466 467 if (pwd->pw_uid == 0 && strcmp(pwd->pw_name, "root") != 0) |
464 fprintf(stderr, "WARNING: new account `%s' has a uid of 0 (superuser access!)\n", pwd->pw_name); | 468 warnx("WARNING: new account `%s' has a uid of 0 (superuser access!)", pwd->pw_name); |
465 } 466 467 /* 468 * Shared add/edit code 469 */ 470 if ((arg = getarg(args, 'c')) != NULL) 471 pwd->pw_gecos = pw_checkname((u_char *)arg->val, 1); 472 --- 21 unchanged lines hidden (view full) --- 494 } 495 b = read(fd, line, sizeof(line) - 1); 496 if (istty) { /* Restore state */ 497 tcsetattr(fd, TCSANOW, &t); 498 fputc('\n', stdout); 499 fflush(stdout); 500 } 501 if (b < 0) { | 469 } 470 471 /* 472 * Shared add/edit code 473 */ 474 if ((arg = getarg(args, 'c')) != NULL) 475 pwd->pw_gecos = pw_checkname((u_char *)arg->val, 1); 476 --- 21 unchanged lines hidden (view full) --- 498 } 499 b = read(fd, line, sizeof(line) - 1); 500 if (istty) { /* Restore state */ 501 tcsetattr(fd, TCSANOW, &t); 502 fputc('\n', stdout); 503 fflush(stdout); 504 } 505 if (b < 0) { |
502 perror("-h file descriptor"); | 506 warn("-h file descriptor"); |
503 return EX_IOERR; 504 } 505 line[b] = '\0'; 506 if ((p = strpbrk(line, " \t\r\n")) != NULL) 507 *p = '\0'; 508 if (!*line) | 507 return EX_IOERR; 508 } 509 line[b] = '\0'; 510 if ((p = strpbrk(line, " \t\r\n")) != NULL) 511 *p = '\0'; 512 if (!*line) |
509 cmderr(EX_DATAERR, "empty password read on file descriptor %d\n", fd); | 513 errx(EX_DATAERR, "empty password read on file descriptor %d", fd); |
510 pwd->pw_passwd = pw_pwcrypt(line); 511 } 512 } 513 514 /* 515 * Special case: -N only displays & exits 516 */ 517 if (getarg(args, 'N') != NULL) --- 6 unchanged lines hidden (view full) --- 524 r1 = addnispwent(cnf->nispasswd, pwd); 525 } else if (mode == M_UPDATE) { 526 r = chgpwent(a_name->val, pwd); 527 if (r && cnf->nispasswd && *cnf->nispasswd=='/') 528 r1 = chgnispwent(cnf->nispasswd, a_name->val, pwd); 529 } 530 531 if (!r) { | 514 pwd->pw_passwd = pw_pwcrypt(line); 515 } 516 } 517 518 /* 519 * Special case: -N only displays & exits 520 */ 521 if (getarg(args, 'N') != NULL) --- 6 unchanged lines hidden (view full) --- 528 r1 = addnispwent(cnf->nispasswd, pwd); 529 } else if (mode == M_UPDATE) { 530 r = chgpwent(a_name->val, pwd); 531 if (r && cnf->nispasswd && *cnf->nispasswd=='/') 532 r1 = chgnispwent(cnf->nispasswd, a_name->val, pwd); 533 } 534 535 if (!r) { |
532 perror("password update"); | 536 warn("password update"); |
533 return EX_IOERR; 534 } else if (!r1) { | 537 return EX_IOERR; 538 } else if (!r1) { |
535 perror("WARNING: NIS password update"); | 539 warn("WARNING: NIS password update"); |
536 /* Keep on trucking */ 537 } 538 539 /* 540 * Ok, user is created or changed - now edit group file 541 */ 542 543 if (mode == M_ADD || getarg(args, 'G') != NULL) 544 editgroups(pwd->pw_name, cnf->groups); 545 546 /* pwd may have been invalidated */ 547 if ((pwd = getpwnam(a_name->val)) == NULL) | 540 /* Keep on trucking */ 541 } 542 543 /* 544 * Ok, user is created or changed - now edit group file 545 */ 546 547 if (mode == M_ADD || getarg(args, 'G') != NULL) 548 editgroups(pwd->pw_name, cnf->groups); 549 550 /* pwd may have been invalidated */ 551 if ((pwd = getpwnam(a_name->val)) == NULL) |
548 cmderr(EX_NOUSER, "user '%s' disappeared during update\n", a_name->val); | 552 errx(EX_NOUSER, "user '%s' disappeared during update", a_name->val); |
549 550 grp = getgrgid(pwd->pw_gid); 551 pw_log(cnf, mode, W_USER, "%s(%ld):%s(%d):%s:%s:%s", 552 pwd->pw_name, (long) pwd->pw_uid, 553 grp ? grp->gr_name : "unknown", (long) (grp ? grp->gr_gid : -1), 554 pwd->pw_gecos, pwd->pw_dir, pwd->pw_shell); 555 556 /* --- 11 unchanged lines hidden (view full) --- 568 569 /* 570 * Send mail to the new user as well, if we are asked to 571 */ 572 if (cnf->newmail && *cnf->newmail && (fp = fopen(cnf->newmail, "r")) != NULL) { 573 FILE *pfp = popen(_PATH_SENDMAIL " -t", "w"); 574 575 if (pfp == NULL) | 553 554 grp = getgrgid(pwd->pw_gid); 555 pw_log(cnf, mode, W_USER, "%s(%ld):%s(%d):%s:%s:%s", 556 pwd->pw_name, (long) pwd->pw_uid, 557 grp ? grp->gr_name : "unknown", (long) (grp ? grp->gr_gid : -1), 558 pwd->pw_gecos, pwd->pw_dir, pwd->pw_shell); 559 560 /* --- 11 unchanged lines hidden (view full) --- 572 573 /* 574 * Send mail to the new user as well, if we are asked to 575 */ 576 if (cnf->newmail && *cnf->newmail && (fp = fopen(cnf->newmail, "r")) != NULL) { 577 FILE *pfp = popen(_PATH_SENDMAIL " -t", "w"); 578 579 if (pfp == NULL) |
576 perror("sendmail"); | 580 warn("sendmail"); |
577 else { 578 fprintf(pfp, "From: root\n" "To: %s\n" "Subject: Welcome!\n\n", pwd->pw_name); 579 while (fgets(line, sizeof(line), fp) != NULL) { 580 /* Do substitutions? */ 581 fputs(line, pfp); 582 } 583 pclose(pfp); 584 pw_log(cnf, mode, W_USER, "%s(%ld) new user mail sent", --- 25 unchanged lines hidden (view full) --- 610 611 /* 612 * Check the given uid, if any 613 */ 614 if (a_uid != NULL) { 615 uid = (uid_t) atol(a_uid->val); 616 617 if ((pwd = getpwuid(uid)) != NULL && getarg(args, 'o') == NULL) | 581 else { 582 fprintf(pfp, "From: root\n" "To: %s\n" "Subject: Welcome!\n\n", pwd->pw_name); 583 while (fgets(line, sizeof(line), fp) != NULL) { 584 /* Do substitutions? */ 585 fputs(line, pfp); 586 } 587 pclose(pfp); 588 pw_log(cnf, mode, W_USER, "%s(%ld) new user mail sent", --- 25 unchanged lines hidden (view full) --- 614 615 /* 616 * Check the given uid, if any 617 */ 618 if (a_uid != NULL) { 619 uid = (uid_t) atol(a_uid->val); 620 621 if ((pwd = getpwuid(uid)) != NULL && getarg(args, 'o') == NULL) |
618 cmderr(EX_DATAERR, "uid `%ld' has already been allocated\n", (long) pwd->pw_uid); | 622 errx(EX_DATAERR, "uid `%ld' has already been allocated", (long) pwd->pw_uid); |
619 } else { 620 struct bitmap bm; 621 622 /* 623 * We need to allocate the next available uid under one of 624 * two policies a) Grab the first unused uid b) Grab the 625 * highest possible unused uid 626 */ --- 18 unchanged lines hidden (view full) --- 645 */ 646 if (cnf->reuse_uids || (uid = (uid_t) (bm_lastset(&bm) + cnf->min_uid + 1)) > cnf->max_uid) 647 uid = (uid_t) (bm_firstunset(&bm) + cnf->min_uid); 648 649 /* 650 * Another sanity check 651 */ 652 if (uid < cnf->min_uid || uid > cnf->max_uid) | 623 } else { 624 struct bitmap bm; 625 626 /* 627 * We need to allocate the next available uid under one of 628 * two policies a) Grab the first unused uid b) Grab the 629 * highest possible unused uid 630 */ --- 18 unchanged lines hidden (view full) --- 649 */ 650 if (cnf->reuse_uids || (uid = (uid_t) (bm_lastset(&bm) + cnf->min_uid + 1)) > cnf->max_uid) 651 uid = (uid_t) (bm_firstunset(&bm) + cnf->min_uid); 652 653 /* 654 * Another sanity check 655 */ 656 if (uid < cnf->min_uid || uid > cnf->max_uid) |
653 cmderr(EX_SOFTWARE, "unable to allocate a new uid - range fully used\n"); | 657 errx(EX_SOFTWARE, "unable to allocate a new uid - range fully used"); |
654 bm_dealloc(&bm); 655 } 656 return uid; 657} 658 659 660static uid_t 661pw_gidpolicy(struct userconf * cnf, struct cargs * args, char *nam, gid_t prefer) --- 11 unchanged lines hidden (view full) --- 673 /* 674 * Check the given gid, if any 675 */ 676 setgrent(); 677 if (a_gid != NULL) { 678 if ((grp = getgrnam(a_gid->val)) == NULL) { 679 gid = (gid_t) atol(a_gid->val); 680 if ((gid == 0 && !isdigit(*a_gid->val)) || (grp = getgrgid(gid)) == NULL) | 658 bm_dealloc(&bm); 659 } 660 return uid; 661} 662 663 664static uid_t 665pw_gidpolicy(struct userconf * cnf, struct cargs * args, char *nam, gid_t prefer) --- 11 unchanged lines hidden (view full) --- 677 /* 678 * Check the given gid, if any 679 */ 680 setgrent(); 681 if (a_gid != NULL) { 682 if ((grp = getgrnam(a_gid->val)) == NULL) { 683 gid = (gid_t) atol(a_gid->val); 684 if ((gid == 0 && !isdigit(*a_gid->val)) || (grp = getgrgid(gid)) == NULL) |
681 cmderr(EX_NOUSER, "group `%s' is not defined\n", a_gid->val); | 685 errx(EX_NOUSER, "group `%s' is not defined", a_gid->val); |
682 } 683 gid = grp->gr_gid; 684 } else if ((grp = getgrnam(nam)) != NULL && grp->gr_mem[0] == NULL) { 685 gid = grp->gr_gid; /* Already created? Use it anyway... */ 686 } else { 687 struct cargs grpargs; 688 char tmp[32]; 689 --- 41 unchanged lines hidden (view full) --- 731pw_pwdpolicy(struct userconf * cnf, struct cargs * args) 732{ 733 time_t result = 0; 734 time_t now = time(NULL); 735 struct carg *arg = getarg(args, 'p'); 736 737 if (arg != NULL) { 738 if ((result = parse_date(now, arg->val)) == now) | 686 } 687 gid = grp->gr_gid; 688 } else if ((grp = getgrnam(nam)) != NULL && grp->gr_mem[0] == NULL) { 689 gid = grp->gr_gid; /* Already created? Use it anyway... */ 690 } else { 691 struct cargs grpargs; 692 char tmp[32]; 693 --- 41 unchanged lines hidden (view full) --- 735pw_pwdpolicy(struct userconf * cnf, struct cargs * args) 736{ 737 time_t result = 0; 738 time_t now = time(NULL); 739 struct carg *arg = getarg(args, 'p'); 740 741 if (arg != NULL) { 742 if ((result = parse_date(now, arg->val)) == now) |
739 cmderr(EX_DATAERR, "invalid date/time `%s'\n", arg->val); | 743 errx(EX_DATAERR, "invalid date/time `%s'", arg->val); |
740 } else if (cnf->password_days > 0) 741 result = now + ((long) cnf->password_days * 86400L); 742 return result; 743} 744 745 746static time_t 747pw_exppolicy(struct userconf * cnf, struct cargs * args) 748{ 749 time_t result = 0; 750 time_t now = time(NULL); 751 struct carg *arg = getarg(args, 'e'); 752 753 if (arg != NULL) { 754 if ((result = parse_date(now, arg->val)) == now) | 744 } else if (cnf->password_days > 0) 745 result = now + ((long) cnf->password_days * 86400L); 746 return result; 747} 748 749 750static time_t 751pw_exppolicy(struct userconf * cnf, struct cargs * args) 752{ 753 time_t result = 0; 754 time_t now = time(NULL); 755 struct carg *arg = getarg(args, 'e'); 756 757 if (arg != NULL) { 758 if ((result = parse_date(now, arg->val)) == now) |
755 cmderr(EX_DATAERR, "invalid date/time `%s'\n", arg->val); | 759 errx(EX_DATAERR, "invalid date/time `%s'", arg->val); |
756 } else if (cnf->expire_days > 0) 757 result = now + ((long) cnf->expire_days * 86400L); 758 return result; 759} 760 761 762static char * 763pw_homepolicy(struct userconf * cnf, struct cargs * args, char const * user) 764{ 765 struct carg *arg = getarg(args, 'd'); 766 767 if (arg) 768 return arg->val; 769 else { 770 static char home[128]; 771 772 if (cnf->home == NULL || *cnf->home == '\0') | 760 } else if (cnf->expire_days > 0) 761 result = now + ((long) cnf->expire_days * 86400L); 762 return result; 763} 764 765 766static char * 767pw_homepolicy(struct userconf * cnf, struct cargs * args, char const * user) 768{ 769 struct carg *arg = getarg(args, 'd'); 770 771 if (arg) 772 return arg->val; 773 else { 774 static char home[128]; 775 776 if (cnf->home == NULL || *cnf->home == '\0') |
773 cmderr(EX_CONFIG, "no base home directory set\n"); | 777 errx(EX_CONFIG, "no base home directory set"); |
774 sprintf(home, "%s/%s", cnf->home, user); 775 return home; 776 } 777} 778 779static char * 780shell_path(char const * path, char *shells[], char *sh) 781{ --- 19 unchanged lines hidden (view full) --- 801 } else 802 for (i = 0; i < _UC_MAXSHELLS && shells[i] != NULL; i++) { 803 sprintf(shellpath, "%s/%s", p, shells[i]); 804 if (access(shellpath, X_OK) == 0) 805 return shellpath; 806 } 807 } 808 if (sh == NULL) | 778 sprintf(home, "%s/%s", cnf->home, user); 779 return home; 780 } 781} 782 783static char * 784shell_path(char const * path, char *shells[], char *sh) 785{ --- 19 unchanged lines hidden (view full) --- 805 } else 806 for (i = 0; i < _UC_MAXSHELLS && shells[i] != NULL; i++) { 807 sprintf(shellpath, "%s/%s", p, shells[i]); 808 if (access(shellpath, X_OK) == 0) 809 return shellpath; 810 } 811 } 812 if (sh == NULL) |
809 cmderr(EX_OSFILE, "can't find shell `%s' in shell paths\n", sh); 810 cmderr(EX_CONFIG, "no default shell available or defined\n"); | 813 errx(EX_OSFILE, "can't find shell `%s' in shell paths", sh); 814 errx(EX_CONFIG, "no default shell available or defined"); |
811 return NULL; 812 } 813} 814 815 816static char * 817pw_shellpolicy(struct userconf * cnf, struct cargs * args, char *newshell) 818{ --- 217 unchanged lines hidden (view full) --- 1036{ 1037 int l = 0; 1038 char const *notch = gecos ? ":!@" : " ,\t:+&#%$^()!@~*?<>=|\\/\""; 1039 1040 while (name[l]) { 1041 if (strchr(notch, name[l]) != NULL || name[l] < ' ' || name[l] == 127 || 1042 (!gecos && l==0 && name[l] == '-') || /* leading '-' */ 1043 (!gecos && name[l] & 0x80)) /* 8-bit */ | 815 return NULL; 816 } 817} 818 819 820static char * 821pw_shellpolicy(struct userconf * cnf, struct cargs * args, char *newshell) 822{ --- 217 unchanged lines hidden (view full) --- 1040{ 1041 int l = 0; 1042 char const *notch = gecos ? ":!@" : " ,\t:+&#%$^()!@~*?<>=|\\/\""; 1043 1044 while (name[l]) { 1045 if (strchr(notch, name[l]) != NULL || name[l] < ' ' || name[l] == 127 || 1046 (!gecos && l==0 && name[l] == '-') || /* leading '-' */ 1047 (!gecos && name[l] & 0x80)) /* 8-bit */ |
1044 cmderr(EX_DATAERR, (name[l] >= ' ' && name[l] < 127) 1045 ? "invalid character `%c' in field\n" 1046 : "invalid character 0x%02x in field\n", | 1048 errx(EX_DATAERR, (name[l] >= ' ' && name[l] < 127) 1049 ? "invalid character `%c' in field" 1050 : "invalid character 0x%02x in field", |
1047 name[l]); 1048 ++l; 1049 } 1050 if (!gecos && l > LOGNAMESIZE) | 1051 name[l]); 1052 ++l; 1053 } 1054 if (!gecos && l > LOGNAMESIZE) |
1051 cmderr(EX_DATAERR, "name too long `%s'\n", name); | 1055 errx(EX_DATAERR, "name too long `%s'", name); |
1052 return (char *)name; 1053} 1054 1055 1056static void 1057rmat(uid_t uid) 1058{ 1059 DIR *d = opendir("/var/at/jobs"); --- 48 unchanged lines hidden --- | 1056 return (char *)name; 1057} 1058 1059 1060static void 1061rmat(uid_t uid) 1062{ 1063 DIR *d = opendir("/var/at/jobs"); --- 48 unchanged lines hidden --- |