xref: /dragonfly/lib/libc/gen/pw_scan.c (revision 8f13a1c5)
1ed5d5720SPeter Avalos /*-
2ed5d5720SPeter Avalos  * Copyright (c) 1990, 1993, 1994
3ed5d5720SPeter Avalos  *	The Regents of the University of California.  All rights reserved.
4ed5d5720SPeter Avalos  *
5ed5d5720SPeter Avalos  * Redistribution and use in source and binary forms, with or without
6ed5d5720SPeter Avalos  * modification, are permitted provided that the following conditions
7ed5d5720SPeter Avalos  * are met:
8ed5d5720SPeter Avalos  * 1. Redistributions of source code must retain the above copyright
9ed5d5720SPeter Avalos  *    notice, this list of conditions and the following disclaimer.
10ed5d5720SPeter Avalos  * 2. Redistributions in binary form must reproduce the above copyright
11ed5d5720SPeter Avalos  *    notice, this list of conditions and the following disclaimer in the
12ed5d5720SPeter Avalos  *    documentation and/or other materials provided with the distribution.
13dc71b7abSJustin C. Sherrill  * 3. Neither the name of the University nor the names of its contributors
14ed5d5720SPeter Avalos  *    may be used to endorse or promote products derived from this software
15ed5d5720SPeter Avalos  *    without specific prior written permission.
16ed5d5720SPeter Avalos  *
17ed5d5720SPeter Avalos  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18ed5d5720SPeter Avalos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19ed5d5720SPeter Avalos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20ed5d5720SPeter Avalos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21ed5d5720SPeter Avalos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22ed5d5720SPeter Avalos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23ed5d5720SPeter Avalos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24ed5d5720SPeter Avalos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25ed5d5720SPeter Avalos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26ed5d5720SPeter Avalos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27ed5d5720SPeter Avalos  * SUCH DAMAGE.
28ed5d5720SPeter Avalos  *
29ed5d5720SPeter Avalos  * @(#)pw_scan.c	8.3 (Berkeley) 4/2/94
30ed5d5720SPeter Avalos  * $FreeBSD: src/lib/libc/gen/pw_scan.c,v 1.26 2007/01/09 00:27:55 imp Exp $
31ed5d5720SPeter Avalos  * $DragonFly: src/usr.sbin/pwd_mkdb/pw_scan.c,v 1.3 2005/12/05 02:40:27 swildner Exp $
32ed5d5720SPeter Avalos  */
33ed5d5720SPeter Avalos 
34ed5d5720SPeter Avalos /*
35ed5d5720SPeter Avalos  * This module is used to "verify" password entries by chpass(1) and
36ed5d5720SPeter Avalos  * pwd_mkdb(8).
37ed5d5720SPeter Avalos  */
38ed5d5720SPeter Avalos 
39ed5d5720SPeter Avalos #include <sys/param.h>
40ed5d5720SPeter Avalos 
41ed5d5720SPeter Avalos #include <err.h>
42ed5d5720SPeter Avalos #include <errno.h>
43ed5d5720SPeter Avalos #include <fcntl.h>
44ed5d5720SPeter Avalos #include <pwd.h>
45ed5d5720SPeter Avalos #include <stdio.h>
46ed5d5720SPeter Avalos #include <string.h>
47ed5d5720SPeter Avalos #include <stdlib.h>
48ed5d5720SPeter Avalos #include <unistd.h>
49ed5d5720SPeter Avalos 
50ed5d5720SPeter Avalos #include "pw_scan.h"
51ed5d5720SPeter Avalos 
52ed5d5720SPeter Avalos int
__pw_scan(char * bp,struct passwd * pw,int flags)53ed5d5720SPeter Avalos __pw_scan(char *bp, struct passwd *pw, int flags)
54ed5d5720SPeter Avalos {
55*8f13a1c5SDan Cross 	long long id;
56ed5d5720SPeter Avalos 	int root;
57*8f13a1c5SDan Cross 	char *p, *sh;
58*8f13a1c5SDan Cross 	const char *ep;
59ed5d5720SPeter Avalos 
60ed5d5720SPeter Avalos 	pw->pw_fields = 0;
61ed5d5720SPeter Avalos 	if (!(pw->pw_name = strsep(&bp, ":")))		/* login */
62ed5d5720SPeter Avalos 		goto fmt;
63ed5d5720SPeter Avalos 	root = !strcmp(pw->pw_name, "root");
64ed5d5720SPeter Avalos 	if (pw->pw_name[0] && (pw->pw_name[0] != '+' || pw->pw_name[1] == '\0'))
65ed5d5720SPeter Avalos 		pw->pw_fields |= _PWF_NAME;
66ed5d5720SPeter Avalos 
67ed5d5720SPeter Avalos 	if (!(pw->pw_passwd = strsep(&bp, ":")))	/* passwd */
68ed5d5720SPeter Avalos 		goto fmt;
69ed5d5720SPeter Avalos 	if (pw->pw_passwd[0])
70ed5d5720SPeter Avalos 		pw->pw_fields |= _PWF_PASSWD;
71ed5d5720SPeter Avalos 
72ed5d5720SPeter Avalos 	if (!(p = strsep(&bp, ":")))			/* uid */
73ed5d5720SPeter Avalos 		goto fmt;
74ed5d5720SPeter Avalos 	if (p[0])
75ed5d5720SPeter Avalos 		pw->pw_fields |= _PWF_UID;
76ed5d5720SPeter Avalos 	else {
77ed5d5720SPeter Avalos 		if (pw->pw_name[0] != '+' && pw->pw_name[0] != '-') {
78ed5d5720SPeter Avalos 			if (flags & _PWSCAN_WARN)
79ed5d5720SPeter Avalos 				warnx("no uid for user %s", pw->pw_name);
80ed5d5720SPeter Avalos 			return (0);
81ed5d5720SPeter Avalos 		}
82ed5d5720SPeter Avalos 	}
83*8f13a1c5SDan Cross 	id = strtonum(p, 0, UID_MAX, &ep);
84*8f13a1c5SDan Cross 	if (ep != NULL) {
85ed5d5720SPeter Avalos 		if (flags & _PWSCAN_WARN)
86*8f13a1c5SDan Cross 			warnx("%s uid is incorrect: %s", p, ep);
87ed5d5720SPeter Avalos 		return (0);
88ed5d5720SPeter Avalos 	}
89ed5d5720SPeter Avalos 	if (root && id) {
90ed5d5720SPeter Avalos 		if (flags & _PWSCAN_WARN)
91ed5d5720SPeter Avalos 			warnx("root uid should be 0");
92ed5d5720SPeter Avalos 		return (0);
93ed5d5720SPeter Avalos 	}
94*8f13a1c5SDan Cross 	pw->pw_uid = (uid_t)id;
95ed5d5720SPeter Avalos 
96ed5d5720SPeter Avalos 	if (!(p = strsep(&bp, ":")))			/* gid */
97ed5d5720SPeter Avalos 		goto fmt;
98ed5d5720SPeter Avalos 	if (p[0])
99ed5d5720SPeter Avalos 		pw->pw_fields |= _PWF_GID;
100ed5d5720SPeter Avalos 	else {
101ed5d5720SPeter Avalos 		if (pw->pw_name[0] != '+' && pw->pw_name[0] != '-') {
102ed5d5720SPeter Avalos 			if (flags & _PWSCAN_WARN)
103ed5d5720SPeter Avalos 				warnx("no gid for user %s", pw->pw_name);
104ed5d5720SPeter Avalos 			return (0);
105ed5d5720SPeter Avalos 		}
106ed5d5720SPeter Avalos 	}
107*8f13a1c5SDan Cross 	id = strtonum(p, 0, GID_MAX, &ep);
108*8f13a1c5SDan Cross 	if (ep != NULL) {
109ed5d5720SPeter Avalos 		if (flags & _PWSCAN_WARN)
110*8f13a1c5SDan Cross 			warnx("%s gid is incorrect: %s", p, ep);
111ed5d5720SPeter Avalos 		return (0);
112ed5d5720SPeter Avalos 	}
113*8f13a1c5SDan Cross 	pw->pw_gid = (gid_t)id;
114ed5d5720SPeter Avalos 
115ed5d5720SPeter Avalos 	if (flags & _PWSCAN_MASTER ) {
116ed5d5720SPeter Avalos 		if (!(pw->pw_class = strsep(&bp, ":")))	/* class */
117ed5d5720SPeter Avalos 			goto fmt;
118ed5d5720SPeter Avalos 		if (pw->pw_class[0])
119ed5d5720SPeter Avalos 			pw->pw_fields |= _PWF_CLASS;
120ed5d5720SPeter Avalos 
121ed5d5720SPeter Avalos 		if (!(p = strsep(&bp, ":")))		/* change */
122ed5d5720SPeter Avalos 			goto fmt;
123ed5d5720SPeter Avalos 		if (p[0])
124ed5d5720SPeter Avalos 			pw->pw_fields |= _PWF_CHANGE;
125ed5d5720SPeter Avalos 		pw->pw_change = atol(p);
126ed5d5720SPeter Avalos 
127ed5d5720SPeter Avalos 		if (!(p = strsep(&bp, ":")))		/* expire */
128ed5d5720SPeter Avalos 			goto fmt;
129ed5d5720SPeter Avalos 		if (p[0])
130ed5d5720SPeter Avalos 			pw->pw_fields |= _PWF_EXPIRE;
131ed5d5720SPeter Avalos 		pw->pw_expire = atol(p);
132ed5d5720SPeter Avalos 	}
133ed5d5720SPeter Avalos 	if (!(pw->pw_gecos = strsep(&bp, ":")))		/* gecos */
134ed5d5720SPeter Avalos 		goto fmt;
135ed5d5720SPeter Avalos 	if (pw->pw_gecos[0])
136ed5d5720SPeter Avalos 		pw->pw_fields |= _PWF_GECOS;
137ed5d5720SPeter Avalos 
138ed5d5720SPeter Avalos 	if (!(pw->pw_dir = strsep(&bp, ":")))		/* directory */
139ed5d5720SPeter Avalos 		goto fmt;
140ed5d5720SPeter Avalos 	if (pw->pw_dir[0])
141ed5d5720SPeter Avalos 		pw->pw_fields |= _PWF_DIR;
142ed5d5720SPeter Avalos 
143ed5d5720SPeter Avalos 	if (!(pw->pw_shell = strsep(&bp, ":")))		/* shell */
144ed5d5720SPeter Avalos 		goto fmt;
145ed5d5720SPeter Avalos 
146ed5d5720SPeter Avalos 	p = pw->pw_shell;
147ed5d5720SPeter Avalos 	if (root && *p) {				/* empty == /bin/sh */
148ed5d5720SPeter Avalos 		for (setusershell();;) {
149ed5d5720SPeter Avalos 			if (!(sh = getusershell())) {
150ed5d5720SPeter Avalos 				if (flags & _PWSCAN_WARN)
151ed5d5720SPeter Avalos 					warnx("warning, unknown root shell");
152ed5d5720SPeter Avalos 				break;
153ed5d5720SPeter Avalos 			}
154ed5d5720SPeter Avalos 			if (!strcmp(p, sh))
155ed5d5720SPeter Avalos 				break;
156ed5d5720SPeter Avalos 		}
157ed5d5720SPeter Avalos 		endusershell();
158ed5d5720SPeter Avalos 	}
159ed5d5720SPeter Avalos 	if (p[0])
160ed5d5720SPeter Avalos 		pw->pw_fields |= _PWF_SHELL;
161ed5d5720SPeter Avalos 
162ed5d5720SPeter Avalos 	if ((p = strsep(&bp, ":"))) {			/* too many */
163ed5d5720SPeter Avalos fmt:
164ed5d5720SPeter Avalos 		if (flags & _PWSCAN_WARN)
165ed5d5720SPeter Avalos 			warnx("corrupted entry");
166ed5d5720SPeter Avalos 		return (0);
167ed5d5720SPeter Avalos 	}
168ed5d5720SPeter Avalos 	return (1);
169ed5d5720SPeter Avalos }
170