Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 10 May 2002 09:47:42 -0700 (PDT)
From:      Jake Burkholder <jake@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 11125 for review
Message-ID:  <200205101647.g4AGlgD46250@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://people.freebsd.org/~peter/p4db/chv.cgi?CH=11125

Change 11125 by jake@jake_sparc64 on 2002/05/10 09:47:35

	More of 11117.

Affected files ...

... //depot/projects/sparc64/usr.bin/chpass/edit.c#4 integrate

Differences ...

==== //depot/projects/sparc64/usr.bin/chpass/edit.c#4 (text+ko) ====

@@ -1,6 +1,13 @@
 /*-
  * Copyright (c) 1990, 1993, 1994
  *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 2002 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * Portions of this software were developed for the FreeBSD Project by
+ * ThinkSec AS and NAI Labs, the Security Research Division of Network
+ * Associates, Inc.  under DARPA/SPAWAR contract N66001-01-C-8035
+ * ("CBOSS"), as part of the DARPA CHATS research program.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -38,7 +45,7 @@
 #endif
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/usr.bin/chpass/edit.c,v 1.21 2002/03/30 13:44:45 dwmalone Exp $");
+__FBSDID("$FreeBSD: src/usr.bin/chpass/edit.c,v 1.22 2002/05/08 00:54:28 des Exp $");
 
 #include <sys/param.h>
 #include <sys/stat.h>
@@ -46,7 +53,6 @@
 #include <ctype.h>
 #include <err.h>
 #include <errno.h>
-#include <md5.h>
 #include <paths.h>
 #include <pwd.h>
 #include <stdio.h>
@@ -55,39 +61,42 @@
 #include <unistd.h>
 
 #include <pw_scan.h>
-#include <pw_util.h>
+#include <libutil.h>
 
 #include "chpass.h"
-#ifdef YP
-#include "pw_yp.h"
-#endif /* YP */
 
-extern char *tempname;
+static int display(const char *tfn, struct passwd *pw);
+static struct passwd *verify(const char *tfn, struct passwd *pw);
 
-void
-edit(struct passwd *pw)
+struct passwd *
+edit(const char *tfn, struct passwd *pw)
 {
-	struct stat begin, end;
-	char *begin_sum, *end_sum;
+	struct passwd *npw;
+	char *line;
+	size_t len;
 
+	if (display(tfn, pw) == -1)
+		return (NULL);
 	for (;;) {
-		if (stat(tempname, &begin))
-			pw_error(tempname, 1, 1);
-		begin_sum = MD5File(tempname, (char *)NULL);
-		pw_edit(1);
-		if (stat(tempname, &end))
-			pw_error(tempname, 1, 1);
-		end_sum = MD5File(tempname, (char *)NULL);
-		if ((begin.st_mtime == end.st_mtime) &&
-		    (strcmp(begin_sum, end_sum) == 0)) {
-			warnx("no changes made");
-			pw_error(NULL, 0, 0);
+		switch (pw_edit(1)) {
+		case -1:
+			return (NULL);
+		case 0:
+			return (pw_dup(pw));
+		default:
+			break;
+		}
+		if ((npw = verify(tfn, pw)) != NULL)
+			return (npw);
+		free(npw);
+		printf("re-edit the password file? ");
+		fflush(stdout);
+		if ((line = fgetln(stdin, &len)) == NULL) {
+			warn("fgetln()");
+			return (NULL);
 		}
-		free(begin_sum);
-		free(end_sum);
-		if (verify(pw))
-			break;
-		pw_prompt();
+		if (len > 0 && (*line == 'N' || *line == 'n'))
+			return (NULL);
 	}
 }
 
@@ -96,23 +105,20 @@
  *	print out the file for the user to edit; strange side-effect:
  *	set conditional flag if the user gets to edit the shell.
  */
-void
-display(int fd, struct passwd *pw)
+static int
+display(const char *tfn, struct passwd *pw)
 {
 	FILE *fp;
 	char *bp, *p;
 
-	if (!(fp = fdopen(fd, "w")))
-		pw_error(tempname, 1, 1);
+	if ((fp = fopen(tfn, "w")) == NULL) {
+		warn("%s", tfn);
+		return (-1);
+	}
 
 	(void)fprintf(fp,
-#ifdef YP
-	    "#Changing %s information for %s.\n", _use_yp ? "NIS" : "user database", pw->pw_name);
-	if (!uid && (!_use_yp || suser_override)) {
-#else
-	    "#Changing user database information for %s.\n", pw->pw_name);
-	if (!uid) {
-#endif /* YP */
+	    "#Changing user information for %s.\n", pw->pw_name);
+	if (master_mode) {
 		(void)fprintf(fp, "Login: %s\n", pw->pw_name);
 		(void)fprintf(fp, "Password: %s\n", pw->pw_passwd);
 		(void)fprintf(fp, "Uid [#]: %lu\n", (unsigned long)pw->pw_uid);
@@ -135,7 +141,8 @@
 		 * necklace, but there's not much else to do.
 		 */
 #else
-	else if ((!list[E_SHELL].restricted && ok_shell(pw->pw_shell)) || !uid)
+	else if ((!list[E_SHELL].restricted && ok_shell(pw->pw_shell)) ||
+	    master_mode)
 		/*
 		 * If change not restrict (table.c) and standard shell
 		 *	OR if root, then allow editing of shell.
@@ -150,120 +157,133 @@
 	p = strsep(&bp, ",");
 	p = strdup(p ? p : "");
 	list[E_NAME].save = p;
-	if (!list[E_NAME].restricted || !uid)
+	if (!list[E_NAME].restricted || master_mode)
 	  (void)fprintf(fp, "Full Name: %s\n", p);
 
-        p = strsep(&bp, ",");
+	p = strsep(&bp, ",");
 	p = strdup(p ? p : "");
 	list[E_LOCATE].save = p;
-	if (!list[E_LOCATE].restricted || !uid)
+	if (!list[E_LOCATE].restricted || master_mode)
 	  (void)fprintf(fp, "Office Location: %s\n", p);
 
-        p = strsep(&bp, ",");
+	p = strsep(&bp, ",");
 	p = strdup(p ? p : "");
 	list[E_BPHONE].save = p;
-	if (!list[E_BPHONE].restricted || !uid)
+	if (!list[E_BPHONE].restricted || master_mode)
 	  (void)fprintf(fp, "Office Phone: %s\n", p);
 
-        p = strsep(&bp, ",");
+	p = strsep(&bp, ",");
 	p = strdup(p ? p : "");
 	list[E_HPHONE].save = p;
-	if (!list[E_HPHONE].restricted || !uid)
+	if (!list[E_HPHONE].restricted || master_mode)
 	  (void)fprintf(fp, "Home Phone: %s\n", p);
 
 	bp = strdup(bp ? bp : "");
 	list[E_OTHER].save = bp;
-	if (!list[E_OTHER].restricted || !uid)
+	if (!list[E_OTHER].restricted || master_mode)
 	  (void)fprintf(fp, "Other information: %s\n", bp);
 
-	(void)fchown(fd, getuid(), getgid());
+	(void)fchown(fileno(fp), getuid(), getgid());
 	(void)fclose(fp);
+	return (0);
 }
 
-int
-verify(struct passwd *pw)
+static struct passwd *
+verify(const char *tfn, struct passwd *pw)
 {
+	struct passwd *npw;
 	ENTRY *ep;
-	char *p;
+	char *buf, *p, *val;
 	struct stat sb;
 	FILE *fp;
-	int len, line;
-	static char buf[LINE_MAX];
+	int line;
+	size_t len;
 
-	if (!(fp = fopen(tempname, "r")))
-		pw_error(tempname, 1, 1);
-	if (fstat(fileno(fp), &sb))
-		pw_error(tempname, 1, 1);
+	if ((pw = pw_dup(pw)) == NULL)
+		return (NULL);
+	if ((fp = fopen(tfn, "r")) == NULL ||
+	    fstat(fileno(fp), &sb) == -1) {
+		warn("%s", tfn);
+		free(pw);
+		return (NULL);
+	}
 	if (sb.st_size == 0) {
 		warnx("corrupted temporary file");
-		goto bad;
+		fclose(fp);
+		free(pw);
+		return (NULL);
 	}
-	line = 0;
-	while (fgets(buf, sizeof(buf), fp)) {
-		line++;
-		if (!buf[0] || buf[0] == '#')
+	val = NULL;
+	for (line = 1; (buf = fgetln(fp, &len)) != NULL; ++line) {
+		if (*buf == '\0' || *buf == '#')
 			continue;
-		if (!(p = strchr(buf, '\n'))) {
-			warnx("line %d too long", line);
-			goto bad;
-		}
-		*p = '\0';
+		while (len > 0 && isspace(buf[len - 1]))
+			--len;
 		for (ep = list;; ++ep) {
 			if (!ep->prompt) {
-				warnx("unrecognized field on line %d", line);
+				warnx("%s: unrecognized field on line %d",
+				    tfn, line);
+				goto bad;
+			}
+			if (ep->len > len)
+				continue;
+			if (strncasecmp(buf, ep->prompt, ep->len) != 0)
+				continue;
+			if (ep->restricted && !master_mode) {
+				warnx("%s: you may not change the %s field",
+				    tfn, ep->prompt);
+				goto bad;
+			}
+			for (p = buf; p < buf + len && *p != ':'; ++p)
+				/* nothing */ ;
+			if (*p != ':') {
+				warnx("%s: line %d corrupted", tfn, line);
 				goto bad;
 			}
-			if (!strncasecmp(buf, ep->prompt, ep->len)) {
-				if (ep->restricted && uid) {
-					warnx(
-					    "you may not change the %s field",
-						ep->prompt);
-					goto bad;
-				}
-				if (!(p = strchr(buf, ':'))) {
-					warnx("line %d corrupted", line);
-					goto bad;
-				}
-				while (isspace(*++p));
-				if (ep->except && strpbrk(p, ep->except)) {
-					warnx(
-				   "illegal character in the \"%s\" field",
-					    ep->prompt);
-					goto bad;
-				}
-				if ((ep->func)(p, pw, ep)) {
-bad:					(void)fclose(fp);
-					return (0);
-				}
-				break;
+			while (++p < buf + len && isspace(*p))
+				/* nothing */ ;
+			free(val);
+			asprintf(&val, "%.*s", (int)(buf + len - p), p);
+			if (val == NULL)
+				goto bad;
+			if (ep->except && strpbrk(val, ep->except)) {
+				warnx("%s: invalid character in \"%s\" field '%s'",
+				    tfn, ep->prompt, val);
+				goto bad;
 			}
+			if ((ep->func)(val, pw, ep))
+				goto bad;
+			break;
 		}
 	}
-	(void)fclose(fp);
+	free(val);
+	fclose(fp);
 
 	/* Build the gecos field. */
-	len = strlen(list[E_NAME].save) + strlen(list[E_BPHONE].save) +
-	    strlen(list[E_HPHONE].save) + strlen(list[E_LOCATE].save) +
-	    strlen(list[E_OTHER].save) + 5;
-	if (!(p = malloc(len)))
-		err(1, NULL);
-	(void)sprintf(pw->pw_gecos = p, "%s,%s,%s,%s,%s", list[E_NAME].save,
-	    list[E_LOCATE].save, list[E_BPHONE].save, list[E_HPHONE].save,
-	    list[E_OTHER].save);
-
-	while ((len = strlen(pw->pw_gecos)) && pw->pw_gecos[len - 1] == ',')
-		pw->pw_gecos[len - 1] = '\0';
-
-	if ((size_t)snprintf(buf, sizeof(buf),
-	    "%s:%s:%lu:%lu:%s:%ld:%ld:%s:%s:%s",
-	    pw->pw_name, pw->pw_passwd, (unsigned long)pw->pw_uid, 
-	    (unsigned long)pw->pw_gid, pw->pw_class, (long)pw->pw_change,
-	    (long)pw->pw_expire, pw->pw_gecos, pw->pw_dir,
-	    pw->pw_shell) >= sizeof(buf)) {
-		warnx("entries too long");
-		free(p);
-		return (0);
+	len = asprintf(&p, "%s,%s,%s,%s,%s", list[E_NAME].save,
+	    list[E_LOCATE].save, list[E_BPHONE].save,
+	    list[E_HPHONE].save, list[E_OTHER].save);
+	if (p == NULL) {
+		warn("asprintf()");
+		free(pw);
+		return (NULL);
 	}
+	while (len > 0 && p[len - 1] == ',')
+		p[--len] = '\0';
+	pw->pw_gecos = p;
+	buf = pw_make(pw);
+	free(pw);
 	free(p);
-	return (__pw_scan(buf, pw, _PWSCAN_WARN|_PWSCAN_MASTER));
+	if (buf == NULL) {
+		warn("pw_make()");
+		return (NULL);
+	}
+	npw = pw_scan(buf, PWSCAN_WARN|PWSCAN_MASTER);
+	free(buf);
+	return (npw);
+bad:
+	free(pw);
+	free(val);
+	fclose(fp);
+	return (NULL);
 }

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe p4-projects" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200205101647.g4AGlgD46250>