pw_scan.c revision 104891
11553Srgrimes/*-
21553Srgrimes * Copyright (c) 1990, 1993, 1994
31553Srgrimes *	The Regents of the University of California.  All rights reserved.
41553Srgrimes *
51553Srgrimes * Redistribution and use in source and binary forms, with or without
61553Srgrimes * modification, are permitted provided that the following conditions
71553Srgrimes * are met:
81553Srgrimes * 1. Redistributions of source code must retain the above copyright
91553Srgrimes *    notice, this list of conditions and the following disclaimer.
101553Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111553Srgrimes *    notice, this list of conditions and the following disclaimer in the
121553Srgrimes *    documentation and/or other materials provided with the distribution.
131553Srgrimes * 3. All advertising materials mentioning features or use of this software
141553Srgrimes *    must display the following acknowledgement:
151553Srgrimes *	This product includes software developed by the University of
161553Srgrimes *	California, Berkeley and its contributors.
171553Srgrimes * 4. Neither the name of the University nor the names of its contributors
181553Srgrimes *    may be used to endorse or promote products derived from this software
191553Srgrimes *    without specific prior written permission.
201553Srgrimes *
211553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221553Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231553Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241553Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251553Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261553Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271553Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281553Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291553Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301553Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311553Srgrimes * SUCH DAMAGE.
321553Srgrimes */
331553Srgrimes
3490039Sobrien#if defined(LIBC_SCCS) && !defined(lint)
351553Srgrimesstatic char sccsid[] = "@(#)pw_scan.c	8.3 (Berkeley) 4/2/94";
3690039Sobrien#endif /* LIBC_SCCS and not lint */
3790039Sobrien#include <sys/cdefs.h>
3890039Sobrien__FBSDID("$FreeBSD: head/lib/libc/gen/pw_scan.c 104891 2002-10-11 11:35:30Z maxim $");
391553Srgrimes
401553Srgrimes/*
411553Srgrimes * This module is used to "verify" password entries by chpass(1) and
421553Srgrimes * pwd_mkdb(8).
431553Srgrimes */
441553Srgrimes
451553Srgrimes#include <sys/param.h>
461553Srgrimes
471553Srgrimes#include <err.h>
4857868Spaul#include <errno.h>
491553Srgrimes#include <fcntl.h>
501553Srgrimes#include <pwd.h>
511553Srgrimes#include <stdio.h>
521553Srgrimes#include <string.h>
531553Srgrimes#include <stdlib.h>
541553Srgrimes#include <unistd.h>
551553Srgrimes
561553Srgrimes#include "pw_scan.h"
571553Srgrimes
5853183Ssheldonh/*
5953183Ssheldonh * Some software assumes that IDs are short.  We should emit warnings
6091925Sdd * for id's which cannot be stored in a short, but we are more liberal
6153183Ssheldonh * by default, warning for IDs greater than USHRT_MAX.
6254034Ssheldonh *
6391925Sdd * If pw_big_ids_warning is -1 on entry to pw_scan(), it will be set based
6491925Sdd * on the existence of PW_SCAN_BIG_IDS in the environment.
6553183Ssheldonh */
6665532Snectarstatic int	pw_big_ids_warning = -1;
6753183Ssheldonh
681553Srgrimesint
6965532Snectar__pw_scan(char *bp, struct passwd *pw, int flags)
701553Srgrimes{
7157868Spaul	uid_t id;
721553Srgrimes	int root;
73103958Smaxim	char *ep, *p, *sh;
741553Srgrimes
7554034Ssheldonh	if (pw_big_ids_warning == -1)
7654034Ssheldonh		pw_big_ids_warning = getenv("PW_SCAN_BIG_IDS") == NULL ? 1 : 0;
7754034Ssheldonh
782916Swollman	pw->pw_fields = 0;
791553Srgrimes	if (!(pw->pw_name = strsep(&bp, ":")))		/* login */
801553Srgrimes		goto fmt;
811553Srgrimes	root = !strcmp(pw->pw_name, "root");
8287348Sdes	if (pw->pw_name[0] && (pw->pw_name[0] != '+' || pw->pw_name[1] == '\0'))
832916Swollman		pw->pw_fields |= _PWF_NAME;
841553Srgrimes
851553Srgrimes	if (!(pw->pw_passwd = strsep(&bp, ":")))	/* passwd */
861553Srgrimes		goto fmt;
8787348Sdes	if (pw->pw_passwd[0])
8887348Sdes		pw->pw_fields |= _PWF_PASSWD;
891553Srgrimes
901553Srgrimes	if (!(p = strsep(&bp, ":")))			/* uid */
911553Srgrimes		goto fmt;
9252921Seivind	if (p[0])
9352921Seivind		pw->pw_fields |= _PWF_UID;
9452921Seivind	else {
9553581Seivind		if (pw->pw_name[0] != '+' && pw->pw_name[0] != '-') {
9665532Snectar			if (flags & _PWSCAN_WARN)
9765532Snectar				warnx("no uid for user %s", pw->pw_name);
9853581Seivind			return (0);
9953581Seivind		}
10052921Seivind	}
101103958Smaxim	id = strtoul(p, &ep, 10);
10257868Spaul	if (errno == ERANGE) {
10365532Snectar		if (flags & _PWSCAN_WARN)
10473725Sdwmalone			warnx("%s > max uid value (%lu)", p, ULONG_MAX);
10557868Spaul		return (0);
10657868Spaul	}
107104348Smaxim	if (*ep != '\0') {
108103958Smaxim		if (flags & _PWSCAN_WARN)
109103958Smaxim			warnx("%s uid is incorrect", p);
110103958Smaxim		return (0);
111103958Smaxim	}
1121553Srgrimes	if (root && id) {
11365532Snectar		if (flags & _PWSCAN_WARN)
11465532Snectar			warnx("root uid should be 0");
1151553Srgrimes		return (0);
1161553Srgrimes	}
11765532Snectar	if (flags & _PWSCAN_WARN && pw_big_ids_warning && id > USHRT_MAX) {
11857868Spaul		warnx("%s > recommended max uid value (%u)", p, USHRT_MAX);
11950700Ssheldonh		/*return (0);*/ /* THIS SHOULD NOT BE FATAL! */
1201553Srgrimes	}
1211553Srgrimes	pw->pw_uid = id;
1221553Srgrimes
1231553Srgrimes	if (!(p = strsep(&bp, ":")))			/* gid */
1241553Srgrimes		goto fmt;
12587348Sdes	if (p[0])
12687348Sdes		pw->pw_fields |= _PWF_GID;
127104891Smaxim	else {
128104891Smaxim		if (pw->pw_name[0] != '+' && pw->pw_name[0] != '-') {
129104891Smaxim			if (flags & _PWSCAN_WARN)
130104891Smaxim				warnx("no gid for user %s", pw->pw_name);
131104891Smaxim			return (0);
132104891Smaxim		}
133104891Smaxim	}
134103958Smaxim	id = strtoul(p, &ep, 10);
13557868Spaul	if (errno == ERANGE) {
13665532Snectar		if (flags & _PWSCAN_WARN)
13773725Sdwmalone			warnx("%s > max gid value (%lu)", p, ULONG_MAX);
13857868Spaul		return (0);
13957868Spaul	}
140104348Smaxim	if (*ep != '\0') {
141103958Smaxim		if (flags & _PWSCAN_WARN)
142103958Smaxim			warnx("%s gid is incorrect", p);
143103958Smaxim		return (0);
144103958Smaxim	}
14565532Snectar	if (flags & _PWSCAN_WARN && pw_big_ids_warning && id > USHRT_MAX) {
14657868Spaul		warnx("%s > recommended max gid value (%u)", p, USHRT_MAX);
14750700Ssheldonh		/* return (0); This should not be fatal! */
1481553Srgrimes	}
1491553Srgrimes	pw->pw_gid = id;
1501553Srgrimes
15165532Snectar	if (flags & _PWSCAN_MASTER ) {
15287348Sdes		if (!(pw->pw_class = strsep(&bp, ":")))	/* class */
15387347Sdes			goto fmt;
15487348Sdes		if (pw->pw_class[0])
15587348Sdes			pw->pw_fields |= _PWF_CLASS;
15665532Snectar
15787348Sdes		if (!(p = strsep(&bp, ":")))		/* change */
15865532Snectar			goto fmt;
15987348Sdes		if (p[0])
16087348Sdes			pw->pw_fields |= _PWF_CHANGE;
16165532Snectar		pw->pw_change = atol(p);
16265532Snectar
16387348Sdes		if (!(p = strsep(&bp, ":")))		/* expire */
16465532Snectar			goto fmt;
16587348Sdes		if (p[0])
16687348Sdes			pw->pw_fields |= _PWF_EXPIRE;
16765532Snectar		pw->pw_expire = atol(p);
16865532Snectar	}
1695964Sdg	if (!(pw->pw_gecos = strsep(&bp, ":")))		/* gecos */
1705964Sdg		goto fmt;
17187348Sdes	if (pw->pw_gecos[0])
17287348Sdes		pw->pw_fields |= _PWF_GECOS;
1732916Swollman
17487348Sdes	if (!(pw->pw_dir = strsep(&bp, ":")))		/* directory */
1755964Sdg		goto fmt;
17687348Sdes	if (pw->pw_dir[0])
17787348Sdes		pw->pw_fields |= _PWF_DIR;
1782916Swollman
1791553Srgrimes	if (!(pw->pw_shell = strsep(&bp, ":")))		/* shell */
1801553Srgrimes		goto fmt;
1811553Srgrimes
1821553Srgrimes	p = pw->pw_shell;
1831553Srgrimes	if (root && *p)					/* empty == /bin/sh */
1841553Srgrimes		for (setusershell();;) {
1851553Srgrimes			if (!(sh = getusershell())) {
18665532Snectar				if (flags & _PWSCAN_WARN)
18765532Snectar					warnx("warning, unknown root shell");
1881553Srgrimes				break;
1891553Srgrimes			}
1901553Srgrimes			if (!strcmp(p, sh))
1918857Srgrimes				break;
1921553Srgrimes		}
19387348Sdes	if (p[0])
19487348Sdes		pw->pw_fields |= _PWF_SHELL;
1951553Srgrimes
19630260Scharnier	if ((p = strsep(&bp, ":"))) {			/* too many */
19765532Snectarfmt:
19865532Snectar		if (flags & _PWSCAN_WARN)
19965532Snectar			warnx("corrupted entry");
2001553Srgrimes		return (0);
2011553Srgrimes	}
2021553Srgrimes	return (1);
2031553Srgrimes}
204