pw_scan.c revision 54034
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
341553Srgrimes#ifndef lint
3530260Scharnier#if 0
361553Srgrimesstatic char sccsid[] = "@(#)pw_scan.c	8.3 (Berkeley) 4/2/94";
3730260Scharnier#endif
3830260Scharnierstatic const char rcsid[] =
3950479Speter  "$FreeBSD: head/lib/libc/gen/pw_scan.c 54034 1999-12-02 16:39:15Z sheldonh $";
401553Srgrimes#endif /* not lint */
411553Srgrimes
421553Srgrimes/*
431553Srgrimes * This module is used to "verify" password entries by chpass(1) and
441553Srgrimes * pwd_mkdb(8).
451553Srgrimes */
461553Srgrimes
471553Srgrimes#include <sys/param.h>
481553Srgrimes
491553Srgrimes#include <err.h>
501553Srgrimes#include <fcntl.h>
511553Srgrimes#include <pwd.h>
521553Srgrimes#include <stdio.h>
531553Srgrimes#include <string.h>
541553Srgrimes#include <stdlib.h>
551553Srgrimes#include <unistd.h>
561553Srgrimes
571553Srgrimes#include "pw_scan.h"
581553Srgrimes
5953183Ssheldonh/*
6053183Ssheldonh * Some software assumes that IDs are short.  We should emit warnings
6153183Ssheldonh * for id's which can not be stored in a short, but we are more liberal
6253183Ssheldonh * by default, warning for IDs greater than USHRT_MAX.
6354034Ssheldonh *
6454034Ssheldonh * If pw_big_ids_warning is anything other than -1 on entry to pw_scan()
6554034Ssheldonh * it will be set based on the existance of PW_SCAN_BIG_IDS in the
6654034Ssheldonh * environment.
6753183Ssheldonh */
6854034Ssheldonhint	pw_big_ids_warning = -1;
6953183Ssheldonh
701553Srgrimesint
711553Srgrimespw_scan(bp, pw)
721553Srgrimes	char *bp;
731553Srgrimes	struct passwd *pw;
741553Srgrimes{
751553Srgrimes	long id;
761553Srgrimes	int root;
771553Srgrimes	char *p, *sh;
781553Srgrimes
7954034Ssheldonh	if (pw_big_ids_warning == -1)
8054034Ssheldonh		pw_big_ids_warning = getenv("PW_SCAN_BIG_IDS") == NULL ? 1 : 0;
8154034Ssheldonh
822916Swollman	pw->pw_fields = 0;
831553Srgrimes	if (!(pw->pw_name = strsep(&bp, ":")))		/* login */
841553Srgrimes		goto fmt;
851553Srgrimes	root = !strcmp(pw->pw_name, "root");
862916Swollman	if(pw->pw_name[0] && (pw->pw_name[0] != '+' || pw->pw_name[1] == '\0'))
872916Swollman		pw->pw_fields |= _PWF_NAME;
881553Srgrimes
891553Srgrimes	if (!(pw->pw_passwd = strsep(&bp, ":")))	/* passwd */
901553Srgrimes		goto fmt;
912916Swollman	if(pw->pw_passwd[0]) pw->pw_fields |= _PWF_PASSWD;
921553Srgrimes
931553Srgrimes	if (!(p = strsep(&bp, ":")))			/* uid */
941553Srgrimes		goto fmt;
9552921Seivind	if (p[0])
9652921Seivind		pw->pw_fields |= _PWF_UID;
9752921Seivind	else {
9853581Seivind		if (pw->pw_name[0] != '+' && pw->pw_name[0] != '-') {
9953581Seivind			warnx("no uid for user %s", pw->pw_name);
10053581Seivind			return (0);
10153581Seivind		}
10252921Seivind	}
1031553Srgrimes	id = atol(p);
1041553Srgrimes	if (root && id) {
1051553Srgrimes		warnx("root uid should be 0");
1061553Srgrimes		return (0);
1071553Srgrimes	}
10853183Ssheldonh	if (pw_big_ids_warning && id > USHRT_MAX) {
10953183Ssheldonh		warnx("%s > max uid value (%u)", p, USHRT_MAX);
11050700Ssheldonh		/*return (0);*/ /* THIS SHOULD NOT BE FATAL! */
1111553Srgrimes	}
1121553Srgrimes	pw->pw_uid = id;
1131553Srgrimes
1141553Srgrimes	if (!(p = strsep(&bp, ":")))			/* gid */
1151553Srgrimes		goto fmt;
1162916Swollman	if(p[0]) pw->pw_fields |= _PWF_GID;
1171553Srgrimes	id = atol(p);
11853183Ssheldonh	if (pw_big_ids_warning && id > USHRT_MAX) {
11953183Ssheldonh		warnx("%s > max gid value (%u)", p, USHRT_MAX);
12050700Ssheldonh		/* return (0); This should not be fatal! */
1211553Srgrimes	}
1221553Srgrimes	pw->pw_gid = id;
1231553Srgrimes
1241553Srgrimes	pw->pw_class = strsep(&bp, ":");		/* class */
1252916Swollman	if(pw->pw_class[0]) pw->pw_fields |= _PWF_CLASS;
1262916Swollman
1271553Srgrimes	if (!(p = strsep(&bp, ":")))			/* change */
1281553Srgrimes		goto fmt;
1292916Swollman	if(p[0]) pw->pw_fields |= _PWF_CHANGE;
1301553Srgrimes	pw->pw_change = atol(p);
1312916Swollman
1321553Srgrimes	if (!(p = strsep(&bp, ":")))			/* expire */
1331553Srgrimes		goto fmt;
1342916Swollman	if(p[0]) pw->pw_fields |= _PWF_EXPIRE;
1351553Srgrimes	pw->pw_expire = atol(p);
1362916Swollman
1375964Sdg	if (!(pw->pw_gecos = strsep(&bp, ":")))		/* gecos */
1385964Sdg		goto fmt;
1392916Swollman	if(pw->pw_gecos[0]) pw->pw_fields |= _PWF_GECOS;
1402916Swollman
1415964Sdg	if (!(pw->pw_dir = strsep(&bp, ":")))			/* directory */
1425964Sdg		goto fmt;
1432916Swollman	if(pw->pw_dir[0]) pw->pw_fields |= _PWF_DIR;
1442916Swollman
1451553Srgrimes	if (!(pw->pw_shell = strsep(&bp, ":")))		/* shell */
1461553Srgrimes		goto fmt;
1471553Srgrimes
1481553Srgrimes	p = pw->pw_shell;
1491553Srgrimes	if (root && *p)					/* empty == /bin/sh */
1501553Srgrimes		for (setusershell();;) {
1511553Srgrimes			if (!(sh = getusershell())) {
1521553Srgrimes				warnx("warning, unknown root shell");
1531553Srgrimes				break;
1541553Srgrimes			}
1551553Srgrimes			if (!strcmp(p, sh))
1568857Srgrimes				break;
1571553Srgrimes		}
1582916Swollman	if(p[0]) pw->pw_fields |= _PWF_SHELL;
1591553Srgrimes
16030260Scharnier	if ((p = strsep(&bp, ":"))) {			/* too many */
1611553Srgrimesfmt:		warnx("corrupted entry");
1621553Srgrimes		return (0);
1631553Srgrimes	}
1641553Srgrimes	return (1);
1651553Srgrimes}
166