diff options
Diffstat (limited to 'system_cmds/chkpasswd.tproj/file_passwd.c')
-rw-r--r-- | system_cmds/chkpasswd.tproj/file_passwd.c | 276 |
1 files changed, 276 insertions, 0 deletions
diff --git a/system_cmds/chkpasswd.tproj/file_passwd.c b/system_cmds/chkpasswd.tproj/file_passwd.c new file mode 100644 index 0000000..90f54f2 --- /dev/null +++ b/system_cmds/chkpasswd.tproj/file_passwd.c @@ -0,0 +1,276 @@ +/* + * Copyright (c) 1999-2016 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <pwd.h> +#include <errno.h> +#include <string.h> +#include "stringops.h" + +#define TEMP_FILE "/tmp/.pwtmp" + +#define _PASSWD_FILE "/etc/master.passwd" +#define _COMPAT_FILE "/etc/passwd" +#define _PASSWD_FIELDS 10 +#define BUFSIZE 8192 + +#include "passwd.h" + +static char * +_getline(FILE *fp) +{ + static char s[BUFSIZE]; + size_t len; + + s[0] = '\0'; + + fgets(s, BUFSIZE, fp); + if (s[0] == '\0') return NULL; + + if (s[0] == '#') return s; + + len = strlen(s) - 1; + s[len] = '\0'; + + return s; +} + +static struct passwd * +parse_user(char *line) +{ + static struct passwd pw = {0}; + char **tokens; + int i, len; + + if (pw.pw_name != NULL) free(pw.pw_name); + pw.pw_name = NULL; + if (pw.pw_passwd != NULL) free(pw.pw_passwd); + pw.pw_passwd = NULL; + if (pw.pw_gecos != NULL) free(pw.pw_gecos); + pw.pw_gecos = NULL; + if (pw.pw_dir != NULL) free(pw.pw_dir); + pw.pw_dir = NULL; + if (pw.pw_shell != NULL) free(pw.pw_shell); + pw.pw_shell = NULL; + + if (pw.pw_class != NULL) free(pw.pw_class); + pw.pw_class = NULL; + + if (line == NULL) return (struct passwd *)NULL; + tokens = explode(line, ':'); + len = listLength(tokens); + + if (len != _PASSWD_FIELDS) + { + freeList(tokens); + return (struct passwd *)NULL; + } + + i = 0; + pw.pw_name = tokens[i++]; + pw.pw_passwd = tokens[i++]; + pw.pw_uid = atoi(tokens[i]); + free(tokens[i++]); + pw.pw_gid = atoi(tokens[i]); + free(tokens[i++]); + pw.pw_class = tokens[i++]; + pw.pw_change = atoi(tokens[i]); + free(tokens[i++]); + pw.pw_expire = atoi(tokens[i]); + free(tokens[i++]); + pw.pw_gecos = tokens[i++]; + pw.pw_dir = tokens[i++]; + pw.pw_shell = tokens[i++]; + + return &pw; +} + +static struct passwd * +find_user(char *uname, FILE *fp) +{ + char *line; + struct passwd *pw; + + rewind(fp); + + while (NULL != (line = _getline(fp))) + { + if (line[0] == '#') continue; + pw = parse_user(line); + if (pw == (struct passwd *)NULL) continue; + if (!strcmp(uname, pw->pw_name)) return pw; + } + + pw = parse_user(NULL); + return (struct passwd *)NULL; +} + +#if 0 +static void +rewrite_file(char *pwname, FILE *fp, struct passwd *newpw) +{ + char *line; + struct passwd *pw; + FILE *tfp, *cfp; + char fname[256]; + + sprintf(fname, "%s.%d", TEMP_FILE, getpid()); + + tfp = fopen(fname, "w+"); + if (tfp == NULL) + { + fprintf(stderr, "can't write temporary file \"%s\": ", fname); + perror(""); + exit(1); + } + + cfp = NULL; + if (!strcmp(pwname, _PASSWD_FILE)) + { + cfp = fopen(_COMPAT_FILE, "w"); + if (cfp == NULL) + { + fprintf(stderr, "warning: can't write compatability file \"%s\": ", + _COMPAT_FILE); + perror(""); + } + } + + if (cfp != NULL) + { + fprintf(cfp, "#\n"); + fprintf(cfp, "# 4.3BSD-compatable User Database\n"); + fprintf(cfp, "#\n"); + fprintf(cfp, "# Note that this file is not consulted for login.\n"); + fprintf(cfp, "# It only exisits for compatability with 4.3BSD utilities.\n"); + fprintf(cfp, "#\n"); + fprintf(cfp, "# This file is automatically re-written by various system utilities.\n"); + fprintf(cfp, "# Do not edit this file. Changes will be lost.\n"); + fprintf(cfp, "#\n"); + } + + rewind(fp); + + while (NULL != (line = _getline(fp))) + { + if (line[0] == '#') + { + fprintf(tfp, "%s", line); + continue; + } + + pw = parse_user(line); + if (pw == (struct passwd *)NULL) + { + fprintf(stderr, "warning: bad format for entry: \"%s\"\n", line); + fprintf(tfp, "%s\n", line); + if (cfp != NULL) fprintf(cfp, "%s\n", line); + continue; + } + + if (strcmp(newpw->pw_name, pw->pw_name)) + { + fprintf(tfp, "%s\n", line); + if (cfp != NULL) fprintf(cfp, "%s\n", line); + continue; + } + + fprintf(tfp, "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n", + newpw->pw_name, newpw->pw_passwd, newpw->pw_uid, newpw->pw_gid, + newpw->pw_class, newpw->pw_change, newpw->pw_expire, + newpw->pw_gecos, newpw->pw_dir, newpw->pw_shell); + if (cfp != NULL) + { + fprintf(cfp, "%s:",newpw->pw_name); + if ((newpw->pw_passwd == NULL) || (newpw->pw_passwd[0] == '\0')) + fprintf(cfp, ":"); + else + fprintf(cfp, "*:"); + fprintf(cfp, "%d:%d:%s:%s:%s\n", + newpw->pw_uid, newpw->pw_gid, newpw->pw_gecos, + newpw->pw_dir, newpw->pw_shell); + } + } + + if (cfp != NULL) fclose(cfp); + fclose(fp); + if (unlink(pwname) < 0) + { + fprintf(stderr, "can't update \"%s\": ", pwname); + perror(""); + } + + rewind(tfp); + + fp = fopen(pwname, "w"); + if (fp == NULL) + { + fprintf(stderr, "ERROR: lost file \"%s\"\n", pwname); + fprintf(stderr, "new passwd file is \"%s\"\n", fname); + perror("open"); + exit(1); + } + + while (NULL != (line = _getline(tfp))) + { + fprintf(fp, "%s", line); + if (line[0] != '#') fprintf(fp, "\n"); + } + fclose(fp); + fclose(tfp); + unlink(fname); +} +#endif /* 0 */ + +int +file_check_passwd(char *uname, char *locn) +{ + FILE *fp; + char *fname; + struct passwd *pw; + + fname = _PASSWD_FILE; + if (locn != NULL) fname = locn; + + if (access(fname,R_OK) || (fp = fopen(fname, "r")) == NULL) + { + fprintf(stderr, "can't read file \"%s\": ", fname); + perror(""); + exit(1); + } + + + pw = find_user(uname, fp); + if (pw == (struct passwd *)NULL) + { + fprintf(stderr, "user %s not found in file %s\n", uname, fname); + exit(1); + } + + checkpasswd(uname, pw->pw_passwd); + fclose(fp); + + return 0; +} |