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