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