getspent.c revision 2830:5228d1267a01
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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 *
26 *	nis/getspent.c -- "nis" backend for nsswitch "shadow" database
27 */
28
29#pragma ident	"%Z%%M%	%I%	%E% SMI"
30
31#include <shadow.h>
32#include <string.h>
33#include "nis_common.h"
34
35/*
36 * Most of the information in a struct spwd simply isn't available from the
37 * YP maps, we dummy out all the numeric fields and just get sp_namp and
38 * sp_pwdp (name and password) from the YP passwd map.  Thus we don't
39 * use the str2ent() routine that's passed to us, but instead have our
40 * own dummy routine:
41 *
42 * Return values: 0 = success, 1 = parse error, 2 = erange ...
43 * The structure pointer passed in is a structure in the caller's space
44 * wherein the field pointers would be set to areas in the buffer if
45 * need be. instring and buffer should be separate areas. Let's not
46 * fight over crumbs.
47 */
48static int
49nis_str2spent(instr, lenstr, ent, buffer, buflen)
50	const char		*instr;
51	int			lenstr;
52	void	*ent; /* it is really (struct spwd *) */
53	char	*buffer;
54	int	buflen;
55{
56	struct spwd		*spwd	= (struct spwd *)ent;
57	char			*p, *q, *r;
58
59	/*
60	 * We know that instr != 0 because we're in 'nis', not 'files'
61	 */
62	if ((p = memchr(instr, ':', lenstr)) == 0) {
63		return (NSS_STR_PARSE_PARSE);
64	}
65	if ((q = memchr(p + 1, ':', lenstr - (p + 1 - instr))) == 0) {
66		return (NSS_STR_PARSE_PARSE);
67	}
68	/* Don't bother checking the rest of the YP passwd entry... */
69
70	if (q + 1 - instr > buflen) {
71		return (NSS_STR_PARSE_ERANGE);
72	}
73	/*
74	 * "name:password" is copied
75	 */
76	(void) memcpy(buffer, instr, q - instr);
77	if (spwd) {
78		buffer[p - instr] = '\0';
79		buffer[q - instr] = '\0';
80
81		spwd->sp_namp	= buffer;
82		spwd->sp_pwdp	= buffer + (p + 1 - instr);
83		spwd->sp_lstchg	= -1;
84		spwd->sp_min	= -1;
85		spwd->sp_max	= -1;
86		spwd->sp_warn	= -1;
87		spwd->sp_inact	= -1;
88		spwd->sp_expire	= -1;
89		spwd->sp_flag	= 0;
90	} else {
91		/*
92		 *  NSS2: nscd is running. Return files format.
93		 *
94		 *  name:password:::::::
95		 */
96		r = buffer + (q - instr);
97		*r = '\0';
98		if (strlcat(buffer, ":::::::", buflen) >= buflen)
99			return (NSS_STR_PARSE_ERANGE);
100	}
101	return (NSS_STR_PARSE_SUCCESS);
102}
103
104typedef int	(*cstr2ent_t)(const char *, int, void *, char *, int);
105
106static nss_status_t
107getbyname(be, a)
108	nis_backend_ptr_t	be;
109	void			*a;
110{
111	nss_XbyY_args_t		*argp = (nss_XbyY_args_t *)a;
112	cstr2ent_t		save_c2e;
113	nss_status_t		res;
114	struct spwd 		*spwd;
115	char			*p;
116
117	save_c2e	= argp->str2ent;
118	argp->str2ent	= nis_str2spent;
119	res = _nss_nis_lookup(be, argp, 0, "passwd.byname", argp->key.name, 0);
120	spwd = (struct spwd *)argp->buf.result;
121	/*
122	 * check for the C2 security flag "##" in the passwd field.
123	 * If the first 2 chars in the passwd field is "##", get
124	 * the user's passwd from passwd.adjunct.byname map.
125	 * The lookup to this passwd.adjunct.byname map will only
126	 * succeed if the caller's uid is 0 because only root user
127	 * can use privilege port.
128	 */
129	if (res == NSS_SUCCESS) {
130		if (spwd) {
131			if ((spwd->sp_pwdp) && (*(spwd->sp_pwdp) == '#') &&
132				(*(spwd->sp_pwdp + 1) == '#')) {
133			/* get password from passwd.adjunct.byname */
134				res = _nss_nis_lookup_rsvdport(be, argp, 0,
135						"passwd.adjunct.byname",
136						argp->key.name, 0);
137			}
138		} else {
139			/*
140			 * getent request from nscd
141			 */
142			if ((p = memchr(argp->buf.buffer, ':',
143					argp->buf.buflen)) == NULL)
144				return (NSS_STR_PARSE_PARSE);
145			if (strncmp(p + 1, "##", 2) == 0)
146				/* get password from passwd.adjunct.byname */
147				res = _nss_nis_lookup_rsvdport(be, argp, 0,
148						"passwd.adjunct.byname",
149						argp->key.name, 0);
150			if (res ==  NSS_SUCCESS) {
151				argp->returnval = argp->buf.buffer;
152				argp->returnlen = strlen(argp->buf.buffer);
153			}
154		}
155	}
156
157	argp->str2ent	= save_c2e;
158	return (res);
159}
160
161#define	NIS_SP_GETENT
162
163#ifdef	NIS_SP_GETENT
164
165static nss_status_t
166getent(be, a)
167	nis_backend_ptr_t	be;
168	void			*a;
169{
170	nss_XbyY_args_t		*argp = (nss_XbyY_args_t *)a;
171	cstr2ent_t		save_c2e;
172	nss_status_t		res;
173	struct spwd 		*spwd;
174	char			*p;
175
176	save_c2e	= argp->str2ent;
177	argp->str2ent	= nis_str2spent;
178	res = _nss_nis_getent_rigid(be, argp);
179	spwd = (struct spwd *)argp->buf.result;
180	/*
181	 * check for the C2 security flag "##" in the passwd field.
182	 * If the first 2 chars in the passwd field is "##", get
183	 * the user's passwd from passwd.adjunct.byname map.
184	 * The lookup to this passwd.adjunct.byname map will only
185	 * succeed if the caller's uid is 0 because only root user
186	 * can use privilege port.
187	 */
188	if (res == NSS_SUCCESS) {
189		if (spwd) {
190			if ((spwd->sp_pwdp) && (*(spwd->sp_pwdp) == '#') &&
191				(*(spwd->sp_pwdp + 1) == '#')) {
192				/* get password from passwd.adjunct.byname */
193				res = _nss_nis_lookup_rsvdport(be, argp, 0,
194					"passwd.adjunct.byname",
195					spwd->sp_namp, 0);
196			}
197		} else {
198			/*
199			 * getent request from nscd
200			 */
201			if ((p = memchr(argp->buf.buffer, ':',
202					argp->buf.buflen)) == NULL)
203				return (NSS_STR_PARSE_PARSE);
204			if (strncmp(p + 1, "##", 2) == 0) {
205				/* need the name for the next search */
206				*p = '\0';
207				/* get password from passwd.adjunct.byname */
208				res = _nss_nis_lookup_rsvdport(be, argp, 0,
209					"passwd.adjunct.byname", p, 0);
210			}
211			if (res ==  NSS_SUCCESS) {
212				argp->returnval = argp->buf.buffer;
213				argp->returnlen = strlen(argp->buf.buffer);
214			}
215		}
216	}
217
218	argp->str2ent	= save_c2e;
219	return (res);
220}
221
222#endif	/* NIS_SP_GETENT */
223
224static nis_backend_op_t shadow_ops[] = {
225	_nss_nis_destr,
226	_nss_nis_endent,
227	_nss_nis_setent,
228#ifdef	NIS_SP_GETENT
229	getent,
230#else
231	0,
232#endif	/* NIS_SP_GETENT */
233	getbyname
234};
235
236/*ARGSUSED*/
237nss_backend_t *
238_nss_nis_shadow_constr(dummy1, dummy2, dummy3)
239	const char	*dummy1, *dummy2, *dummy3;
240{
241	return (_nss_nis_constr(shadow_ops,
242				sizeof (shadow_ops) / sizeof (shadow_ops[0]),
243				"passwd.byname"));
244}
245