]>
git.saurik.com Git - apple/system_cmds.git/blob - passwd.tproj/file_passwd.c
1fca2f9fb352f6da7b992326a6a2d178126cb0cd
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 "stringops.h"
35 #define TEMP_FILE_TEMPLATE "/var/run/.pwtmpXXXXXX"
36 #define LOCK_FILE "/var/run/.passwd.lock"
38 #define _PASSWD_FILE "/etc/master.passwd"
39 #define _COMPAT_FILE "/etc/passwd"
40 #define _PASSWD_FIELDS 10
43 extern void getpasswd(char *, int, int, int, int, char *, char **, char**, char **);
45 //static int do_compat = 1; (unused)
50 static char s
[BUFSIZE
];
55 fgets(s
, BUFSIZE
, fp
);
56 if (s
== NULL
|| s
[0] == '\0') return NULL
;
58 if (s
[0] == '#') return s
;
67 parse_user(char *line
)
69 static struct passwd pw
= {0};
73 if (pw
.pw_name
!= NULL
) free(pw
.pw_name
);
75 if (pw
.pw_passwd
!= NULL
) free(pw
.pw_passwd
);
77 if (pw
.pw_gecos
!= NULL
) free(pw
.pw_gecos
);
79 if (pw
.pw_dir
!= NULL
) free(pw
.pw_dir
);
81 if (pw
.pw_shell
!= NULL
) free(pw
.pw_shell
);
84 if (pw
.pw_class
!= NULL
) free(pw
.pw_class
);
87 if (line
== NULL
) return (struct passwd
*)NULL
;
88 tokens
= explode(line
, ':');
89 len
= listLength(tokens
);
91 if (len
!= _PASSWD_FIELDS
)
94 return (struct passwd
*)NULL
;
98 pw
.pw_name
= tokens
[i
++];
99 pw
.pw_passwd
= tokens
[i
++];
100 pw
.pw_uid
= atoi(tokens
[i
]);
102 pw
.pw_gid
= atoi(tokens
[i
]);
104 pw
.pw_class
= tokens
[i
++];
105 pw
.pw_change
= atoi(tokens
[i
]);
107 pw
.pw_expire
= atoi(tokens
[i
]);
109 pw
.pw_gecos
= tokens
[i
++];
110 pw
.pw_dir
= tokens
[i
++];
111 pw
.pw_shell
= tokens
[i
++];
117 find_user(char *uname
, FILE *fp
)
124 while (NULL
!= (line
= getline(fp
)))
126 if (line
[0] == '#') continue;
127 pw
= parse_user(line
);
128 if (pw
== (struct passwd
*)NULL
) continue;
129 if (!strcmp(uname
, pw
->pw_name
)) return pw
;
132 pw
= parse_user(NULL
);
133 return (struct passwd
*)NULL
;
137 rewrite_file(char *pwname
, FILE *fp
, struct passwd
*newpw
, char *locn
)
145 sprintf(fname
, "%s.%.5d", TEMP_FILE_TEMPLATE
, getpid());
146 fd
= mkstemps(fname
, 6);
149 fprintf(stderr
, "can't create temporary file \"%s\": ", fname
);
153 if (fchmod(fd
, (S_IRUSR
| S_IWUSR
)) != 0)
157 fprintf(stderr
, "can't set permissions for temporary file \"%s\": ", fname
);
161 tfp
= fdopen(fd
, "w+");
166 fprintf(stderr
, "can't write temporary file \"%s\": ", fname
);
172 if (!strcmp(pwname
, _PASSWD_FILE
))
174 cfp
= fopen(_COMPAT_FILE
, "w");
177 fprintf(stderr
, "warning: can't write compatability file \"%s\": ",
186 fprintf(cfp
, "# 4.3BSD-compatable User Database\n");
188 fprintf(cfp
, "# Note that this file is not consulted for login.\n");
189 fprintf(cfp
, "# It only exisits for compatability with 4.3BSD utilities.\n");
191 fprintf(cfp
, "# This file is automatically re-written by various system utilities.\n");
192 fprintf(cfp
, "# Do not edit this file. Changes will be lost.\n");
198 while (NULL
!= (line
= getline(fp
)))
202 fprintf(tfp
, "%s", line
);
206 pw
= parse_user(line
);
207 if (pw
== (struct passwd
*)NULL
)
209 fprintf(stderr
, "warning: bad format for entry: \"%s\"\n", line
);
210 fprintf(tfp
, "%s\n", line
);
211 if (cfp
!= NULL
) fprintf(cfp
, "%s\n", line
);
215 if (strcmp(newpw
->pw_name
, pw
->pw_name
))
217 fprintf(tfp
, "%s\n", line
);
218 if (cfp
!= NULL
) fprintf(cfp
, "%s\n", line
);
222 fprintf(tfp
, "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n",
223 newpw
->pw_name
, newpw
->pw_passwd
, newpw
->pw_uid
, newpw
->pw_gid
,
224 newpw
->pw_class
, newpw
->pw_change
, newpw
->pw_expire
,
225 newpw
->pw_gecos
, newpw
->pw_dir
, newpw
->pw_shell
);
228 fprintf(cfp
, "%s:",newpw
->pw_name
);
229 if ((newpw
->pw_passwd
== NULL
) || (newpw
->pw_passwd
[0] == '\0'))
233 fprintf(cfp
, "%d:%d:%s:%s:%s\n",
234 newpw
->pw_uid
, newpw
->pw_gid
, newpw
->pw_gecos
,
235 newpw
->pw_dir
, newpw
->pw_shell
);
239 if (cfp
!= NULL
) fclose(cfp
);
245 if (setuid(getuid()) != 0) {
246 fprintf(stderr
, "Unable to set privileges.");
251 fp
= fopen(pwname
, "w");
254 fprintf(stderr
, "ERROR: can't update \"%s\"\n", pwname
);
255 fprintf(stderr
, "new passwd file is \"%s\"\n", fname
);
260 while (NULL
!= (line
= getline(tfp
)))
262 fprintf(fp
, "%s", line
);
263 if (line
[0] != '#') fprintf(fp
, "\n");
271 _file_passwd_main(char *uname
, char *locn
)
280 fname
= _PASSWD_FILE
;
281 if (locn
!= NULL
) fname
= locn
;
283 umask((S_IRWXG
| S_IRWXO
));
284 fp
= fopen(fname
, "a+");
287 fprintf(stderr
, "can't write to file \"%s\": ", fname
);
291 if (fchmod(fileno(fp
), (S_IRUSR
| S_IWUSR
)) != 0)
294 fprintf(stderr
, "can't set permissions for file \"%s\": ", fname
);
299 pw
= find_user(uname
, fp
);
300 if (pw
== (struct passwd
*)NULL
)
302 fprintf(stderr
, "user %s not found in file %s\n", uname
, fname
);
307 if ((uid
!= 0) && (uid
!= pw
->pw_uid
))
309 fprintf(stderr
, "Permission denied\n");
314 * Get the new password
316 getpasswd(uname
, (uid
== 0), 5, 0, 0, pw
->pw_passwd
, &ne
, &oc
, &nc
);
318 newpw
.pw_name
= copyString(pw
->pw_name
);
319 newpw
.pw_passwd
= copyString(ne
);
320 newpw
.pw_uid
= pw
->pw_uid
;
321 newpw
.pw_gid
= pw
->pw_gid
;
322 newpw
.pw_class
= copyString(pw
->pw_class
);
323 newpw
.pw_change
= pw
->pw_change
;
324 newpw
.pw_expire
= pw
->pw_expire
;
325 newpw
.pw_gecos
= copyString(pw
->pw_gecos
);
326 newpw
.pw_dir
= copyString(pw
->pw_dir
);
327 newpw
.pw_shell
= copyString(pw
->pw_shell
);
332 rewrite_file(fname
, fp
, &newpw
, locn
);
337 pw
= parse_user(NULL
);
339 free(newpw
.pw_passwd
);
340 free(newpw
.pw_gecos
);
342 free(newpw
.pw_shell
);
343 free(newpw
.pw_class
);
351 void sighandler(int inSignal
)
359 file_passwd(char *uname
, char *locn
)
367 struct sigaction action
= {0};
370 sigfillset( &action
.sa_mask
);
371 action
.sa_flags
= SA_RESTART
;
372 action
.sa_handler
= sighandler
;
373 sigaction(SIGHUP
, &action
, NULL
);
374 sigaction(SIGINT
, &action
, NULL
); // ctrl-c
375 sigaction(SIGQUIT
, &action
, NULL
);
376 sigaction(SIGABRT
, &action
, NULL
);
377 sigaction(SIGPIPE
, &action
, NULL
);
378 sigaction(SIGALRM
, &action
, NULL
);
379 sigaction(SIGTERM
, &action
, NULL
);
380 sigaction(SIGSTOP
, &action
, NULL
);
381 sigaction(SIGTSTP
, &action
, NULL
);
383 /* Check/create lock file */
384 for (retries
= 0; retries
< 5; retries
++)
386 retVal
= lstat(LOCK_FILE
, &sb
);
389 /* try in 100 milliseconds */
394 fprintf(stderr
, "another passwd process is running.\n");
398 umask((S_IRWXG
| S_IRWXO
));
399 lockFile
= fopen(LOCK_FILE
, "w");
400 if (lockFile
== NULL
)
402 fprintf(stderr
, "can't create lock file.\n");
405 fprintf(lockFile
, "%d\n", getpid());
411 fprintf(stderr
, "can't fork\n");
415 /* Handle the child */
418 retVal
= _file_passwd_main(uname
, locn
);
422 /* Handle the parent */
423 waitResult
= waitpid(pid
, &retVal
, 0);
424 retVal
= (waitResult
== 0) ? WEXITSTATUS(retVal
) : 1;
426 /* delete lock file */