]> git.saurik.com Git - apple/system_cmds.git/blame - passwd.tproj/passwd.c
system_cmds-498.2.tar.gz
[apple/system_cmds.git] / passwd.tproj / passwd.c
CommitLineData
1815bff5 1/*
34d340d7 2 * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved.
1815bff5
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
34d340d7
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
1815bff5
A
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
34d340d7
A
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
1815bff5
A
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
34d340d7
A
23#include <TargetConditionals.h>
24
1815bff5 25#define INFO_FILE 1
34d340d7 26#if !TARGET_OS_EMBEDDED
916eb79e 27#define INFO_NIS 2
34d340d7 28#define INFO_OPEN_DIRECTORY 3
ef8ad44b 29#define INFO_PAM 4
34d340d7 30#endif
1815bff5
A
31
32#ifndef __SLICK__
33#define _PASSWD_FILE "/etc/master.passwd"
34#else
35#define _PASSWD_FILE "/etc/passwd"
36#endif
37
38#include <stdio.h>
39#include <errno.h>
40#include <pwd.h>
41#include <libc.h>
42#include <ctype.h>
43#include <string.h>
1815bff5
A
44#include "stringops.h"
45
46#ifdef __SLICK__
47#define _PASSWORD_LEN 8
48#endif
49
34d340d7
A
50char* progname = "passwd";
51
1815bff5
A
52static char *saltchars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
53
54extern int file_passwd(char *, char *);
1815bff5 55extern int nis_passwd(char *, char *);
34d340d7
A
56#ifdef INFO_OPEN_DIRECTORY
57extern int od_passwd(char *, char *, char*);
58#endif
ef8ad44b
A
59#ifdef INFO_PAM
60extern int pam_passwd(char *);
61#endif
1815bff5
A
62
63void
64getpasswd(char *name, int isroot, int minlen, int mixcase, int nonalpha,
65 char *old_pw, char **new_pw, char **old_clear, char **new_clear)
66{
67 int i, tries, len, pw_ok, upper, lower, alpha, notalpha;
68 int isNull;
69 char *p;
70 static char obuf[_PASSWORD_LEN+1];
71 static char nbuf[_PASSWORD_LEN+1];
72 char salt[9];
73
74 printf("Changing password for %s.\n", name);
75
76 p = "";
77 isNull = 0;
78 if (old_pw == NULL) isNull = 1;
79 if ((isNull == 0) && (old_pw[0] == '\0')) isNull = 1;
80 if ((isroot == 0) && (isNull == 0))
81 {
82 p = getpass("Old password:");
83 if (strcmp(crypt(p, old_pw), old_pw))
84 {
85 errno = EACCES;
86 fprintf(stderr, "Sorry\n");
87 exit(1);
88 }
89 }
20e66415
A
90 //strcpy(obuf, p);
91 snprintf( obuf, sizeof(obuf), "%s", p );
92
1815bff5
A
93 tries = 0;
94 nbuf[0] = '\0';
95 for (;;)
96 {
97 p = getpass("New password:");
98 if (!*p)
99 {
100 printf("Password unchanged.\n");
101 exit(0);
102 }
103
104 tries++;
105 len = strlen(p);
106 upper = 0;
107 lower = 0;
108 alpha = 0;
109 notalpha = 0;
110 for (i = 0; i < len; i++)
111 {
112 if (isupper(p[i])) upper++;
113 if (islower(p[i])) lower++;
114 if (isalpha(p[i])) alpha++;
115 else notalpha++;
116 }
117
118
119 pw_ok = 1;
120 if (len < minlen) pw_ok = 0;
121 if ((mixcase == 1) && ((upper == 0) || (lower == 0))) pw_ok = 0;
122 if ((nonalpha == 1) && (notalpha == 0)) pw_ok = 0;
123
124 /*
125 * An insistent root may override security options.
126 */
127 if ((isroot == 1) && (tries > 2)) pw_ok = 1;
128
129 /*
130 * A very insistent user may override security options.
131 */
132 if (tries > 4) pw_ok = 1;
133
134 if (pw_ok == 0)
135 {
136 if (len < minlen)
137 printf("Password must be at least %d characters long.\n", minlen);
138 if ((mixcase == 1) && ((upper == 0) || (lower == 0)))
139 printf("Password must contain both upper and lower case characters.\n");
140 if ((nonalpha == 1) && (notalpha == 0))
141 printf("Password must contain non-alphabetic characters.\n");
142 continue;
143 }
144
20e66415
A
145 //strcpy(nbuf, p);
146 snprintf( nbuf, sizeof(nbuf), "%s", p );
147
1815bff5
A
148 if (!strcmp(nbuf, getpass("Retype new password:"))) break;
149
150 printf("Mismatch; try again, EOF to quit.\n");
151 }
152
153 /*
154 * Create a random salt
155 */
156 srandom((int)time((time_t *)NULL));
157 salt[0] = saltchars[random() % strlen(saltchars)];
158 salt[1] = saltchars[random() % strlen(saltchars)];
159 salt[2] = '\0';
160 *new_pw = crypt(nbuf, salt);
161
162 *old_clear = obuf;
163 *new_clear = nbuf;
164 return;
165}
166
167void
168usage()
169{
ef8ad44b 170 fprintf(stderr, "usage: %s [-i infosystem] -l location]] [-u authname] [name]\n", progname);
34d340d7 171 fprintf(stderr, " infosystem:\n");
1815bff5 172 fprintf(stderr, " file\n");
34d340d7
A
173 fprintf(stderr, " NIS\n");
174 fprintf(stderr, " OpenDirectory\n");
ef8ad44b 175 fprintf(stderr, " PAM\n");
34d340d7
A
176 fprintf(stderr, " location (for infosystem):\n");
177 fprintf(stderr, " file location is path to file (default is %s)\n", _PASSWD_FILE);
178 fprintf(stderr, " NIS location is NIS domain name\n");
179 fprintf(stderr, " OpenDirectory location is directory node name\n");
ef8ad44b 180 fprintf(stderr, " PAM location is not used\n");
1815bff5
A
181 exit(1);
182}
183
184int
185main(int argc, char *argv[])
186{
34d340d7
A
187 char* user = NULL;
188 char* locn = NULL;
189 char* auth = NULL;
190 int infosystem, ch;
2fc1e207 191 int free_user = 0;
20e66415 192
ef8ad44b
A
193#ifdef INFO_PAM
194 infosystem = INFO_PAM;
195#else
34d340d7 196#ifdef INFO_OPEN_DIRECTORY
34d340d7
A
197 infosystem = INFO_OPEN_DIRECTORY;
198#else
199 infosystem = INFO_FILE;
200#endif
ef8ad44b
A
201#endif
202
203#ifdef INFO_OPEN_DIRECTORY
204 /* PAM is the default infosystem, but we still want to use OpenDirectory directly when run by root */
205 if (0 == getuid())
206 infosystem = INFO_OPEN_DIRECTORY;
207#endif
208
34d340d7
A
209 while ((ch = getopt(argc, argv, "i:l:u:")) != -1)
210 switch(ch) {
211 case 'i':
212 if (!strcasecmp(optarg, "file")) {
213 infosystem = INFO_FILE;
916eb79e 214#ifdef INFO_NIS
34d340d7
A
215 } else if (!strcasecmp(optarg, "NIS")) {
216 infosystem = INFO_NIS;
217 } else if (!strcasecmp(optarg, "YP")) {
218 infosystem = INFO_NIS;
916eb79e 219#endif
34d340d7
A
220#ifdef INFO_OPEN_DIRECTORY
221 } else if (!strcasecmp(optarg, "opendirectory")) {
222 infosystem = INFO_OPEN_DIRECTORY;
ef8ad44b
A
223#endif
224#ifdef INFO_PAM
225 } else if (!strcasecmp(optarg, "PAM")) {
226 infosystem = INFO_PAM;
34d340d7
A
227#endif
228 } else {
229 fprintf(stderr, "%s: Unknown info system \'%s\'.\n",
230 progname, optarg);
1815bff5
A
231 usage();
232 }
34d340d7
A
233 break;
234 case 'l':
235 locn = optarg;
236 break;
237 case 'u':
238 auth = optarg;
239 break;
240 case '?':
241 default:
242 usage();
243 break;
244 }
245 argc -= optind;
246 argv += optind;
1815bff5 247
34d340d7
A
248 if (argc > 1) {
249 usage();
250 } else if (argc == 1) {
251 user = argv[0];
1815bff5
A
252 }
253
ef8ad44b
A
254#ifdef INFO_PAM
255 if (INFO_PAM == infosystem && NULL != locn)
256 usage();
257#endif
258
1815bff5
A
259 if (user == NULL)
260 {
2fc1e207 261 /*
1815bff5
A
262 * Verify that the login name exists.
263 * lukeh 24 Dec 1997
264 */
2fc1e207
A
265
266 /* getlogin() is the wrong thing to use here because it returns the wrong user after su */
267 /* sns 5 Jan 2005 */
268
269 struct passwd * userRec = getpwuid(getuid());
270 if (userRec != NULL && userRec->pw_name != NULL) {
271 /* global static mem is volatile; must strdup */
272 user = strdup(userRec->pw_name);
273 free_user = 1;
274 }
275
276 if (user == NULL)
1815bff5
A
277 {
278 fprintf(stderr, "you don't have a login name\n");
279 exit(1);
280 }
281 }
282
283 switch (infosystem)
284 {
1815bff5
A
285 case INFO_FILE:
286 file_passwd(user, locn);
287 break;
916eb79e 288#ifdef INFO_NIS
1815bff5
A
289 case INFO_NIS:
290 nis_passwd(user, locn);
291 break;
916eb79e 292#endif
34d340d7
A
293#ifdef INFO_OPEN_DIRECTORY
294 case INFO_OPEN_DIRECTORY:
295 od_passwd(user, locn, auth);
20e66415 296 break;
ef8ad44b
A
297#endif
298#ifdef INFO_PAM
299 case INFO_PAM:
300 pam_passwd(user);
301 break;
34d340d7 302#endif
1815bff5 303 }
2fc1e207
A
304
305 if (free_user == 1)
306 free(user);
307
1815bff5
A
308 exit(0);
309}
310