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