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