xref: /titanic_52/usr/src/lib/nsswitch/compat/common/getpwent.c (revision ea8dc4b6d2251b437950c0056bc626b311c73c27)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  *	getpwent.c
24  *
25  *	Copyright (c) 1988-1992 Sun Microsystems Inc
26  *	All Rights Reserved.
27  *
28  * lib/nsswitch/compat/getpwent.c -- name-service-switch backend for getpwnam()
29  *   et al that does 4.x compatibility.  It looks in /etc/passwd; if it finds
30  *   passwd entries there that begin with "+" or "-", it consults other
31  *   services.  By default it uses NIS (YP), but the user can override this
32  *   with a "passwd_compat" entry in /etc/nsswitch.conf, e.g.
33  *			passwd_compat: nisplus
34  *
35  * This code tries to produce the same results as the 4.x code, even when
36  *   the latter seems ill thought-out (mostly in the handling of netgroups,
37  *   "-", and the combination thereof).  Bug-compatible, in other words.
38  *   Though we do try to be more reasonable about the format of "+" and "-"
39  *   entries here, i.e. you don't have to pad them with spurious colons and
40  *   bogus uid/gid values.
41  *
42  * Caveats:
43  *    -	More than one source may be specified, with the usual switch semantics,
44  *	but having multiple sources here is definitely odd.
45  *    -	People who recursively specify "compat" deserve what they get.
46  *    -	Entries that begin with "+@" or "-@" are interpreted using
47  *	getnetgrent() and innetgr(), which use the "netgroup" entry in
48  *	/etc/nsswitch.conf.  If the sources for "passwd_compat" and "netgroup"
49  *	differ, everything should work fine, but the semantics will be pretty
50  *	confusing.
51  */
52 
53 #pragma ident	"%Z%%M%	%I%	%E% SMI"
54 
55 #include <pwd.h>
56 #include <shadow.h>		/* For PASSWD (pathname to passwd file) */
57 #include <stdlib.h>
58 #include <strings.h>
59 #include "compat_common.h"
60 
61 static DEFINE_NSS_DB_ROOT(db_root);
62 
63 void
64 _nss_initf_passwd_compat(p)
65 	nss_db_params_t	*p;
66 {
67 	p->name		  = NSS_DBNAM_PASSWD;
68 	p->config_name	  = NSS_DBNAM_PASSWD_COMPAT;
69 	p->default_config = NSS_DEFCONF_PASSWD_COMPAT;
70 }
71 
72 static const char *
73 get_pwname(argp)
74 	nss_XbyY_args_t		*argp;
75 {
76 	struct passwd		*p = (struct passwd *)argp->returnval;
77 
78 	return (p->pw_name);
79 }
80 
81 static int
82 check_pwname(argp)
83 	nss_XbyY_args_t		*argp;
84 {
85 	struct passwd		*p = (struct passwd *)argp->returnval;
86 
87 	return (strcmp(p->pw_name, argp->key.name) == 0);
88 }
89 
90 static nss_status_t
91 getbyname(be, a)
92 	compat_backend_ptr_t	be;
93 	void			*a;
94 {
95 	nss_XbyY_args_t		*argp = (nss_XbyY_args_t *) a;
96 
97 	return (_nss_compat_XY_all(be, argp,
98 				check_pwname, NSS_DBOP_PASSWD_BYNAME));
99 }
100 
101 static int
102 check_pwuid(argp)
103 	nss_XbyY_args_t		*argp;
104 {
105 	struct passwd		*p = (struct passwd *)argp->returnval;
106 
107 	return (p->pw_uid == argp->key.uid);
108 }
109 
110 static nss_status_t
111 getbyuid(be, a)
112 	compat_backend_ptr_t	be;
113 	void			*a;
114 {
115 	nss_XbyY_args_t		*argp = (nss_XbyY_args_t *) a;
116 
117 	return (_nss_compat_XY_all(be, argp,
118 				check_pwuid, NSS_DBOP_PASSWD_BYUID));
119 }
120 
121 /*ARGSUSED*/
122 static int
123 merge_pwents(be, argp, fields)
124 	compat_backend_ptr_t	be;
125 	nss_XbyY_args_t		*argp;
126 	const char		**fields;
127 {
128 	struct passwd		*pw	= (struct passwd *)argp->buf.result;
129 	char			*buf	= malloc(NSS_LINELEN_PASSWD);
130 	char			*s;
131 	int			parsestat;
132 
133 	if (buf == 0) {
134 		return (NSS_STR_PARSE_PARSE);
135 		/* Really "out of memory", but PARSE_PARSE will have to do */
136 	}
137 	/*
138 	 * Don't allow overriding of
139 	 *	- username
140 	 *	- uid
141 	 *	- gid
142 	 * That's what the SunOS 4.x code did;  who are we to question it...
143 	 */
144 	s = buf;
145 	sprintf(s, "%s:", pw->pw_name);
146 	s += strlen(s);
147 	if (fields[1] != 0) {
148 		strcpy(s, fields[1]);
149 	} else {
150 		strcpy(s, pw->pw_passwd);
151 		if (pw->pw_age != 0) {
152 			s += strlen(s);
153 /* ====> Does this do the right thing? */
154 			sprintf(s, ",%s", pw->pw_age);
155 		}
156 	}
157 	s += strlen(s);
158 	sprintf(s, ":%d:%d:%s:%s:%s",
159 		pw->pw_uid,
160 		pw->pw_gid,
161 		fields[4] != 0 ? fields[4] : pw->pw_gecos,
162 		fields[5] != 0 ? fields[5] : pw->pw_dir,
163 		fields[6] != 0 ? fields[6] : pw->pw_shell);
164 	s += strlen(s);
165 	parsestat = (*argp->str2ent)(buf, s - buf,
166 				    argp->buf.result,
167 				    argp->buf.buffer,
168 				    argp->buf.buflen);
169 	free(buf);
170 	return (parsestat);
171 }
172 
173 static compat_backend_op_t passwd_ops[] = {
174 	_nss_compat_destr,
175 	_nss_compat_endent,
176 	_nss_compat_setent,
177 	_nss_compat_getent,
178 	getbyname,
179 	getbyuid
180 };
181 
182 /*ARGSUSED*/
183 nss_backend_t *
184 _nss_compat_passwd_constr(dummy1, dummy2, dummy3)
185 	const char	*dummy1, *dummy2, *dummy3;
186 {
187 	return (_nss_compat_constr(passwd_ops,
188 				sizeof (passwd_ops) / sizeof (passwd_ops[0]),
189 				PASSWD,
190 				NSS_LINELEN_PASSWD,
191 				&db_root,
192 				_nss_initf_passwd_compat,
193 				1,
194 				get_pwname,
195 				merge_pwents));
196 }
197