]>
git.saurik.com Git - apple/system_cmds.git/blob - passwd.tproj/file_passwd.c
65a862f27ee8d2e533aed1eba28e937c3491ae9f
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
33 #include <sys/resource.h>
36 #include "stringops.h"
38 #define TEMP_FILE_TEMPLATE "/var/run/.pwtmpXXXXXX"
39 #define LOCK_FILE "/var/run/.passwd.lock"
41 #define _PASSWD_FILE "/etc/master.passwd"
42 #define _COMPAT_FILE "/etc/passwd"
43 #define _PASSWD_FIELDS 10
46 extern void getpasswd(char *, int, int, int, int, char *, char **, char**, char **);
48 //static int do_compat = 1; (unused)
53 static char s
[BUFSIZE
];
58 fgets(s
, BUFSIZE
, fp
);
59 if (s
== NULL
|| s
[0] == '\0') return NULL
;
61 if (s
[0] == '#') return s
;
70 parse_user(char *line
)
72 static struct passwd pw
= {0};
76 if (pw
.pw_name
!= NULL
) free(pw
.pw_name
);
78 if (pw
.pw_passwd
!= NULL
) free(pw
.pw_passwd
);
80 if (pw
.pw_gecos
!= NULL
) free(pw
.pw_gecos
);
82 if (pw
.pw_dir
!= NULL
) free(pw
.pw_dir
);
84 if (pw
.pw_shell
!= NULL
) free(pw
.pw_shell
);
87 if (pw
.pw_class
!= NULL
) free(pw
.pw_class
);
90 if (line
== NULL
) return (struct passwd
*)NULL
;
91 tokens
= explode(line
, ':');
92 len
= listLength(tokens
);
94 if (len
!= _PASSWD_FIELDS
)
97 return (struct passwd
*)NULL
;
101 pw
.pw_name
= tokens
[i
++];
102 pw
.pw_passwd
= tokens
[i
++];
103 pw
.pw_uid
= atoi(tokens
[i
]);
105 pw
.pw_gid
= atoi(tokens
[i
]);
107 pw
.pw_class
= tokens
[i
++];
108 pw
.pw_change
= atoi(tokens
[i
]);
110 pw
.pw_expire
= atoi(tokens
[i
]);
112 pw
.pw_gecos
= tokens
[i
++];
113 pw
.pw_dir
= tokens
[i
++];
114 pw
.pw_shell
= tokens
[i
++];
120 find_user(char *uname
, FILE *fp
)
127 while (NULL
!= (line
= getline(fp
)))
129 if (line
[0] == '#') continue;
130 pw
= parse_user(line
);
131 if (pw
== (struct passwd
*)NULL
) continue;
132 if (!strcmp(uname
, pw
->pw_name
)) return pw
;
135 pw
= parse_user(NULL
);
136 return (struct passwd
*)NULL
;
140 rewrite_file(char *pwname
, FILE *fp
, struct passwd
*newpw
, char *locn
)
148 sprintf(fname
, "%s.%.5d", TEMP_FILE_TEMPLATE
, getpid());
149 fd
= mkstemps(fname
, 6);
152 fprintf(stderr
, "can't create temporary file \"%s\": ", fname
);
156 if (fchmod(fd
, (S_IRUSR
| S_IWUSR
)) != 0)
160 fprintf(stderr
, "can't set permissions for temporary file \"%s\": ", fname
);
164 tfp
= fdopen(fd
, "w+");
169 fprintf(stderr
, "can't write temporary file \"%s\": ", fname
);
175 if (!strcmp(pwname
, _PASSWD_FILE
))
177 cfp
= fopen(_COMPAT_FILE
, "w");
180 fprintf(stderr
, "warning: can't write compatability file \"%s\": ",
189 fprintf(cfp
, "# 4.3BSD-compatable User Database\n");
191 fprintf(cfp
, "# Note that this file is not consulted for login.\n");
192 fprintf(cfp
, "# It only exisits for compatability with 4.3BSD utilities.\n");
194 fprintf(cfp
, "# This file is automatically re-written by various system utilities.\n");
195 fprintf(cfp
, "# Do not edit this file. Changes will be lost.\n");
201 while (NULL
!= (line
= getline(fp
)))
205 fprintf(tfp
, "%s", line
);
209 pw
= parse_user(line
);
210 if (pw
== (struct passwd
*)NULL
)
212 fprintf(stderr
, "warning: bad format for entry: \"%s\"\n", line
);
213 fprintf(tfp
, "%s\n", line
);
214 if (cfp
!= NULL
) fprintf(cfp
, "%s\n", line
);
218 if (strcmp(newpw
->pw_name
, pw
->pw_name
))
220 fprintf(tfp
, "%s\n", line
);
221 if (cfp
!= NULL
) fprintf(cfp
, "%s\n", line
);
225 fprintf(tfp
, "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n",
226 newpw
->pw_name
, newpw
->pw_passwd
, newpw
->pw_uid
, newpw
->pw_gid
,
227 newpw
->pw_class
, newpw
->pw_change
, newpw
->pw_expire
,
228 newpw
->pw_gecos
, newpw
->pw_dir
, newpw
->pw_shell
);
231 fprintf(cfp
, "%s:",newpw
->pw_name
);
232 if ((newpw
->pw_passwd
== NULL
) || (newpw
->pw_passwd
[0] == '\0'))
236 fprintf(cfp
, "%d:%d:%s:%s:%s\n",
237 newpw
->pw_uid
, newpw
->pw_gid
, newpw
->pw_gecos
,
238 newpw
->pw_dir
, newpw
->pw_shell
);
242 if (cfp
!= NULL
) fclose(cfp
);
248 if (seteuid(getuid()) != 0) {
249 fprintf(stderr
, "Unable to set privileges.");
254 fp
= fopen(pwname
, "w");
257 fprintf(stderr
, "ERROR: can't update \"%s\"\n", pwname
);
258 fprintf(stderr
, "new passwd file is \"%s\"\n", fname
);
263 while (NULL
!= (line
= getline(tfp
)))
265 fprintf(fp
, "%s", line
);
266 if (line
[0] != '#') fprintf(fp
, "\n");
274 _file_passwd_main(char *uname
, char *locn
)
285 fname
= _PASSWD_FILE
;
286 if (locn
!= NULL
) fname
= locn
;
288 umask((S_IRWXG
| S_IRWXO
));
290 if ( lstat(fname
, &sb
) != 0 )
292 fprintf(stderr
, "The file does not exist.\n");
298 if (seteuid(getuid()) != 0) {
299 fprintf(stderr
, "Permission denied.\n");
303 fp
= fopen(fname
, "a+");
310 fprintf(stderr
, "can't write to file \"%s\": ", fname
);
314 if (fchmod(fileno(fp
), (S_IRUSR
| S_IWUSR
)) != 0)
317 fprintf(stderr
, "can't set permissions for file \"%s\": ", fname
);
322 pw
= find_user(uname
, fp
);
323 if (pw
== (struct passwd
*)NULL
)
325 fprintf(stderr
, "user %s not found in file %s\n", uname
, fname
);
330 if ((uid
!= 0) && (uid
!= pw
->pw_uid
))
332 fprintf(stderr
, "Permission denied\n");
337 * Get the new password
339 getpasswd(uname
, (uid
== 0), 5, 0, 0, pw
->pw_passwd
, &ne
, &oc
, &nc
);
341 newpw
.pw_name
= copyString(pw
->pw_name
);
342 newpw
.pw_passwd
= copyString(ne
);
343 newpw
.pw_uid
= pw
->pw_uid
;
344 newpw
.pw_gid
= pw
->pw_gid
;
345 newpw
.pw_class
= copyString(pw
->pw_class
);
346 newpw
.pw_change
= pw
->pw_change
;
347 newpw
.pw_expire
= pw
->pw_expire
;
348 newpw
.pw_gecos
= copyString(pw
->pw_gecos
);
349 newpw
.pw_dir
= copyString(pw
->pw_dir
);
350 newpw
.pw_shell
= copyString(pw
->pw_shell
);
355 rewrite_file(fname
, fp
, &newpw
, locn
);
360 pw
= parse_user(NULL
);
362 free(newpw
.pw_passwd
);
363 free(newpw
.pw_gecos
);
365 free(newpw
.pw_shell
);
366 free(newpw
.pw_class
);
374 void sighandler(int inSignal
)
382 file_passwd(char *uname
, char *locn
)
390 struct sigaction action
= {0};
393 /* unlimit the resource limits */
394 rlim
.rlim_cur
= rlim
.rlim_max
= RLIM_INFINITY
;
395 (void)setrlimit(RLIMIT_CPU
, &rlim
);
396 (void)setrlimit(RLIMIT_FSIZE
, &rlim
);
397 (void)setrlimit(RLIMIT_STACK
, &rlim
);
398 (void)setrlimit(RLIMIT_DATA
, &rlim
);
399 (void)setrlimit(RLIMIT_RSS
, &rlim
);
400 (void)setrlimit(RLIMIT_NOFILE
, &rlim
);
403 sigfillset( &action
.sa_mask
);
404 action
.sa_flags
= SA_RESTART
;
405 action
.sa_handler
= sighandler
;
406 sigaction(SIGHUP
, &action
, NULL
);
407 sigaction(SIGINT
, &action
, NULL
); // ctrl-c
408 sigaction(SIGQUIT
, &action
, NULL
);
409 sigaction(SIGABRT
, &action
, NULL
);
410 sigaction(SIGPIPE
, &action
, NULL
);
411 sigaction(SIGALRM
, &action
, NULL
);
412 sigaction(SIGTERM
, &action
, NULL
);
413 sigaction(SIGSTOP
, &action
, NULL
);
414 sigaction(SIGTSTP
, &action
, NULL
);
416 /* Check/create lock file */
417 for (retries
= 0; retries
< 5; retries
++)
419 retVal
= lstat(LOCK_FILE
, &sb
);
422 /* try in 100 milliseconds */
427 fprintf(stderr
, "another passwd process is running.\n");
431 umask((S_IRWXG
| S_IRWXO
));
432 lockFile
= fopen(LOCK_FILE
, "w");
433 if (lockFile
== NULL
)
435 fprintf(stderr
, "can't create lock file.\n");
438 fprintf(lockFile
, "%d\n", getpid());
444 fprintf(stderr
, "can't fork\n");
448 /* Handle the child */
451 retVal
= _file_passwd_main(uname
, locn
);
455 /* Handle the parent */
456 waitResult
= waitpid(pid
, &retVal
, 0);
457 retVal
= (waitResult
== 0) ? WEXITSTATUS(retVal
) : 1;
459 /* delete lock file */