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
nis_str2spent(instr,lenstr,ent,buffer,buflen)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
getbyname(be,a)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
getent(be,a)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 *
_nss_nis_shadow_constr(dummy1,dummy2,dummy3)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