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