]>
git.saurik.com Git - apple/system_cmds.git/blob - passwd.tproj/file_passwd.c
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@
34 #include <sys/resource.h>
37 #include "stringops.h"
39 #define TEMP_FILE_TEMPLATE "/var/run/.pwtmpXXXXXX"
40 #define LOCK_FILE "/var/run/.passwd.lock"
42 #define _PASSWD_FILE "/etc/master.passwd"
43 #define _COMPAT_FILE "/etc/passwd"
44 #define _PASSWD_FIELDS 10
47 extern void getpasswd(char *, int, int, int, int, char *, char **, char**, char **);
49 //static int do_compat = 1; (unused)
54 static char s
[BUFSIZE
];
59 fgets(s
, BUFSIZE
, fp
);
60 if (s
== NULL
|| s
[0] == '\0') return NULL
;
62 if (s
[0] == '#') return s
;
71 parse_user(char *line
)
73 static struct passwd pw
= {0};
77 if (pw
.pw_name
!= NULL
) free(pw
.pw_name
);
79 if (pw
.pw_passwd
!= NULL
) free(pw
.pw_passwd
);
81 if (pw
.pw_gecos
!= NULL
) free(pw
.pw_gecos
);
83 if (pw
.pw_dir
!= NULL
) free(pw
.pw_dir
);
85 if (pw
.pw_shell
!= NULL
) free(pw
.pw_shell
);
88 if (pw
.pw_class
!= NULL
) free(pw
.pw_class
);
91 if (line
== NULL
) return (struct passwd
*)NULL
;
92 tokens
= explode(line
, ':');
93 len
= listLength(tokens
);
95 if (len
!= _PASSWD_FIELDS
)
98 return (struct passwd
*)NULL
;
102 pw
.pw_name
= tokens
[i
++];
103 pw
.pw_passwd
= tokens
[i
++];
104 pw
.pw_uid
= atoi(tokens
[i
]);
106 pw
.pw_gid
= atoi(tokens
[i
]);
108 pw
.pw_class
= tokens
[i
++];
109 pw
.pw_change
= atoi(tokens
[i
]);
111 pw
.pw_expire
= atoi(tokens
[i
]);
113 pw
.pw_gecos
= tokens
[i
++];
114 pw
.pw_dir
= tokens
[i
++];
115 pw
.pw_shell
= tokens
[i
++];
121 find_user(char *uname
, FILE *fp
)
128 while (NULL
!= (line
= getline(fp
)))
130 if (line
[0] == '#') continue;
131 pw
= parse_user(line
);
132 if (pw
== (struct passwd
*)NULL
) continue;
133 if (!strcmp(uname
, pw
->pw_name
)) return pw
;
136 pw
= parse_user(NULL
);
137 return (struct passwd
*)NULL
;
141 rewrite_file(char *pwname
, FILE *fp
, struct passwd
*newpw
, char *locn
)
149 sprintf(fname
, "%s.%.5d", TEMP_FILE_TEMPLATE
, getpid());
150 fd
= mkstemps(fname
, 6);
153 fprintf(stderr
, "can't create temporary file \"%s\": ", fname
);
157 if (fchmod(fd
, (S_IRUSR
| S_IWUSR
)) != 0)
161 fprintf(stderr
, "can't set permissions for temporary file \"%s\": ", fname
);
165 tfp
= fdopen(fd
, "w+");
170 fprintf(stderr
, "can't write temporary file \"%s\": ", fname
);
176 if (!strcmp(pwname
, _PASSWD_FILE
))
178 cfp
= fopen(_COMPAT_FILE
, "w");
181 fprintf(stderr
, "warning: can't write compatability file \"%s\": ",
190 fprintf(cfp
, "# 4.3BSD-compatable User Database\n");
192 fprintf(cfp
, "# Note that this file is not consulted for login.\n");
193 fprintf(cfp
, "# It only exisits for compatability with 4.3BSD utilities.\n");
195 fprintf(cfp
, "# This file is automatically re-written by various system utilities.\n");
196 fprintf(cfp
, "# Do not edit this file. Changes will be lost.\n");
202 while (NULL
!= (line
= getline(fp
)))
206 fprintf(tfp
, "%s", line
);
210 pw
= parse_user(line
);
211 if (pw
== (struct passwd
*)NULL
)
213 fprintf(stderr
, "warning: bad format for entry: \"%s\"\n", line
);
214 fprintf(tfp
, "%s\n", line
);
215 if (cfp
!= NULL
) fprintf(cfp
, "%s\n", line
);
219 if (strcmp(newpw
->pw_name
, pw
->pw_name
))
221 fprintf(tfp
, "%s\n", line
);
222 if (cfp
!= NULL
) fprintf(cfp
, "%s\n", line
);
226 fprintf(tfp
, "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n",
227 newpw
->pw_name
, newpw
->pw_passwd
, newpw
->pw_uid
, newpw
->pw_gid
,
228 newpw
->pw_class
, newpw
->pw_change
, newpw
->pw_expire
,
229 newpw
->pw_gecos
, newpw
->pw_dir
, newpw
->pw_shell
);
232 fprintf(cfp
, "%s:",newpw
->pw_name
);
233 if ((newpw
->pw_passwd
== NULL
) || (newpw
->pw_passwd
[0] == '\0'))
237 fprintf(cfp
, "%d:%d:%s:%s:%s\n",
238 newpw
->pw_uid
, newpw
->pw_gid
, newpw
->pw_gecos
,
239 newpw
->pw_dir
, newpw
->pw_shell
);
243 if (cfp
!= NULL
) fclose(cfp
);
249 if (seteuid(getuid()) != 0) {
250 fprintf(stderr
, "Unable to set privileges.");
255 fp
= fopen(pwname
, "w");
258 fprintf(stderr
, "ERROR: can't update \"%s\"\n", pwname
);
259 fprintf(stderr
, "new passwd file is \"%s\"\n", fname
);
264 while (NULL
!= (line
= getline(tfp
)))
266 fprintf(fp
, "%s", line
);
267 if (line
[0] != '#') fprintf(fp
, "\n");
275 _file_passwd_main(char *uname
, char *locn
)
286 fname
= _PASSWD_FILE
;
287 if (locn
!= NULL
) fname
= locn
;
289 umask((S_IRWXG
| S_IRWXO
));
291 if ( lstat(fname
, &sb
) != 0 )
293 fprintf(stderr
, "The file does not exist.\n");
299 if (seteuid(getuid()) != 0) {
300 fprintf(stderr
, "Permission denied.\n");
304 fp
= fopen(fname
, "a+");
311 fprintf(stderr
, "can't write to file \"%s\": ", fname
);
315 if (fchmod(fileno(fp
), (S_IRUSR
| S_IWUSR
)) != 0)
318 fprintf(stderr
, "can't set permissions for file \"%s\": ", fname
);
323 pw
= find_user(uname
, fp
);
324 if (pw
== (struct passwd
*)NULL
)
326 fprintf(stderr
, "user %s not found in file %s\n", uname
, fname
);
331 if ((uid
!= 0) && (uid
!= pw
->pw_uid
))
333 fprintf(stderr
, "Permission denied\n");
338 * Get the new password
340 getpasswd(uname
, (uid
== 0), 5, 0, 0, pw
->pw_passwd
, &ne
, &oc
, &nc
);
342 newpw
.pw_name
= copyString(pw
->pw_name
);
343 newpw
.pw_passwd
= copyString(ne
);
344 newpw
.pw_uid
= pw
->pw_uid
;
345 newpw
.pw_gid
= pw
->pw_gid
;
346 newpw
.pw_class
= copyString(pw
->pw_class
);
347 newpw
.pw_change
= pw
->pw_change
;
348 newpw
.pw_expire
= pw
->pw_expire
;
349 newpw
.pw_gecos
= copyString(pw
->pw_gecos
);
350 newpw
.pw_dir
= copyString(pw
->pw_dir
);
351 newpw
.pw_shell
= copyString(pw
->pw_shell
);
356 rewrite_file(fname
, fp
, &newpw
, locn
);
361 pw
= parse_user(NULL
);
363 free(newpw
.pw_passwd
);
364 free(newpw
.pw_gecos
);
366 free(newpw
.pw_shell
);
367 free(newpw
.pw_class
);
375 void sighandler(int inSignal
)
383 file_passwd(char *uname
, char *locn
)
391 struct sigaction action
= {{0}};
394 /* unlimit the resource limits */
395 rlim
.rlim_cur
= rlim
.rlim_max
= RLIM_INFINITY
;
396 (void)setrlimit(RLIMIT_CPU
, &rlim
);
397 (void)setrlimit(RLIMIT_FSIZE
, &rlim
);
398 (void)setrlimit(RLIMIT_STACK
, &rlim
);
399 (void)setrlimit(RLIMIT_DATA
, &rlim
);
400 (void)setrlimit(RLIMIT_RSS
, &rlim
);
401 (void)setrlimit(RLIMIT_NOFILE
, &rlim
);
404 sigfillset( &action
.sa_mask
);
405 action
.sa_flags
= SA_RESTART
;
406 action
.sa_handler
= sighandler
;
407 sigaction(SIGHUP
, &action
, NULL
);
408 sigaction(SIGINT
, &action
, NULL
); // ctrl-c
409 sigaction(SIGQUIT
, &action
, NULL
);
410 sigaction(SIGABRT
, &action
, NULL
);
411 sigaction(SIGPIPE
, &action
, NULL
);
412 sigaction(SIGALRM
, &action
, NULL
);
413 sigaction(SIGTERM
, &action
, NULL
);
414 sigaction(SIGSTOP
, &action
, NULL
);
415 sigaction(SIGTSTP
, &action
, NULL
);
417 /* Check/create lock file */
418 for (retries
= 0; retries
< 5; retries
++)
420 retVal
= lstat(LOCK_FILE
, &sb
);
423 /* try in 100 milliseconds */
428 fprintf(stderr
, "another passwd process is running.\n");
432 umask((S_IRWXG
| S_IRWXO
));
433 lockFile
= fopen(LOCK_FILE
, "w");
434 if (lockFile
== NULL
)
436 fprintf(stderr
, "can't create lock file.\n");
439 fprintf(lockFile
, "%d\n", getpid());
445 fprintf(stderr
, "can't fork\n");
449 /* Handle the child */
452 retVal
= _file_passwd_main(uname
, locn
);
456 /* Handle the parent */
457 waitResult
= waitpid(pid
, &retVal
, 0);
458 retVal
= (waitResult
== 0) ? WEXITSTATUS(retVal
) : 1;
460 /* delete lock file */