Пример #1
0
/*
 * Copy password file from one descriptor to another, replacing or adding
 * a single record on the way.
 */
int
pw_copy(int ffd, int tfd, const struct passwd *pw, struct passwd *old_pw)
{
	char buf[8192], *end, *line, *p, *q, *r, t;
	struct passwd *fpw;
	size_t len;
	int eof, readlen;

	if ((line = pw_make(pw)) == NULL)
		return (-1);

	eof = 0;
	len = 0;
	p = q = end = buf;
	for (;;) {
		/* find the end of the current line */
		for (p = q; q < end && *q != '\0'; ++q)
			if (*q == '\n')
				break;

		/* if we don't have a complete line, fill up the buffer */
		if (q >= end) {
			if (eof)
				break;
			if ((size_t)(q - p) >= sizeof(buf)) {
				warnx("passwd line too long");
				errno = EINVAL; /* hack */
				goto err;
			}
			if (p < end) {
				q = memmove(buf, p, end - p);
				end -= p - buf;
			} else {
				p = q = end = buf;
			}
			readlen = read(ffd, end, sizeof(buf) - (end - buf));
			if (readlen == -1)
				goto err;
			else
				len = (size_t)readlen;
			if (len == 0 && p == buf)
				break;
			end += len;
			len = end - buf;
			if (len < (ssize_t)sizeof(buf)) {
				eof = 1;
				if (len > 0 && buf[len - 1] != '\n')
					++len, *end++ = '\n';
			}
			continue;
		}

		/* is it a blank line or a comment? */
		for (r = p; r < q && isspace(*r); ++r)
			/* nothing */ ;
		if (r == q || *r == '#') {
			/* yep */
			if (write(tfd, p, q - p + 1) != q - p + 1)
				goto err;
			++q;
			continue;
		}

		/* is it the one we're looking for? */

		t = *q;
		*q = '\0';

		fpw = pw_scan(r, PWSCAN_MASTER);

		/*
		 * fpw is either the struct passwd for the current line,
		 * or NULL if the line is malformed.
		 */

		*q = t;
		if (fpw == NULL || strcmp(fpw->pw_name, pw->pw_name) != 0) {
			/* nope */
			if (fpw != NULL)
				free(fpw);
			if (write(tfd, p, q - p + 1) != q - p + 1)
				goto err;
			++q;
			continue;
		}
		if (old_pw && !pw_equal(fpw, old_pw)) {
			warnx("entry inconsistent");
			free(fpw);
			errno = EINVAL; /* hack */
			goto err;
		}
		free(fpw);

		/* it is, replace it */
		len = strlen(line);
		if (write(tfd, line, len) != (int)len)
			goto err;

		/* we're done, just copy the rest over */
		for (;;) {
			if (write(tfd, q, end - q) != end - q)
				goto err;
			q = buf;
			readlen = read(ffd, buf, sizeof(buf));
			if (readlen == 0)
				break;
			else
				len = (size_t)readlen;
			if (readlen == -1)
				goto err;
			end = buf + len;
		}
		goto done;
	}

	/* if we got here, we have a new entry */
	len = strlen(line);
	if ((size_t)write(tfd, line, len) != len ||
	    write(tfd, "\n", 1) != 1)
		goto err;
 done:
	free(line);
	return (0);
 err:
	free(line);
	return (-1);
}
Пример #2
0
static int
print_user(struct passwd * pwd, int pretty, int v7)
{
	if (!pretty) {
		char            *buf;

		if (!v7)
			pwd->pw_passwd = (pwd->pw_passwd == NULL) ? "" : "*";

		buf = v7 ? pw_make_v7(pwd) : pw_make(pwd);
		printf("%s\n", buf);
		free(buf);
	} else {
		int		j;
		char           *p;
		struct group   *grp = GETGRGID(pwd->pw_gid);
		char            uname[60] = "User &", office[60] = "[None]",
		                wphone[60] = "[None]", hphone[60] = "[None]";
		char		acexpire[32] = "[None]", pwexpire[32] = "[None]";
		struct tm *    tptr;

		if ((p = strtok(pwd->pw_gecos, ",")) != NULL) {
			strlcpy(uname, p, sizeof(uname));
			if ((p = strtok(NULL, ",")) != NULL) {
				strlcpy(office, p, sizeof(office));
				if ((p = strtok(NULL, ",")) != NULL) {
					strlcpy(wphone, p, sizeof(wphone));
					if ((p = strtok(NULL, "")) != NULL) {
						strlcpy(hphone, p,
						    sizeof(hphone));
					}
				}
			}
		}
		/*
		 * Handle '&' in gecos field
		 */
		if ((p = strchr(uname, '&')) != NULL) {
			int             l = strlen(pwd->pw_name);
			int             m = strlen(p);

			memmove(p + l, p + 1, m);
			memmove(p, pwd->pw_name, l);
			*p = (char) toupper((unsigned char)*p);
		}
		if (pwd->pw_expire > (time_t)0 && (tptr = localtime(&pwd->pw_expire)) != NULL)
			strftime(acexpire, sizeof acexpire, "%c", tptr);
		if (pwd->pw_change > (time_t)0 && (tptr = localtime(&pwd->pw_change)) != NULL)
			strftime(pwexpire, sizeof pwexpire, "%c", tptr);
		printf("Login Name: %-15s   #%-12ld Group: %-15s   #%ld\n"
		       " Full Name: %s\n"
		       "      Home: %-26.26s      Class: %s\n"
		       "     Shell: %-26.26s     Office: %s\n"
		       "Work Phone: %-26.26s Home Phone: %s\n"
		       "Acc Expire: %-26.26s Pwd Expire: %s\n",
		       pwd->pw_name, (long) pwd->pw_uid,
		       grp ? grp->gr_name : "(invalid)", (long) pwd->pw_gid,
		       uname, pwd->pw_dir, pwd->pw_class,
		       pwd->pw_shell, office, wphone, hphone,
		       acexpire, pwexpire);
	        SETGRENT();
		j = 0;
		while ((grp=GETGRENT()) != NULL)
		{
			int     i = 0;
			if (grp->gr_mem != NULL) {
				while (grp->gr_mem[i] != NULL)
				{
					if (strcmp(grp->gr_mem[i], pwd->pw_name)==0)
					{
						printf(j++ == 0 ? "    Groups: %s" : ",%s", grp->gr_name);
						break;
					}
					++i;
				}
			}
		}
		ENDGRENT();
		printf("%s", j ? "\n" : "");
	}
	return EXIT_SUCCESS;
}
Пример #3
0
static struct passwd *
verify(const char *tfn, struct passwd *pw)
{
	struct passwd *npw;
	ENTRY *ep;
	char *buf, *p, *val;
	struct stat sb;
	FILE *fp;
	int line;
	size_t len;

	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");
		fclose(fp);
		free(pw);
		return (NULL);
	}
	val = NULL;
	for (line = 1; (buf = fgetln(fp, &len)) != NULL; ++line) {
		if (*buf == '\0' || *buf == '#')
			continue;
		while (len > 0 && isspace(buf[len - 1]))
			--len;
		for (ep = list;; ++ep) {
			if (!ep->prompt) {
				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;
			}
			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;
		}
	}
	free(val);
	fclose(fp);

	/* Build the gecos field. */
	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);
	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);
}