/* * 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 #include #include #include #include #include #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; }