xref: /illumos-gate/usr/src/lib/nsswitch/nis/common/getspent.c (revision 587644a8567e6a9533f88401daa59cbd78c4632f)
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  */
48 static int
49 nis_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 
104 typedef int	(*cstr2ent_t)(const char *, int, void *, char *, int);
105 
106 static nss_status_t
107 getbyname(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 
165 static nss_status_t
166 getent(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 
224 static 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*/
237 nss_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