Mercurial > illumos > illumos-gate
annotate usr/src/cmd/passwd/passwd.c @ 14136:9178198c46b5
4026 cleanup warnings in cmd/passwd
Reviewed by: Jason King <jason.brian.king@gmail.com>
Reviewed by: Cedric Blancher <cedric.blancher@gmail.com>
Reviewed by: Keith Wesolowski <keith.wesolowski@joyent.com>
Approved by: Robert Mustacchi <rm@joyent.com>
author | Igor Kozhukhov <ikozhukhov@gmail.com> |
---|---|
date | Tue, 13 Aug 2013 09:02:40 -0700 |
parents | f6cca4323de0 |
children |
rev | line source |
---|---|
0 | 1 /* |
2 * CDDL HEADER START | |
3 * | |
4 * The contents of this file are subject to the terms of the | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
5 * Common Development and Distribution License (the "License"). |
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
6 * You may not use this file except in compliance with the License. |
0 | 7 * |
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE | |
9 * or http://www.opensolaris.org/os/licensing. | |
10 * See the License for the specific language governing permissions | |
11 * and limitations under the License. | |
12 * | |
13 * When distributing Covered Code, include this CDDL HEADER in each | |
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. | |
15 * If applicable, add the following below this CDDL HEADER, with the | |
16 * fields enclosed by brackets "[]" replaced with your own identifying | |
17 * information: Portions Copyright [yyyy] [name of copyright owner] | |
18 * | |
19 * CDDL HEADER END | |
20 */ | |
21 /* | |
11893
ff6e80260186
6914628 Implement the user object audit token PSARC/2010/001 User object audit token
gww <gww@eng.sun.com>
parents:
11262
diff
changeset
|
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. |
0 | 23 * Use is subject to license terms. |
24 */ | |
25 | |
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ | |
27 /* All Rights Reserved */ | |
28 | |
29 /* Copyright (c) 1987, 1988 Microsoft Corporation */ | |
30 /* All Rights Reserved */ | |
31 | |
32 /* | |
33 * passwd is a program whose sole purpose is to manage | |
34 * the password file, map, or table. It allows system administrator | |
35 * to add, change and display password attributes. | |
36 * Non privileged user can change password or display | |
37 * password attributes which corresponds to their login name. | |
38 */ | |
39 | |
40 #include <stdio.h> | |
41 #include <pwd.h> | |
42 #include <sys/types.h> | |
43 #include <errno.h> | |
44 #include <unistd.h> | |
45 #include <stdlib.h> | |
46 #include <locale.h> | |
47 #include <stdarg.h> | |
48 #include <errno.h> | |
49 #include <string.h> | |
50 #include <security/pam_appl.h> | |
51 #include <security/pam_modules.h> | |
52 #include <security/pam_impl.h> | |
53 #include <rpcsvc/nis.h> | |
54 #undef GROUP | |
55 #include <syslog.h> | |
56 #include <userdefs.h> | |
57 #include <passwdutil.h> | |
58 | |
59 #include <nss_dbdefs.h> | |
60 | |
61 #include <deflt.h> | |
62 | |
63 #undef GROUP | |
64 #include <bsm/adt.h> | |
65 #include <bsm/adt_event.h> | |
66 | |
67 /* | |
68 * flags indicate password attributes to be modified | |
69 */ | |
70 | |
71 #define LFLAG 0x001 /* lock user's password */ | |
72 #define DFLAG 0x002 /* delete user's password */ | |
73 #define MFLAG 0x004 /* set max field -- # of days passwd is valid */ | |
74 #define NFLAG 0x008 /* set min field -- # of days between */ | |
75 /* password changes */ | |
76 #define SFLAG 0x010 /* display password attributes */ | |
77 #define FFLAG 0x020 /* expire user's password */ | |
78 #define AFLAG 0x040 /* display password attributes for all users */ | |
79 #define SAFLAG (SFLAG|AFLAG) /* display password attributes for all users */ | |
80 #define WFLAG 0x100 /* warn user to change passwd */ | |
81 #define OFLAG 0x200 /* domain name */ | |
82 #define EFLAG 0x400 /* change shell */ | |
83 #define GFLAG 0x800 /* change gecos information */ | |
84 #define HFLAG 0x1000 /* change home directory */ | |
85 #define XFLAG 0x2000 /* no login */ | |
86 #define UFLAG 0x4000 /* unlock user's password */ | |
87 | |
88 #define NONAGEFLAG (EFLAG | GFLAG | HFLAG) | |
89 #define AGEFLAG (LFLAG | FFLAG | MFLAG | NFLAG | WFLAG | XFLAG | UFLAG) | |
90 #define MUTEXFLAG (DFLAG | LFLAG | XFLAG | UFLAG | SAFLAG) | |
91 | |
92 | |
93 /* | |
94 * exit code | |
95 */ | |
96 | |
97 #define SUCCESS 0 /* succeeded */ | |
98 #define NOPERM 1 /* No permission */ | |
99 #define BADOPT 2 /* Invalid combination of option */ | |
100 #define FMERR 3 /* File/table manipulation error */ | |
101 #define FATAL 4 /* Old file/table can not be recovered */ | |
102 #define FBUSY 5 /* Lock file/table busy */ | |
103 #define BADSYN 6 /* Incorrect syntax */ | |
104 #define BADAGE 7 /* Aging is disabled */ | |
105 #define NOMEM 8 /* No memory */ | |
106 #define SYSERR 9 /* System error */ | |
107 #define EXPIRED 10 /* Account expired */ | |
108 | |
109 /* | |
110 * define error messages | |
111 */ | |
112 #define MSG_NP "Permission denied" | |
113 #define MSG_BS "Invalid combination of options" | |
114 #define MSG_FE "Unexpected failure. Password file/table unchanged." | |
115 #define MSG_FF "Unexpected failure. Password file/table missing." | |
116 #define MSG_FB "Password file/table busy. Try again later." | |
117 #define MSG_NV "Invalid argument to option" | |
118 #define MSG_AD "Password aging is disabled" | |
119 #define MSG_RS "Cannot change from restricted shell %s\n" | |
120 #define MSG_NM "Out of memory." | |
121 #define MSG_UNACCEPT "%s is unacceptable as a new shell\n" | |
122 #define MSG_UNAVAIL "warning: %s is unavailable on this machine\n" | |
123 #define MSG_COLON "':' is not allowed.\n" | |
124 #define MSG_MAXLEN "Maximum number of characters allowed is %d." | |
125 #define MSG_CONTROL "Control characters are not allowed.\n" | |
126 #define MSG_SHELL_UNCHANGED "Login shell unchanged.\n" | |
127 #define MSG_GECOS_UNCHANGED "Finger information unchanged.\n" | |
128 #define MSG_DIR_UNCHANGED "Homedir information unchanged.\n" | |
129 #define MSG_NAME "\nName [%s]: " | |
130 #define MSG_HOMEDIR "\nHome Directory [%s]: " | |
131 #define MSG_OLDSHELL "Old shell: %s\n" | |
132 #define MSG_NEWSHELL "New shell: " | |
133 #define MSG_AGAIN "\nPlease try again\n" | |
134 #define MSG_INPUTHDR "Default values are printed inside of '[]'.\n" \ | |
135 "To accept the default, type <return>.\n" \ | |
136 "To have a blank entry, type the word 'none'.\n" | |
137 #define MSG_UNKNOWN "%s: User unknown: %s\n" | |
138 #define MSG_ACCOUNT_EXP "User account has expired: %s\n" | |
139 #define MSG_AUTHTOK_EXP "Your password has been expired for too long.\n" \ | |
140 "Please contact the system administrator.\n" | |
141 #define MSG_NIS_HOMEDIR "-h does not apply to NIS" | |
142 #define MSG_CUR_PASS "Enter existing login password: " | |
143 #define MSG_CUR_PASS_UNAME "Enter %s's existing login password: " | |
144 #define MSG_SUCCESS "%s: password information changed for %s\n" | |
145 #define MSG_SORRY "%s: Sorry, wrong passwd\n" | |
146 #define MSG_INFO "%s: Changing password for %s\n" | |
147 | |
148 | |
149 /* | |
150 * return code from ckarg() routine | |
151 */ | |
152 #define FAIL -1 | |
153 | |
154 /* | |
155 * defind password file name | |
156 */ | |
157 #define PASSWD "/etc/passwd" | |
158 | |
159 #define MAX_INPUT_LEN 512 | |
160 | |
161 #define DEF_ATTEMPTS 3 | |
162 | |
163 /* Number of characters in that make up an encrypted password (for now) */ | |
164 #define NUMCP 13 | |
165 | |
166 #ifdef DEBUG | |
167 #define dprintf1 printf | |
168 #else | |
169 #define dprintf1(w, x) | |
170 #endif | |
171 | |
172 extern int optind; | |
173 | |
174 static int retval = SUCCESS; | |
175 static int pam_retval = PAM_SUCCESS; | |
176 static uid_t uid; | |
177 static char *prognamep; | |
178 static long maxdate; /* password aging information */ | |
108 | 179 static int passwd_conv(int, struct pam_message **, |
180 struct pam_response **, void *); | |
0 | 181 static struct pam_conv pam_conv = {passwd_conv, NULL}; |
182 static pam_handle_t *pamh; /* Authentication handle */ | |
183 static char *usrname; /* user whose attribute we update */ | |
184 static adt_session_data_t *ah; /* audit session handle */ | |
185 static adt_event_data_t *event = NULL; /* event to be generated */ | |
186 | |
187 static pam_repository_t auth_rep; | |
188 static pwu_repository_t repository; | |
189 static pwu_repository_t __REPFILES = { "files", NULL, 0 }; | |
190 | |
191 /* | |
192 * Function Declarations | |
193 */ | |
194 | |
195 extern void setusershell(void); | |
196 extern char *getusershell(void); | |
197 extern void endusershell(void); | |
198 | |
108 | 199 static void passwd_exit(int retcode) __NORETURN; |
0 | 200 static void rusage(void); |
201 static int ckuid(void); | |
202 static int ckarg(int argc, char **argv, attrlist **attributes); | |
203 | |
204 static int get_namelist(pwu_repository_t, char ***, int *); | |
205 static int get_namelist_files(char ***, int *); | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
206 static int get_namelist_local(char ***, int *); |
0 | 207 static int get_attr(char *, pwu_repository_t *, attrlist **); |
208 static void display_attr(char *, attrlist *); | |
209 static void free_attr(attrlist *); | |
210 static void attrlist_add(attrlist **, attrtype, char *); | |
211 static void attrlist_reorder(attrlist **); | |
212 static char *userinput(char *, pwu_repository_t *, attrtype); | |
213 static char *getresponse(char *); | |
214 | |
215 /* | |
216 * main(): | |
217 * The main routine will call ckarg() to parse the command line | |
218 * arguments and call the appropriate functions to perform the | |
219 * tasks specified by the arguments. It allows system | |
220 * administrator to add, change and display password attributes. | |
221 * Non privileged user can change password or display | |
222 * password attributes which corresponds to their login name. | |
223 */ | |
224 | |
108 | 225 int |
226 main(int argc, char *argv[]) | |
0 | 227 { |
228 | |
229 int flag; | |
230 char **namelist; | |
231 int num_user; | |
232 int i; | |
233 attrlist *attributes = NULL; | |
234 char *input; | |
235 int tries = 1; | |
236 int updated_reps; | |
237 | |
238 | |
14136
9178198c46b5
4026 cleanup warnings in cmd/passwd
Igor Kozhukhov <ikozhukhov@gmail.com>
parents:
13475
diff
changeset
|
239 if ((prognamep = strrchr(argv[0], '/')) != NULL) |
0 | 240 ++prognamep; |
241 else | |
242 prognamep = argv[0]; | |
243 | |
244 auth_rep.type = NULL; | |
245 auth_rep.scope = NULL; | |
246 repository.type = NULL; | |
247 repository.scope = NULL; | |
248 repository.scope_len = 0; | |
249 | |
250 | |
251 /* initialization for variables, set locale and textdomain */ | |
252 i = 0; | |
253 flag = 0; | |
254 | |
255 uid = getuid(); /* get the user id */ | |
256 (void) setlocale(LC_ALL, ""); | |
257 | |
258 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ | |
259 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ | |
260 #endif | |
261 (void) textdomain(TEXT_DOMAIN); | |
262 | |
263 /* | |
264 * ckarg() parses the arguments. In case of an error, | |
265 * it sets the retval and returns FAIL (-1). | |
266 */ | |
267 | |
268 flag = ckarg(argc, argv, &attributes); | |
269 dprintf1("flag is %0x\n", flag); | |
270 if (flag == FAIL) | |
271 passwd_exit(retval); | |
272 | |
273 argc -= optind; | |
274 | |
275 if (argc < 1) { | |
276 if ((usrname = getlogin()) == NULL) { | |
277 struct passwd *pass = getpwuid(uid); | |
278 if (pass != NULL) | |
279 usrname = pass->pw_name; | |
280 else { | |
281 rusage(); | |
282 exit(NOPERM); | |
283 } | |
284 } else if (flag == 0) { | |
285 /* | |
286 * If flag is zero, change passwd. | |
287 * Otherwise, it will display or | |
288 * modify password aging attributes | |
289 */ | |
290 (void) fprintf(stderr, gettext(MSG_INFO), prognamep, | |
291 usrname); | |
292 } | |
11893
ff6e80260186
6914628 Implement the user object audit token PSARC/2010/001 User object audit token
gww <gww@eng.sun.com>
parents:
11262
diff
changeset
|
293 } else { |
0 | 294 usrname = argv[optind]; |
11893
ff6e80260186
6914628 Implement the user object audit token PSARC/2010/001 User object audit token
gww <gww@eng.sun.com>
parents:
11262
diff
changeset
|
295 } |
0 | 296 |
11893
ff6e80260186
6914628 Implement the user object audit token PSARC/2010/001 User object audit token
gww <gww@eng.sun.com>
parents:
11262
diff
changeset
|
297 if (pam_start("passwd", usrname, &pam_conv, &pamh) != PAM_SUCCESS) { |
0 | 298 passwd_exit(NOPERM); |
11893
ff6e80260186
6914628 Implement the user object audit token PSARC/2010/001 User object audit token
gww <gww@eng.sun.com>
parents:
11262
diff
changeset
|
299 } |
0 | 300 |
301 auth_rep.type = repository.type; | |
302 auth_rep.scope = repository.scope; | |
303 auth_rep.scope_len = repository.scope_len; | |
304 | |
305 if (auth_rep.type != NULL) { | |
306 if (pam_set_item(pamh, PAM_REPOSITORY, (void *)&auth_rep) | |
307 != PAM_SUCCESS) { | |
308 passwd_exit(NOPERM); | |
309 } | |
310 } | |
311 | |
312 if (flag == SAFLAG) { /* display password attributes for all users */ | |
313 retval = get_namelist(repository, &namelist, &num_user); | |
314 if (retval != SUCCESS) | |
315 (void) passwd_exit(retval); | |
316 | |
317 if (num_user == 0) { | |
318 (void) fprintf(stderr, "%s: %s\n", prognamep, | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
319 gettext(MSG_FF)); |
0 | 320 passwd_exit(FATAL); |
321 } | |
322 i = 0; | |
323 while (namelist[i] != NULL) { | |
324 (void) get_attr(namelist[i], &repository, | |
325 &attributes); | |
326 (void) display_attr(namelist[i], attributes); | |
327 (void) free(namelist[i]); | |
328 (void) free_attr(attributes); | |
329 i++; | |
330 } | |
331 (void) free(namelist); | |
332 passwd_exit(SUCCESS); | |
333 } else if (flag == SFLAG) { /* display password attributes by user */ | |
334 if (get_attr(usrname, &repository, &attributes) == | |
335 PWU_SUCCESS) { | |
336 (void) display_attr(usrname, attributes); | |
337 (void) free_attr(attributes); | |
338 } | |
339 passwd_exit(SUCCESS); | |
340 /* NOT REACHED */ | |
341 } | |
342 | |
343 | |
344 switch (pam_authenticate(pamh, 0)) { | |
345 case PAM_SUCCESS: | |
346 break; | |
347 case PAM_USER_UNKNOWN: | |
348 (void) fprintf(stderr, gettext(MSG_UNKNOWN), prognamep, | |
349 usrname); | |
350 passwd_exit(NOPERM); | |
351 break; | |
352 case PAM_PERM_DENIED: | |
353 passwd_exit(NOPERM); | |
354 break; | |
355 case PAM_AUTH_ERR: | |
356 (void) fprintf(stderr, gettext(MSG_SORRY), prognamep); | |
357 passwd_exit(NOPERM); | |
358 break; | |
359 default: | |
360 /* system error */ | |
361 passwd_exit(FMERR); | |
362 break; | |
363 } | |
364 | |
365 if (flag == 0) { /* changing user password */ | |
366 int chk_authtok = 0; /* check password strength */ | |
367 | |
368 dprintf1("call pam_chauthtok() repository name =%s\n", | |
369 repository.type); | |
370 | |
371 /* Set up for Audit */ | |
372 if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) != 0) { | |
373 perror("adt_start_session"); | |
374 passwd_exit(SYSERR); | |
375 } | |
376 if ((event = adt_alloc_event(ah, ADT_passwd)) == NULL) { | |
377 perror("adt_alloc_event"); | |
378 passwd_exit(NOMEM); | |
379 } | |
380 | |
381 /* Don't check account expiration when invoked by root */ | |
382 if (ckuid() != SUCCESS) { | |
383 pam_retval = pam_acct_mgmt(pamh, PAM_SILENT); | |
384 switch (pam_retval) { | |
385 case PAM_ACCT_EXPIRED: | |
386 (void) fprintf(stderr, | |
387 gettext(MSG_ACCOUNT_EXP), usrname); | |
388 passwd_exit(EXPIRED); | |
389 break; | |
390 case PAM_AUTHTOK_EXPIRED: | |
391 (void) fprintf(stderr, | |
392 gettext(MSG_AUTHTOK_EXP)); | |
393 passwd_exit(NOPERM); | |
394 break; | |
395 case PAM_NEW_AUTHTOK_REQD: | |
396 /* valid error when changing passwords */ | |
397 break; | |
398 case PAM_SUCCESS: | |
399 /* Ok to change password */ | |
400 break; | |
401 default: | |
402 passwd_exit(NOPERM); | |
403 } | |
404 } | |
405 | |
406 | |
407 pam_retval = PAM_AUTHTOK_ERR; | |
408 tries = 1; | |
409 if (ckuid() == SUCCESS) { | |
410 /* bypass password strength checks */ | |
411 chk_authtok = PAM_NO_AUTHTOK_CHECK; | |
412 } | |
413 | |
414 while (pam_retval == PAM_AUTHTOK_ERR && tries <= DEF_ATTEMPTS) { | |
415 if (tries > 1) | |
416 (void) printf(gettext(MSG_AGAIN)); | |
417 pam_retval = pam_chauthtok(pamh, chk_authtok); | |
418 if (pam_retval == PAM_TRY_AGAIN) { | |
419 (void) sleep(1); | |
420 pam_retval = pam_chauthtok(pamh, chk_authtok); | |
421 } | |
422 tries++; | |
423 } | |
424 | |
425 switch (pam_retval) { | |
426 case PAM_SUCCESS: | |
427 retval = SUCCESS; | |
428 break; | |
429 case PAM_AUTHTOK_DISABLE_AGING: | |
430 retval = BADAGE; | |
431 break; | |
432 case PAM_AUTHTOK_LOCK_BUSY: | |
433 retval = FBUSY; | |
434 break; | |
435 case PAM_TRY_AGAIN: | |
436 retval = FBUSY; | |
437 break; | |
438 case PAM_AUTHTOK_ERR: | |
439 case PAM_AUTHTOK_RECOVERY_ERR: | |
440 default: | |
441 retval = NOPERM; | |
442 break; | |
443 } | |
444 | |
445 (void) passwd_exit(retval); | |
446 /* NOT REACHED */ | |
447 } else { /* changing attributes */ | |
448 switch (flag) { | |
449 case EFLAG: /* changing user password attributes */ | |
450 input = userinput(usrname, &repository, ATTR_SHELL); | |
451 if (input) | |
452 attrlist_add(&attributes, ATTR_SHELL, input); | |
453 else | |
454 (void) printf(gettext(MSG_SHELL_UNCHANGED)); | |
455 break; | |
456 case GFLAG: | |
457 input = userinput(usrname, &repository, ATTR_GECOS); | |
458 if (input) | |
459 attrlist_add(&attributes, ATTR_GECOS, input); | |
460 else | |
461 (void) printf(gettext(MSG_GECOS_UNCHANGED)); | |
462 break; | |
463 case HFLAG: | |
464 input = userinput(usrname, &repository, ATTR_HOMEDIR); | |
465 if (input) | |
466 attrlist_add(&attributes, ATTR_HOMEDIR, input); | |
467 else | |
468 (void) printf(gettext(MSG_DIR_UNCHANGED)); | |
469 break; | |
470 } | |
471 | |
472 if (attributes != NULL) { | |
473 retval = __set_authtoken_attr(usrname, | |
474 pamh->ps_item[PAM_AUTHTOK].pi_addr, | |
11262
b7ebfbf2359e
6874309 Remove NIS+ from Solaris
Raja Andra <Rajagopal.Andra@Sun.COM>
parents:
8821
diff
changeset
|
475 &repository, attributes, &updated_reps); |
0 | 476 switch (retval) { |
477 case PWU_SUCCESS: | |
478 for (i = 1; i <= REP_LAST; i <<= 1) { | |
479 if ((updated_reps & i) == 0) | |
480 continue; | |
481 (void) printf(gettext(MSG_SUCCESS), | |
482 prognamep, usrname); | |
483 } | |
484 retval = SUCCESS; | |
485 break; | |
486 case PWU_AGING_DISABLED: | |
487 retval = BADAGE; | |
488 break; | |
489 default: | |
490 retval = NOPERM; | |
491 break; | |
492 } | |
493 } else { | |
494 retval = SUCCESS; /* nothing to change won't fail */ | |
495 } | |
496 (void) passwd_exit(retval); | |
497 } | |
108 | 498 /* NOTREACHED */ |
499 return (0); | |
0 | 500 } |
501 | |
502 /* | |
503 * Get a line of input from the user. | |
504 * | |
505 * If the line is empty, or the input equals 'oldval', NULL is returned. | |
506 * therwise, a malloced string containing the input (minus the trailing | |
507 * newline) is returned. | |
508 */ | |
509 char * | |
510 getresponse(char *oldval) | |
511 { | |
512 char resp[MAX_INPUT_LEN]; | |
513 char *retval = NULL; | |
514 int resplen; | |
515 | |
516 (void) fgets(resp, sizeof (resp) - 1, stdin); | |
517 resplen = strlen(resp) - 1; | |
518 if (resp[resplen] == '\n') | |
519 resp[resplen] = '\0'; | |
520 if (*resp != '\0' && strcmp(resp, oldval) != 0) | |
521 retval = strdup(resp); | |
522 return (retval); | |
523 } | |
524 | |
525 /* | |
526 * char *userinput(item) | |
527 * | |
528 * user conversation function. The old value of attribute "item" is | |
529 * displayed while the user is asked to provide a new value. | |
530 * | |
531 * returns a malloc()-ed string if the user actualy provided input | |
532 * or NULL if the user simply hit return or the input equals the old | |
533 * value (not changed). | |
534 */ | |
535 char * | |
536 userinput(char *name, pwu_repository_t *rep, attrtype type) | |
537 { | |
538 attrlist oldattr; | |
539 char *oldval; /* shorthand for oldattr.data.val_s */ | |
540 char *valid; /* points to valid shells */ | |
541 char *response; | |
542 char *cp; | |
543 | |
544 oldattr.type = type; | |
545 oldattr.next = NULL; | |
546 | |
547 if (__get_authtoken_attr(name, rep, &oldattr) != PWU_SUCCESS) | |
548 passwd_exit(FMERR); | |
549 | |
550 oldval = oldattr.data.val_s; | |
551 | |
552 if (type == ATTR_SHELL) { | |
553 /* No current shell: set DEFSHL as default choice */ | |
554 if (*oldval == '\0') { | |
555 free(oldval); | |
556 oldval = strdup(DEFSHL); | |
557 } | |
558 | |
559 if (ckuid() != SUCCESS) { | |
560 /* User must currently have a valid shell */ | |
561 setusershell(); | |
562 valid = getusershell(); | |
563 while (valid && strcmp(valid, oldval) != 0) | |
564 valid = getusershell(); | |
565 endusershell(); | |
566 | |
567 if (valid == NULL) { | |
568 (void) fprintf(stderr, gettext(MSG_RS), oldval); | |
569 free(oldval); | |
570 return (NULL); | |
571 } | |
572 } | |
573 (void) printf(gettext(MSG_OLDSHELL), oldval); | |
574 (void) printf(gettext(MSG_NEWSHELL)); | |
575 (void) fflush(stdout); | |
576 | |
577 response = getresponse(oldval); | |
578 free(oldval); /* We don't need the old value anymore */ | |
579 | |
580 if (response == NULL || *response == '\0') | |
581 return (NULL); | |
582 | |
583 /* Make sure new shell is listed */ | |
584 setusershell(); | |
585 valid = getusershell(); | |
586 while (valid) { | |
587 char *cp; | |
588 | |
589 /* Allow user to give shell without path */ | |
590 if (*response == '/') { | |
591 cp = valid; | |
592 } else { | |
593 if ((cp = strrchr(valid, '/')) == NULL) | |
594 cp = valid; | |
595 else | |
596 cp++; | |
597 } | |
598 if (strcmp(cp, response) == 0) { | |
599 if (*response != '/') { | |
600 /* take shell name including path */ | |
601 free(response); | |
602 response = strdup(valid); | |
603 } | |
604 break; | |
605 } | |
606 valid = getusershell(); | |
607 } | |
608 endusershell(); | |
609 | |
610 if (valid == NULL) { /* No valid shell matches */ | |
611 (void) fprintf(stderr, gettext(MSG_UNACCEPT), response); | |
612 return (NULL); | |
613 } | |
614 | |
615 if (access(response, X_OK) < 0) | |
616 (void) fprintf(stderr, gettext(MSG_UNAVAIL), response); | |
617 return (response); | |
618 /* NOT REACHED */ | |
619 } | |
620 /* | |
621 * if type == SHELL, we have returned by now. Only GECOS and | |
622 * HOMEDIR get to this point. | |
623 */ | |
624 (void) printf(gettext(MSG_INPUTHDR)); | |
625 | |
626 /* | |
627 * PRE: oldval points to malloced string with Old Value | |
628 * INV: oldval remains unchanged | |
629 * POST:response points to valid string or NULL. | |
630 */ | |
631 for (;;) { | |
632 if (type == ATTR_GECOS) | |
633 (void) printf(gettext(MSG_NAME), oldval); | |
634 else if (type == ATTR_HOMEDIR) | |
635 (void) printf(gettext(MSG_HOMEDIR), oldval); | |
636 | |
637 response = getresponse(oldval); | |
638 | |
639 if (response && strcmp(response, "none") == 0) | |
640 *response = '\0'; | |
641 | |
642 /* No-change or empty string are OK */ | |
643 if (response == NULL || *response == '\0') | |
644 break; | |
645 | |
646 /* Check for illegal characters */ | |
647 if (strchr(response, ':')) { | |
648 (void) fprintf(stderr, "%s", gettext(MSG_COLON)); | |
649 free(response); | |
650 } else if (strlen(response) > MAX_INPUT_LEN - 1) { | |
651 (void) fprintf(stderr, gettext(MSG_MAXLEN), | |
652 MAX_INPUT_LEN); | |
653 free(response); | |
654 } else { | |
655 /* don't allow control characters */ | |
656 for (cp = response; *cp >= 040; cp++) | |
657 ; | |
658 if (*cp != '\0') { | |
659 (void) fprintf(stderr, gettext(MSG_CONTROL)); | |
660 free(response); | |
661 } else | |
662 break; /* response is a valid string */ | |
663 } | |
664 /* | |
665 * We only get here if the input was invalid. | |
666 * In that case, we again ask the user for input. | |
667 */ | |
668 } | |
669 free(oldval); | |
670 return (response); | |
671 } | |
672 /* | |
673 * ckarg(): | |
674 * This function parses and verifies the | |
675 * arguments. It takes three parameters: | |
676 * argc => # of arguments | |
677 * argv => pointer to an argument | |
678 * attrlist => pointer to list of password attributes | |
679 */ | |
680 | |
681 static int | |
682 ckarg(int argc, char **argv, attrlist **attributes) | |
683 { | |
684 extern char *optarg; | |
685 char *char_p; | |
686 int opt; | |
687 int flag; | |
688 | |
689 flag = 0; | |
690 | |
11262
b7ebfbf2359e
6874309 Remove NIS+ from Solaris
Raja Andra <Rajagopal.Andra@Sun.COM>
parents:
8821
diff
changeset
|
691 while ((opt = getopt(argc, argv, "r:aldefghsux:n:w:N")) != EOF) { |
0 | 692 switch (opt) { |
693 | |
694 case 'r': /* Repository Specified */ | |
695 /* repository: this option should be specified first */ | |
696 | |
697 if (repository.type != NULL) { | |
698 (void) fprintf(stderr, gettext( | |
699 "Repository is already defined or specified.\n")); | |
700 rusage(); | |
701 retval = BADSYN; | |
702 return (FAIL); | |
703 } | |
11262
b7ebfbf2359e
6874309 Remove NIS+ from Solaris
Raja Andra <Rajagopal.Andra@Sun.COM>
parents:
8821
diff
changeset
|
704 if (strcmp(optarg, "nis") == 0) { |
0 | 705 repository.type = optarg; |
706 } else if (strcmp(optarg, "ldap") == 0) { | |
707 repository.type = optarg; | |
708 } else if (strcmp(optarg, "files") == 0) { | |
709 repository.type = optarg; | |
710 } else { | |
711 (void) fprintf(stderr, | |
712 gettext("invalid repository: %s\n"), | |
713 optarg); | |
714 rusage(); | |
715 retval = BADSYN; | |
716 return (FAIL); | |
717 } | |
718 break; | |
719 | |
720 case 'd': /* Delete Auth Token */ | |
721 /* if no repository the default for -d is files */ | |
722 if (repository.type == NULL) | |
723 repository = __REPFILES; | |
724 | |
725 /* | |
726 * Delete the password - only privileged processes | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
727 * can execute this for FILES or LDAP |
0 | 728 */ |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
729 if (IS_FILES(repository) == FALSE && |
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
730 IS_LDAP(repository) == FALSE) { |
0 | 731 (void) fprintf(stderr, gettext( |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
732 "-d only applies to files " |
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
733 "or ldap repository\n")); |
0 | 734 rusage(); /* exit */ |
735 retval = BADSYN; | |
736 return (FAIL); | |
737 } | |
738 | |
739 if (ckuid() != SUCCESS) { | |
740 retval = NOPERM; | |
741 return (FAIL); | |
742 } | |
743 if (flag & (LFLAG|SAFLAG|DFLAG|XFLAG|UFLAG)) { | |
744 rusage(); | |
745 retval = BADOPT; | |
746 return (FAIL); | |
747 } | |
748 flag |= DFLAG; | |
749 attrlist_add(attributes, ATTR_PASSWD, NULL); | |
750 break; | |
751 | |
752 case 'N': /* set account to be "no login" */ | |
753 | |
754 /* if no repository the default for -N is files */ | |
755 if (repository.type == NULL) | |
756 repository = __REPFILES; | |
757 | |
758 if (IS_FILES(repository) == FALSE && | |
11262
b7ebfbf2359e
6874309 Remove NIS+ from Solaris
Raja Andra <Rajagopal.Andra@Sun.COM>
parents:
8821
diff
changeset
|
759 IS_LDAP(repository) == FALSE) { |
0 | 760 (void) fprintf(stderr, gettext( |
11262
b7ebfbf2359e
6874309 Remove NIS+ from Solaris
Raja Andra <Rajagopal.Andra@Sun.COM>
parents:
8821
diff
changeset
|
761 "-N only applies to files or ldap " |
b7ebfbf2359e
6874309 Remove NIS+ from Solaris
Raja Andra <Rajagopal.Andra@Sun.COM>
parents:
8821
diff
changeset
|
762 "repository\n")); |
0 | 763 rusage(); /* exit */ |
764 retval = BADOPT; | |
765 return (FAIL); | |
766 } | |
767 | |
768 /* | |
769 * Only privileged processes can execute this | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
770 * for FILES or LDAP |
0 | 771 */ |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
772 if ((IS_FILES(repository) || IS_LDAP(repository)) && |
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
773 ((retval = ckuid()) != SUCCESS)) |
0 | 774 return (FAIL); |
775 if (flag & (MUTEXFLAG|NONAGEFLAG)) { | |
776 rusage(); /* exit */ | |
777 retval = BADOPT; | |
778 return (FAIL); | |
779 } | |
780 flag |= XFLAG; | |
781 attrlist_add(attributes, ATTR_NOLOGIN_ACCOUNT, NULL); | |
782 break; | |
783 | |
784 case 'l': /* lock the password */ | |
785 | |
786 /* if no repository the default for -l is files */ | |
787 if (repository.type == NULL) | |
788 repository = __REPFILES; | |
789 | |
790 if (IS_FILES(repository) == FALSE && | |
11262
b7ebfbf2359e
6874309 Remove NIS+ from Solaris
Raja Andra <Rajagopal.Andra@Sun.COM>
parents:
8821
diff
changeset
|
791 IS_LDAP(repository) == FALSE) { |
0 | 792 (void) fprintf(stderr, gettext( |
11262
b7ebfbf2359e
6874309 Remove NIS+ from Solaris
Raja Andra <Rajagopal.Andra@Sun.COM>
parents:
8821
diff
changeset
|
793 "-l only applies to files or ldap " |
b7ebfbf2359e
6874309 Remove NIS+ from Solaris
Raja Andra <Rajagopal.Andra@Sun.COM>
parents:
8821
diff
changeset
|
794 "repository\n")); |
0 | 795 rusage(); /* exit */ |
796 retval = BADOPT; | |
797 return (FAIL); | |
798 } | |
799 | |
800 /* | |
801 * Only privileged processes can execute this | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
802 * for FILES or LDAP |
0 | 803 */ |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
804 if ((IS_FILES(repository) || IS_LDAP(repository)) && |
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
805 ((retval = ckuid()) != SUCCESS)) |
0 | 806 return (FAIL); |
807 if (flag & (MUTEXFLAG|NONAGEFLAG)) { | |
808 rusage(); /* exit */ | |
809 retval = BADOPT; | |
810 return (FAIL); | |
811 } | |
812 flag |= LFLAG; | |
813 attrlist_add(attributes, ATTR_LOCK_ACCOUNT, NULL); | |
814 break; | |
815 | |
816 case 'u': /* unlock the password */ | |
817 | |
818 /* if no repository the default for -u is files */ | |
819 if (repository.type == NULL) | |
820 repository = __REPFILES; | |
821 | |
822 if (IS_FILES(repository) == FALSE && | |
11262
b7ebfbf2359e
6874309 Remove NIS+ from Solaris
Raja Andra <Rajagopal.Andra@Sun.COM>
parents:
8821
diff
changeset
|
823 IS_LDAP(repository) == FALSE) { |
0 | 824 (void) fprintf(stderr, gettext( |
11262
b7ebfbf2359e
6874309 Remove NIS+ from Solaris
Raja Andra <Rajagopal.Andra@Sun.COM>
parents:
8821
diff
changeset
|
825 "-u only applies to files or ldap " |
b7ebfbf2359e
6874309 Remove NIS+ from Solaris
Raja Andra <Rajagopal.Andra@Sun.COM>
parents:
8821
diff
changeset
|
826 "repository\n")); |
0 | 827 rusage(); /* exit */ |
828 retval = BADOPT; | |
829 return (FAIL); | |
830 } | |
831 | |
832 /* | |
833 * Only privileged processes can execute this | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
834 * for FILES or LDAP |
0 | 835 */ |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
836 if ((IS_FILES(repository) || IS_LDAP(repository)) && |
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
837 ((retval = ckuid()) != SUCCESS)) |
0 | 838 return (FAIL); |
839 if (flag & (MUTEXFLAG|NONAGEFLAG)) { | |
840 rusage(); /* exit */ | |
841 retval = BADOPT; | |
842 return (FAIL); | |
843 } | |
844 flag |= UFLAG; | |
845 attrlist_add(attributes, ATTR_UNLOCK_ACCOUNT, NULL); | |
846 attrlist_add(attributes, ATTR_RST_FAILED_LOGINS, NULL); | |
847 break; | |
848 | |
849 case 'x': /* set the max date */ | |
850 | |
851 /* if no repository the default for -x is files */ | |
852 if (repository.type == NULL) | |
853 repository = __REPFILES; | |
854 | |
855 if (IS_FILES(repository) == FALSE && | |
11262
b7ebfbf2359e
6874309 Remove NIS+ from Solaris
Raja Andra <Rajagopal.Andra@Sun.COM>
parents:
8821
diff
changeset
|
856 IS_LDAP(repository) == FALSE) { |
0 | 857 (void) fprintf(stderr, gettext( |
11262
b7ebfbf2359e
6874309 Remove NIS+ from Solaris
Raja Andra <Rajagopal.Andra@Sun.COM>
parents:
8821
diff
changeset
|
858 "-x only applies to files or ldap " |
b7ebfbf2359e
6874309 Remove NIS+ from Solaris
Raja Andra <Rajagopal.Andra@Sun.COM>
parents:
8821
diff
changeset
|
859 "repository\n")); |
0 | 860 rusage(); /* exit */ |
861 retval = BADSYN; | |
862 return (FAIL); | |
863 } | |
864 | |
865 /* | |
866 * Only privileged process can execute this | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
867 * for FILES or LDAP |
0 | 868 */ |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
869 if ((IS_FILES(repository) || IS_LDAP(repository)) && |
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
870 (ckuid() != SUCCESS)) { |
0 | 871 retval = NOPERM; |
872 return (FAIL); | |
873 } | |
874 if (flag & (SAFLAG|MFLAG|NONAGEFLAG)) { | |
875 retval = BADOPT; | |
876 return (FAIL); | |
877 } | |
878 flag |= MFLAG; | |
879 if ((int)strlen(optarg) <= 0 || | |
880 (maxdate = strtol(optarg, &char_p, 10)) < -1 || | |
881 *char_p != '\0') { | |
882 (void) fprintf(stderr, "%s: %s -x\n", | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
883 prognamep, gettext(MSG_NV)); |
0 | 884 retval = BADSYN; |
885 return (FAIL); | |
886 } | |
887 attrlist_add(attributes, ATTR_MAX, optarg); | |
888 break; | |
889 | |
890 case 'n': /* set the min date */ | |
891 | |
892 /* if no repository the default for -n is files */ | |
893 if (repository.type == NULL) | |
894 repository = __REPFILES; | |
895 | |
896 if (IS_FILES(repository) == FALSE && | |
11262
b7ebfbf2359e
6874309 Remove NIS+ from Solaris
Raja Andra <Rajagopal.Andra@Sun.COM>
parents:
8821
diff
changeset
|
897 IS_LDAP(repository) == FALSE) { |
0 | 898 (void) fprintf(stderr, gettext( |
11262
b7ebfbf2359e
6874309 Remove NIS+ from Solaris
Raja Andra <Rajagopal.Andra@Sun.COM>
parents:
8821
diff
changeset
|
899 "-n only applies to files or ldap " |
b7ebfbf2359e
6874309 Remove NIS+ from Solaris
Raja Andra <Rajagopal.Andra@Sun.COM>
parents:
8821
diff
changeset
|
900 "repository\n")); |
0 | 901 rusage(); /* exit */ |
902 retval = BADSYN; | |
903 return (FAIL); | |
904 } | |
905 | |
906 /* | |
907 * Only privileged process can execute this | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
908 * for FILES or LDAP |
0 | 909 */ |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
910 if ((IS_FILES(repository) || IS_LDAP(repository)) && |
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
911 ((retval = ckuid()) != SUCCESS)) |
0 | 912 return (FAIL); |
913 if (flag & (SAFLAG|NFLAG|NONAGEFLAG)) { | |
914 retval = BADOPT; | |
915 return (FAIL); | |
916 } | |
917 flag |= NFLAG; | |
918 if ((int)strlen(optarg) <= 0 || | |
919 (strtol(optarg, &char_p, 10)) < 0 || | |
920 *char_p != '\0') { | |
921 (void) fprintf(stderr, "%s: %s -n\n", | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
922 prognamep, gettext(MSG_NV)); |
0 | 923 retval = BADSYN; |
924 return (FAIL); | |
925 } | |
926 attrlist_add(attributes, ATTR_MIN, optarg); | |
927 break; | |
928 | |
929 case 'w': /* set the warning field */ | |
930 | |
931 /* if no repository the default for -w is files */ | |
932 if (repository.type == NULL) | |
933 repository = __REPFILES; | |
934 | |
935 if (IS_FILES(repository) == FALSE && | |
11262
b7ebfbf2359e
6874309 Remove NIS+ from Solaris
Raja Andra <Rajagopal.Andra@Sun.COM>
parents:
8821
diff
changeset
|
936 IS_LDAP(repository) == FALSE) { |
0 | 937 (void) fprintf(stderr, gettext( |
11262
b7ebfbf2359e
6874309 Remove NIS+ from Solaris
Raja Andra <Rajagopal.Andra@Sun.COM>
parents:
8821
diff
changeset
|
938 "-w only applies to files or ldap " |
b7ebfbf2359e
6874309 Remove NIS+ from Solaris
Raja Andra <Rajagopal.Andra@Sun.COM>
parents:
8821
diff
changeset
|
939 "repository\n")); |
0 | 940 rusage(); /* exit */ |
941 retval = BADSYN; | |
942 return (FAIL); | |
943 } | |
944 | |
945 /* | |
946 * Only privileged process can execute this | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
947 * for FILES or LDAP |
0 | 948 */ |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
949 if ((IS_FILES(repository) || IS_LDAP(repository)) && |
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
950 (ckuid() != SUCCESS)) { |
0 | 951 retval = NOPERM; |
952 return (FAIL); | |
953 } | |
954 if (flag & (SAFLAG|WFLAG|NONAGEFLAG)) { | |
955 retval = BADOPT; | |
956 return (FAIL); | |
957 } | |
958 flag |= WFLAG; | |
959 if ((int)strlen(optarg) <= 0 || | |
960 (strtol(optarg, &char_p, 10)) < 0 || | |
961 *char_p != '\0') { | |
962 (void) fprintf(stderr, "%s: %s -w\n", | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
963 prognamep, gettext(MSG_NV)); |
0 | 964 retval = BADSYN; |
965 return (FAIL); | |
966 } | |
967 attrlist_add(attributes, ATTR_WARN, optarg); | |
968 break; | |
969 | |
970 case 's': /* display password attributes */ | |
971 | |
972 /* if no repository the default for -s is files */ | |
973 if (repository.type == NULL) | |
974 repository = __REPFILES; | |
975 | |
976 | |
977 /* display password attributes */ | |
978 if (IS_FILES(repository) == FALSE && | |
11262
b7ebfbf2359e
6874309 Remove NIS+ from Solaris
Raja Andra <Rajagopal.Andra@Sun.COM>
parents:
8821
diff
changeset
|
979 IS_LDAP(repository) == FALSE) { |
0 | 980 (void) fprintf(stderr, gettext( |
11262
b7ebfbf2359e
6874309 Remove NIS+ from Solaris
Raja Andra <Rajagopal.Andra@Sun.COM>
parents:
8821
diff
changeset
|
981 "-s only applies to files or ldap " |
b7ebfbf2359e
6874309 Remove NIS+ from Solaris
Raja Andra <Rajagopal.Andra@Sun.COM>
parents:
8821
diff
changeset
|
982 "repository\n")); |
0 | 983 rusage(); /* exit */ |
984 retval = BADSYN; | |
985 return (FAIL); | |
986 } | |
987 | |
988 /* | |
989 * Only privileged process can execute this | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
990 * for FILES or LDAP |
0 | 991 */ |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
992 if ((IS_FILES(repository) || IS_LDAP(repository)) && |
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
993 ((retval = ckuid()) != SUCCESS)) |
0 | 994 return (FAIL); |
995 if (flag && (flag != AFLAG)) { | |
996 retval = BADOPT; | |
997 return (FAIL); | |
998 } | |
999 flag |= SFLAG; | |
1000 break; | |
1001 | |
1002 case 'a': /* display password attributes */ | |
1003 | |
1004 /* if no repository the default for -a is files */ | |
1005 if (repository.type == NULL) | |
1006 repository = __REPFILES; | |
1007 | |
1008 if (IS_FILES(repository) == FALSE && | |
11262
b7ebfbf2359e
6874309 Remove NIS+ from Solaris
Raja Andra <Rajagopal.Andra@Sun.COM>
parents:
8821
diff
changeset
|
1009 IS_LDAP(repository) == FALSE) { |
0 | 1010 (void) fprintf(stderr, gettext( |
11262
b7ebfbf2359e
6874309 Remove NIS+ from Solaris
Raja Andra <Rajagopal.Andra@Sun.COM>
parents:
8821
diff
changeset
|
1011 "-a only applies to files or ldap " |
b7ebfbf2359e
6874309 Remove NIS+ from Solaris
Raja Andra <Rajagopal.Andra@Sun.COM>
parents:
8821
diff
changeset
|
1012 "repository\n")); |
0 | 1013 rusage(); /* exit */ |
1014 retval = BADSYN; | |
1015 return (FAIL); | |
1016 } | |
1017 | |
1018 /* | |
1019 * Only privileged process can execute this | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1020 * for FILES or LDAP |
0 | 1021 */ |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1022 if ((IS_FILES(repository) || IS_LDAP(repository)) && |
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1023 ((retval = ckuid()) != SUCCESS)) |
0 | 1024 return (FAIL); |
1025 if (flag && (flag != SFLAG)) { | |
1026 retval = BADOPT; | |
1027 return (FAIL); | |
1028 } | |
1029 flag |= AFLAG; | |
1030 break; | |
1031 | |
1032 case 'f': /* expire password attributes */ | |
1033 | |
1034 /* if no repository the default for -f is files */ | |
1035 if (repository.type == NULL) | |
1036 repository = __REPFILES; | |
1037 | |
1038 if (IS_FILES(repository) == FALSE && | |
11262
b7ebfbf2359e
6874309 Remove NIS+ from Solaris
Raja Andra <Rajagopal.Andra@Sun.COM>
parents:
8821
diff
changeset
|
1039 IS_LDAP(repository) == FALSE) { |
0 | 1040 (void) fprintf(stderr, gettext( |
11262
b7ebfbf2359e
6874309 Remove NIS+ from Solaris
Raja Andra <Rajagopal.Andra@Sun.COM>
parents:
8821
diff
changeset
|
1041 "-f only applies to files or ldap " |
b7ebfbf2359e
6874309 Remove NIS+ from Solaris
Raja Andra <Rajagopal.Andra@Sun.COM>
parents:
8821
diff
changeset
|
1042 "repository\n")); |
0 | 1043 rusage(); /* exit */ |
1044 retval = BADSYN; | |
1045 return (FAIL); | |
1046 } | |
1047 | |
1048 /* | |
1049 * Only privileged process can execute this | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1050 * for FILES or LDAP |
0 | 1051 */ |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1052 if ((IS_FILES(repository) || IS_LDAP(repository)) && |
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1053 ((retval = ckuid()) != SUCCESS)) |
0 | 1054 return (FAIL); |
1055 if (flag & (SAFLAG|FFLAG|NONAGEFLAG)) { | |
1056 retval = BADOPT; | |
1057 return (FAIL); | |
1058 } | |
1059 flag |= FFLAG; | |
1060 attrlist_add(attributes, ATTR_EXPIRE_PASSWORD, NULL); | |
1061 break; | |
1062 | |
1063 case 'e': /* change login shell */ | |
1064 | |
1065 /* if no repository the default for -e is files */ | |
1066 if (repository.type == NULL) | |
1067 repository = __REPFILES; | |
1068 | |
1069 if (flag & (EFLAG|SAFLAG|AGEFLAG)) { | |
1070 retval = BADOPT; | |
1071 return (FAIL); | |
1072 } | |
1073 flag |= EFLAG; | |
1074 break; | |
1075 | |
1076 case 'g': /* change gecos information */ | |
1077 | |
1078 /* if no repository the default for -g is files */ | |
1079 if (repository.type == NULL) | |
1080 repository = __REPFILES; | |
1081 | |
1082 /* | |
1083 * Only privileged process can execute this | |
1084 * for FILES | |
1085 */ | |
1086 if (IS_FILES(repository) && (ckuid() != SUCCESS)) { | |
1087 retval = NOPERM; | |
1088 return (FAIL); | |
1089 } | |
1090 if (flag & (GFLAG|SAFLAG|AGEFLAG)) { | |
1091 retval = BADOPT; | |
1092 return (FAIL); | |
1093 } | |
1094 flag |= GFLAG; | |
1095 break; | |
1096 | |
1097 case 'h': /* change home dir */ | |
1098 | |
1099 /* if no repository the default for -h is files */ | |
1100 if (repository.type == NULL) | |
1101 repository = __REPFILES; | |
1102 /* | |
1103 * Only privileged process can execute this | |
1104 * for FILES | |
1105 */ | |
1106 if (IS_FILES(repository) && (ckuid() != SUCCESS)) { | |
1107 retval = NOPERM; | |
1108 return (FAIL); | |
1109 } | |
1110 if (IS_NIS(repository)) { | |
1111 (void) fprintf(stderr, "%s\n", | |
1112 gettext(MSG_NIS_HOMEDIR)); | |
1113 retval = BADSYN; | |
1114 return (FAIL); | |
1115 } | |
1116 | |
1117 if (flag & (HFLAG|SAFLAG|AGEFLAG)) { | |
1118 retval = BADOPT; | |
1119 return (FAIL); | |
1120 } | |
1121 flag |= HFLAG; | |
1122 break; | |
1123 | |
1124 case '?': | |
1125 rusage(); | |
1126 retval = BADOPT; | |
1127 return (FAIL); | |
1128 } | |
1129 } | |
1130 | |
1131 argc -= optind; | |
1132 if (argc > 1) { | |
1133 rusage(); | |
1134 retval = BADSYN; | |
1135 return (FAIL); | |
1136 } | |
1137 | |
1138 /* Make sure (EXPIRE comes after (MAX comes after MIN)) */ | |
1139 attrlist_reorder(attributes); | |
1140 | |
1141 /* If no options are specified or only the show option */ | |
1142 /* is specified, return because no option error checking */ | |
1143 /* is needed */ | |
1144 if (!flag || (flag == SFLAG)) | |
1145 return (flag); | |
1146 | |
1147 /* AFLAG must be used with SFLAG */ | |
1148 if (flag == AFLAG) { | |
1149 rusage(); | |
1150 retval = BADSYN; | |
1151 return (FAIL); | |
1152 } | |
1153 | |
1154 if (flag != SAFLAG && argc < 1) { | |
1155 /* | |
1156 * user name is not specified (argc<1), it can't be | |
1157 * aging info update. | |
1158 */ | |
1159 if (!(flag & NONAGEFLAG)) { | |
1160 rusage(); | |
1161 retval = BADSYN; | |
1162 return (FAIL); | |
1163 } | |
1164 } | |
1165 | |
1166 /* user name(s) may not be specified when SAFLAG is used. */ | |
1167 if (flag == SAFLAG && argc >= 1) { | |
1168 rusage(); | |
1169 retval = BADSYN; | |
1170 return (FAIL); | |
1171 } | |
1172 | |
1173 /* | |
1174 * If aging is being turned off (maxdate == -1), mindate may not | |
1175 * be specified. | |
1176 */ | |
1177 if ((maxdate == -1) && (flag & NFLAG)) { | |
1178 (void) fprintf(stderr, "%s: %s -n\n", | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1179 prognamep, gettext(MSG_NV)); |
0 | 1180 retval = BADOPT; |
1181 return (FAIL); | |
1182 } | |
1183 | |
1184 return (flag); | |
1185 } | |
1186 | |
1187 /* | |
1188 * | |
1189 * ckuid(): | |
1190 * This function returns SUCCESS if the caller is root, else | |
1191 * it returns NOPERM. | |
1192 * | |
1193 */ | |
1194 | |
1195 static int | |
108 | 1196 ckuid(void) |
0 | 1197 { |
1198 if (uid != 0) { | |
1199 return (retval = NOPERM); | |
1200 } | |
1201 return (SUCCESS); | |
1202 } | |
1203 | |
1204 | |
1205 /* | |
1206 * get_attr() | |
1207 */ | |
1208 int | |
1209 get_attr(char *username, pwu_repository_t *repository, attrlist **attributes) | |
1210 { | |
1211 int res; | |
1212 | |
1213 attrlist_add(attributes, ATTR_PASSWD, NULL); | |
1214 attrlist_add(attributes, ATTR_LSTCHG, "0"); | |
1215 attrlist_add(attributes, ATTR_MIN, "0"); | |
1216 attrlist_add(attributes, ATTR_MAX, "0"); | |
1217 attrlist_add(attributes, ATTR_WARN, "0"); | |
1218 | |
1219 res = __get_authtoken_attr(username, repository, *attributes); | |
1220 | |
1221 if (res == PWU_SUCCESS) { | |
1222 retval = SUCCESS; | |
1223 return (PWU_SUCCESS); | |
1224 } | |
1225 | |
1226 if (res == PWU_NOT_FOUND) | |
1227 (void) fprintf(stderr, gettext(MSG_UNKNOWN), prognamep, | |
1228 username); | |
1229 | |
1230 retval = NOPERM; | |
1231 passwd_exit(retval); | |
1232 /*NOTREACHED*/ | |
1233 } | |
1234 | |
1235 /* | |
1236 * display_attr(): | |
1237 * This function prints out the password attributes of a usr | |
1238 * onto standand output. | |
1239 */ | |
1240 void | |
1241 display_attr(char *usrname, attrlist *attributes) | |
1242 { | |
14136
9178198c46b5
4026 cleanup warnings in cmd/passwd
Igor Kozhukhov <ikozhukhov@gmail.com>
parents:
13475
diff
changeset
|
1243 char *status = NULL; |
0 | 1244 char *passwd; |
1245 long lstchg; | |
14136
9178198c46b5
4026 cleanup warnings in cmd/passwd
Igor Kozhukhov <ikozhukhov@gmail.com>
parents:
13475
diff
changeset
|
1246 int min = 0, max = 0, warn = 0; |
0 | 1247 |
1248 while (attributes) { | |
1249 switch (attributes->type) { | |
1250 case ATTR_PASSWD: | |
1251 passwd = attributes->data.val_s; | |
1252 if (passwd == NULL || *passwd == '\0') | |
1253 status = "NP "; | |
1254 else if (strncmp(passwd, LOCKSTRING, | |
1255 sizeof (LOCKSTRING)-1) == 0) | |
1256 status = "LK "; | |
1257 else if (strncmp(passwd, NOLOGINSTRING, | |
1258 sizeof (NOLOGINSTRING)-1) == 0) | |
1259 status = "NL "; | |
446 | 1260 else if ((strlen(passwd) == 13 && passwd[0] != '$') || |
1261 passwd[0] == '$') | |
1262 status = "PS "; | |
0 | 1263 else |
446 | 1264 status = "UN "; |
0 | 1265 break; |
1266 case ATTR_LSTCHG: | |
1267 lstchg = attributes->data.val_i * DAY; | |
1268 break; | |
1269 case ATTR_MIN: | |
1270 min = attributes->data.val_i; | |
1271 break; | |
1272 case ATTR_MAX: | |
1273 max = attributes->data.val_i; | |
1274 break; | |
1275 case ATTR_WARN: | |
1276 warn = attributes->data.val_i; | |
1277 break; | |
14136
9178198c46b5
4026 cleanup warnings in cmd/passwd
Igor Kozhukhov <ikozhukhov@gmail.com>
parents:
13475
diff
changeset
|
1278 default: |
9178198c46b5
4026 cleanup warnings in cmd/passwd
Igor Kozhukhov <ikozhukhov@gmail.com>
parents:
13475
diff
changeset
|
1279 break; |
0 | 1280 } |
1281 attributes = attributes->next; | |
1282 } | |
1283 (void) fprintf(stdout, "%-8s ", usrname); | |
1284 | |
1285 if (status) | |
1286 (void) fprintf(stdout, "%s ", status); | |
1287 | |
1288 if (max != -1) { | |
1289 if (lstchg == 0) { | |
1290 (void) fprintf(stdout, "00/00/00 "); | |
1291 } else { | |
1292 struct tm *tmp; | |
1293 tmp = gmtime(&lstchg); | |
1294 (void) fprintf(stdout, "%.2d/%.2d/%.2d ", | |
1295 tmp->tm_mon + 1, | |
1296 tmp->tm_mday, | |
1297 tmp->tm_year % 100); | |
1298 } | |
1299 (void) fprintf(stdout, (min >= 0) ? "%4d " : " ", min); | |
1300 (void) fprintf(stdout, "%4d ", max); | |
1301 (void) fprintf(stdout, (warn > 0) ? "%4d " : " ", warn); | |
1302 } | |
1303 (void) fprintf(stdout, "\n"); | |
1304 } | |
1305 | |
1306 void | |
1307 free_attr(attrlist *attributes) | |
1308 { | |
1309 while (attributes) { | |
1310 if (attributes->type == ATTR_PASSWD) | |
1311 free(attributes->data.val_s); | |
1312 attributes = attributes->next; | |
1313 } | |
1314 } | |
1315 | |
1316 /* | |
1317 * | |
1318 * get_namelist_files(): | |
1319 * This function gets a list of user names on the system from | |
1320 * the /etc/passwd file. | |
1321 * | |
1322 */ | |
1323 int | |
108 | 1324 get_namelist_files(char ***namelist_p, int *num_user) |
0 | 1325 { |
1326 FILE *pwfp; | |
1327 struct passwd *pwd; | |
1328 int max_user; | |
1329 int nuser; | |
1330 char **nl; | |
1331 | |
1332 nuser = 0; | |
1333 errno = 0; | |
1334 pwd = NULL; | |
1335 | |
1336 if ((pwfp = fopen(PASSWD, "r")) == NULL) | |
1337 return (NOPERM); | |
1338 | |
1339 /* | |
1340 * find out the actual number of entries in the PASSWD file | |
1341 */ | |
1342 max_user = 1; /* need one slot for terminator NULL */ | |
1343 while ((pwd = fgetpwent(pwfp)) != NULL) | |
1344 max_user++; | |
1345 | |
1346 /* | |
1347 * reset the file stream pointer | |
1348 */ | |
1349 rewind(pwfp); | |
1350 | |
1351 nl = (char **)calloc(max_user, (sizeof (char *))); | |
1352 if (nl == NULL) { | |
1353 (void) fclose(pwfp); | |
1354 return (FMERR); | |
1355 } | |
1356 | |
1357 while ((pwd = fgetpwent(pwfp)) != NULL) { | |
1358 if ((nl[nuser] = strdup(pwd->pw_name)) == NULL) { | |
1359 (void) fclose(pwfp); | |
1360 return (FMERR); | |
1361 } | |
1362 nuser++; | |
1363 } | |
1364 | |
1365 nl[nuser] = NULL; | |
1366 *num_user = nuser; | |
1367 *namelist_p = nl; | |
1368 (void) fclose(pwfp); | |
1369 return (SUCCESS); | |
1370 } | |
1371 | |
1372 /* | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1373 * get_namelist_local |
0 | 1374 * |
1375 */ | |
1376 | |
1377 /* | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1378 * Our private version of the switch frontend for getspent. We want |
11262
b7ebfbf2359e
6874309 Remove NIS+ from Solaris
Raja Andra <Rajagopal.Andra@Sun.COM>
parents:
8821
diff
changeset
|
1379 * to search just the ldap sp file, so we want to bypass |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1380 * normal nsswitch.conf based processing. This implementation |
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1381 * compatible with version 2 of the name service switch. |
0 | 1382 */ |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1383 #define NSS_LDAP_ONLY "ldap" |
0 | 1384 |
1385 extern int str2spwd(const char *, int, void *, char *, int); | |
1386 | |
1387 static DEFINE_NSS_DB_ROOT(db_root); | |
1388 static DEFINE_NSS_GETENT(context); | |
1389 | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1390 static char *local_config; |
0 | 1391 static void |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1392 _lc_nss_initf_shadow(nss_db_params_t *p) |
0 | 1393 { |
1394 p->name = NSS_DBNAM_SHADOW; | |
1395 p->config_name = NSS_DBNAM_PASSWD; /* Use config for "passwd" */ | |
11262
b7ebfbf2359e
6874309 Remove NIS+ from Solaris
Raja Andra <Rajagopal.Andra@Sun.COM>
parents:
8821
diff
changeset
|
1396 p->default_config = local_config; /* Use ldap only */ |
0 | 1397 p->flags = NSS_USE_DEFAULT_CONFIG; |
1398 } | |
1399 | |
1400 static void | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1401 _lc_setspent(void) |
0 | 1402 { |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1403 nss_setent(&db_root, _lc_nss_initf_shadow, &context); |
0 | 1404 } |
1405 | |
1406 static void | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1407 _lc_endspent(void) |
0 | 1408 { |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1409 nss_endent(&db_root, _lc_nss_initf_shadow, &context); |
0 | 1410 nss_delete(&db_root); |
1411 } | |
1412 | |
1413 static struct spwd * | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1414 _lc_getspent_r(struct spwd *result, char *buffer, int buflen) |
0 | 1415 { |
1416 nss_XbyY_args_t arg; | |
1417 char *nam; | |
1418 | |
1419 /* In getXXent_r(), protect the unsuspecting caller from +/- entries */ | |
1420 | |
1421 do { | |
1422 NSS_XbyY_INIT(&arg, result, buffer, buflen, str2spwd); | |
1423 /* No key to fill in */ | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1424 (void) nss_getent(&db_root, _lc_nss_initf_shadow, &context, |
0 | 1425 &arg); |
1426 } while (arg.returnval != 0 && | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1427 (nam = ((struct spwd *)arg.returnval)->sp_namp) != 0 && |
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1428 (*nam == '+' || *nam == '-')); |
0 | 1429 |
1430 return (struct spwd *)NSS_XbyY_FINI(&arg); | |
1431 } | |
1432 | |
1433 static nss_XbyY_buf_t *buffer; | |
1434 | |
1435 static struct spwd * | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1436 _lc_getspent(void) |
0 | 1437 { |
1438 nss_XbyY_buf_t *b; | |
1439 | |
1440 b = NSS_XbyY_ALLOC(&buffer, sizeof (struct spwd), NSS_BUFLEN_SHADOW); | |
1441 | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1442 return (b == 0 ? 0 : _lc_getspent_r(b->result, b->buffer, b->buflen)); |
0 | 1443 } |
1444 | |
1445 int | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1446 get_namelist_local(char ***namelist_p, int *num_user) |
0 | 1447 { |
1448 int nuser = 0; | |
1449 int alloced = 100; | |
1450 char **nl; | |
1451 struct spwd *p; | |
1452 | |
1453 | |
1454 if ((nl = calloc(alloced, sizeof (*nl))) == NULL) | |
1455 return (FMERR); | |
1456 | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1457 (void) _lc_setspent(); |
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1458 while ((p = _lc_getspent()) != NULL) { |
0 | 1459 if ((nl[nuser] = strdup(p->sp_namp)) == NULL) { |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1460 _lc_endspent(); |
0 | 1461 return (FMERR); |
1462 } | |
1463 if (++nuser == alloced) { | |
1464 alloced += 100; | |
1465 nl = realloc(nl, alloced * (sizeof (*nl))); | |
1466 if (nl == NULL) { | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1467 _lc_endspent(); |
0 | 1468 return (FMERR); |
1469 } | |
1470 } | |
1471 } | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1472 (void) _lc_endspent(); |
0 | 1473 nl[nuser] = NULL; |
1474 | |
1475 *namelist_p = nl; | |
1476 *num_user = nuser; /* including NULL */ | |
1477 | |
1478 return (SUCCESS); | |
1479 } | |
1480 | |
1481 int | |
1482 get_namelist(pwu_repository_t repository, char ***namelist, int *num_user) | |
1483 { | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1484 if (IS_LDAP(repository)) { |
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1485 local_config = NSS_LDAP_ONLY; |
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1486 return (get_namelist_local(namelist, num_user)); |
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1487 } else if (IS_FILES(repository)) |
0 | 1488 return (get_namelist_files(namelist, num_user)); |
1489 | |
1490 rusage(); | |
1491 return (BADSYN); | |
1492 } | |
1493 | |
1494 /* | |
1495 * | |
1496 * passwd_exit(): | |
1497 * This function will call exit() with appropriate exit code | |
1498 * according to the input "retcode" value. | |
1499 * It also calls pam_end() to clean-up buffers before exit. | |
1500 * | |
1501 */ | |
1502 | |
1503 void | |
108 | 1504 passwd_exit(int retcode) |
0 | 1505 { |
1506 | |
1507 if (pamh) | |
1508 (void) pam_end(pamh, pam_retval); | |
1509 | |
1510 switch (retcode) { | |
1511 case SUCCESS: | |
1512 break; | |
1513 case NOPERM: | |
1514 (void) fprintf(stderr, "%s\n", gettext(MSG_NP)); | |
1515 break; | |
1516 case BADOPT: | |
1517 (void) fprintf(stderr, "%s\n", gettext(MSG_BS)); | |
1518 break; | |
1519 case FMERR: | |
1520 (void) fprintf(stderr, "%s\n", gettext(MSG_FE)); | |
1521 break; | |
1522 case FATAL: | |
1523 (void) fprintf(stderr, "%s\n", gettext(MSG_FF)); | |
1524 break; | |
1525 case FBUSY: | |
1526 (void) fprintf(stderr, "%s\n", gettext(MSG_FB)); | |
1527 break; | |
1528 case BADSYN: | |
1529 (void) fprintf(stderr, "%s\n", gettext(MSG_NV)); | |
1530 break; | |
1531 case BADAGE: | |
1532 (void) fprintf(stderr, "%s\n", gettext(MSG_AD)); | |
1533 break; | |
1534 case NOMEM: | |
1535 (void) fprintf(stderr, "%s\n", gettext(MSG_NM)); | |
1536 break; | |
1537 default: | |
1538 (void) fprintf(stderr, "%s\n", gettext(MSG_NP)); | |
1539 retcode = NOPERM; | |
1540 break; | |
1541 } | |
1542 /* write password record */ | |
1543 if (event != NULL) { | |
11893
ff6e80260186
6914628 Implement the user object audit token PSARC/2010/001 User object audit token
gww <gww@eng.sun.com>
parents:
11262
diff
changeset
|
1544 struct passwd *pass; |
ff6e80260186
6914628 Implement the user object audit token PSARC/2010/001 User object audit token
gww <gww@eng.sun.com>
parents:
11262
diff
changeset
|
1545 |
ff6e80260186
6914628 Implement the user object audit token PSARC/2010/001 User object audit token
gww <gww@eng.sun.com>
parents:
11262
diff
changeset
|
1546 if ((pass = getpwnam(usrname)) == NULL) { |
ff6e80260186
6914628 Implement the user object audit token PSARC/2010/001 User object audit token
gww <gww@eng.sun.com>
parents:
11262
diff
changeset
|
1547 /* unlikely to ever get here, but ... */ |
ff6e80260186
6914628 Implement the user object audit token PSARC/2010/001 User object audit token
gww <gww@eng.sun.com>
parents:
11262
diff
changeset
|
1548 event->adt_passwd.username = usrname; |
ff6e80260186
6914628 Implement the user object audit token PSARC/2010/001 User object audit token
gww <gww@eng.sun.com>
parents:
11262
diff
changeset
|
1549 } else if (pass->pw_uid != uid) { |
ff6e80260186
6914628 Implement the user object audit token PSARC/2010/001 User object audit token
gww <gww@eng.sun.com>
parents:
11262
diff
changeset
|
1550 /* save target user */ |
ff6e80260186
6914628 Implement the user object audit token PSARC/2010/001 User object audit token
gww <gww@eng.sun.com>
parents:
11262
diff
changeset
|
1551 event->adt_passwd.uid = pass->pw_uid; |
ff6e80260186
6914628 Implement the user object audit token PSARC/2010/001 User object audit token
gww <gww@eng.sun.com>
parents:
11262
diff
changeset
|
1552 event->adt_passwd.username = pass->pw_name; |
ff6e80260186
6914628 Implement the user object audit token PSARC/2010/001 User object audit token
gww <gww@eng.sun.com>
parents:
11262
diff
changeset
|
1553 } |
ff6e80260186
6914628 Implement the user object audit token PSARC/2010/001 User object audit token
gww <gww@eng.sun.com>
parents:
11262
diff
changeset
|
1554 |
0 | 1555 if (adt_put_event(event, |
1556 retcode == SUCCESS ? ADT_SUCCESS : ADT_FAILURE, | |
1557 retcode == SUCCESS ? ADT_SUCCESS : ADT_FAIL_PAM + | |
1558 pam_retval) != 0) { | |
1559 adt_free_event(event); | |
1560 (void) adt_end_session(ah); | |
1561 perror("adt_put_event"); | |
1562 exit(retcode); | |
1563 } | |
1564 adt_free_event(event); | |
1565 } | |
1566 (void) adt_end_session(ah); | |
1567 exit(retcode); | |
1568 } | |
1569 | |
1570 /* | |
1571 * | |
1572 * passwd_conv(): | |
1573 * This is the conv (conversation) function called from | |
1574 * a PAM authentication module to print error messages | |
1575 * or garner information from the user. | |
1576 * | |
1577 */ | |
1578 | |
1579 /*ARGSUSED*/ | |
1580 static int | |
108 | 1581 passwd_conv(int num_msg, struct pam_message **msg, |
1582 struct pam_response **response, void *appdata_ptr) | |
0 | 1583 { |
1584 struct pam_message *m; | |
1585 struct pam_response *r; | |
1586 char *temp; | |
1587 int k, i; | |
1588 | |
1589 if (num_msg <= 0) | |
1590 return (PAM_CONV_ERR); | |
1591 | |
1592 *response = (struct pam_response *)calloc(num_msg, | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1593 sizeof (struct pam_response)); |
0 | 1594 if (*response == NULL) |
1595 return (PAM_BUF_ERR); | |
1596 | |
1597 k = num_msg; | |
1598 m = *msg; | |
1599 r = *response; | |
1600 while (k--) { | |
1601 | |
1602 switch (m->msg_style) { | |
1603 | |
1604 case PAM_PROMPT_ECHO_OFF: | |
1605 temp = getpassphrase(m->msg); | |
1606 if (temp != NULL) { | |
1607 r->resp = strdup(temp); | |
1608 (void) memset(temp, 0, strlen(temp)); | |
1609 if (r->resp == NULL) { | |
1610 /* free responses */ | |
1611 r = *response; | |
1612 for (i = 0; i < num_msg; i++, r++) { | |
1613 if (r->resp) | |
1614 free(r->resp); | |
1615 } | |
1616 free(*response); | |
1617 *response = NULL; | |
1618 return (PAM_BUF_ERR); | |
1619 } | |
1620 } | |
1621 m++; | |
1622 r++; | |
1623 break; | |
1624 | |
1625 case PAM_PROMPT_ECHO_ON: | |
1626 if (m->msg != NULL) { | |
1627 (void) fputs(m->msg, stdout); | |
1628 } | |
1629 r->resp = (char *)calloc(PAM_MAX_RESP_SIZE, | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1630 sizeof (char)); |
0 | 1631 if (r->resp == NULL) { |
1632 /* free responses */ | |
1633 r = *response; | |
1634 for (i = 0; i < num_msg; i++, r++) { | |
1635 if (r->resp) | |
1636 free(r->resp); | |
1637 } | |
1638 free(*response); | |
1639 *response = NULL; | |
1640 return (PAM_BUF_ERR); | |
1641 } | |
1642 if (fgets(r->resp, PAM_MAX_RESP_SIZE-1, stdin)) { | |
1643 int len = strlen(r->resp); | |
1644 if (r->resp[len-1] == '\n') | |
1645 r->resp[len-1] = '\0'; | |
1646 } | |
1647 m++; | |
1648 r++; | |
1649 break; | |
1650 | |
1651 case PAM_ERROR_MSG: | |
1652 if (m->msg != NULL) { | |
1653 (void) fputs(m->msg, stderr); | |
1654 (void) fputs("\n", stderr); | |
1655 } | |
1656 m++; | |
1657 r++; | |
1658 break; | |
1659 case PAM_TEXT_INFO: | |
1660 if (m->msg != NULL) { | |
1661 (void) fputs(m->msg, stdout); | |
1662 (void) fputs("\n", stdout); | |
1663 } | |
1664 m++; | |
1665 r++; | |
1666 break; | |
1667 | |
1668 default: | |
1669 break; | |
1670 } | |
1671 } | |
1672 return (PAM_SUCCESS); | |
1673 } | |
1674 | |
1675 /* | |
1676 * Utilities Functions | |
1677 */ | |
1678 | |
1679 /* | |
1680 * int attrlist_add(attrlist **l, attrtype type, char *val) | |
1681 * add an item, with type "type" and value "val", at the tail of list l. | |
1682 * This functions exits the application on OutOfMem error. | |
1683 */ | |
1684 void | |
1685 attrlist_add(attrlist **l, attrtype type, char *val) | |
1686 { | |
1687 attrlist **w; | |
1688 | |
1689 /* tail insert */ | |
1690 for (w = l; *w != NULL; w = &(*w)->next) | |
1691 ; | |
1692 | |
1693 if ((*w = malloc(sizeof (**w))) == NULL) | |
1694 passwd_exit(NOMEM); | |
1695 | |
1696 (*w)->type = type; | |
1697 (*w)->next = NULL; | |
1698 | |
1699 switch (type) { | |
1700 case ATTR_MIN: | |
1701 case ATTR_WARN: | |
1702 case ATTR_MAX: | |
1703 (*w)->data.val_i = atoi(val); | |
1704 break; | |
1705 default: | |
1706 (*w)->data.val_s = val; | |
1707 break; | |
1708 } | |
1709 } | |
1710 | |
1711 /* | |
1712 * attrlist_reorder(attrlist **l) | |
1713 * Make sure that | |
1714 * - if EXPIRE and MAX or MIN is set, EXPIRE comes after MAX/MIN | |
1715 * - if both MIN and MAX are set, MAX comes before MIN. | |
1716 */ | |
1717 | |
1718 static void | |
1719 attrlist_reorder(attrlist **l) | |
1720 { | |
1721 attrlist **w; | |
1722 attrlist *exp = NULL; /* ATTR_EXPIRE_PASSWORD, if found */ | |
1723 attrlist *max = NULL; /* ATTR_MAX, if found */ | |
1724 | |
1725 if (*l == NULL || (*l)->next == NULL) | |
1726 return; /* order of list with <= one item is ok */ | |
1727 | |
1728 /* | |
1729 * We simply walk the list, take off the EXPIRE and MAX items if | |
1730 * they appear, and put them (first MAX, them EXPIRE) at the end | |
1731 * of the list. | |
1732 */ | |
1733 w = l; | |
1734 while (*w != NULL) { | |
1735 if ((*w)->type == ATTR_EXPIRE_PASSWORD) { | |
1736 exp = *w; | |
1737 *w = (*w)->next; | |
1738 } else if ((*w)->type == ATTR_MAX) { | |
1739 max = *w; | |
1740 *w = (*w)->next; | |
1741 } else | |
1742 w = &(*w)->next; | |
1743 } | |
1744 | |
1745 /* 'w' points to the address of the 'next' field of the last element */ | |
1746 | |
1747 if (max) { | |
1748 *w = max; | |
1749 w = &max->next; | |
1750 } | |
1751 if (exp) { | |
1752 *w = exp; | |
1753 w = &exp->next; | |
1754 } | |
1755 *w = NULL; | |
1756 } | |
1757 | |
1758 void | |
108 | 1759 rusage(void) |
0 | 1760 { |
1761 | |
1762 #define MSG(a) (void) fprintf(stderr, gettext((a))); | |
1763 | |
1764 MSG("usage:\n"); | |
11262
b7ebfbf2359e
6874309 Remove NIS+ from Solaris
Raja Andra <Rajagopal.Andra@Sun.COM>
parents:
8821
diff
changeset
|
1765 MSG("\tpasswd [-r files | -r nis | -r ldap] [name]\n"); |
0 | 1766 MSG("\tpasswd [-r files] [-egh] [name]\n"); |
1767 MSG("\tpasswd [-r files] -sa\n"); | |
1768 MSG("\tpasswd [-r files] -s [name]\n"); | |
1769 MSG("\tpasswd [-r files] [-d|-l|-N|-u] [-f] [-n min] [-w warn] " | |
1770 "[-x max] name\n"); | |
1771 MSG("\tpasswd -r nis [-eg] [name]\n"); | |
1772 MSG("\t\t[-x max] name\n"); | |
1773 MSG("\tpasswd -r ldap [-egh] [name]\n"); | |
8821
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1774 MSG("\tpasswd -r ldap -sa\n"); |
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1775 MSG("\tpasswd -r ldap -s [name]\n"); |
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1776 MSG("\tpasswd -r ldap [-l|-N|-u] [-f] [-n min] [-w warn] " |
7eb613e55044
PSARC 2008/745 nss_ldap shadowAccount support
Michen Chang <Michen.Chang@Sun.COM>
parents:
446
diff
changeset
|
1777 "[-x max] name\n"); |
0 | 1778 #undef MSG |
1779 } |