]>
Commit | Line | Data |
---|---|---|
0ecb606c | 1 | /* Copyright (c) 1997,1999,2001,2003,2005,2006 Free Software Foundation, Inc. |
e61abf83 | 2 | This file is part of the GNU C Library. |
a680290a | 3 | Contributed by Thorsten Kukuk <kukuk@suse.de>, 1997. |
e61abf83 UD |
4 | |
5 | The GNU C Library is free software; you can redistribute it and/or | |
41bdb6e2 AJ |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
e61abf83 UD |
9 | |
10 | The GNU C Library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
41bdb6e2 | 13 | Lesser General Public License for more details. |
e61abf83 | 14 | |
41bdb6e2 AJ |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; if not, write to the Free | |
17 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | |
18 | 02111-1307 USA. */ | |
e61abf83 UD |
19 | |
20 | #include <nss.h> | |
21 | #include <ctype.h> | |
22 | #include <errno.h> | |
23 | #include <stdio.h> | |
24 | #include <string.h> | |
4360eafd | 25 | #include <libintl.h> |
e61abf83 | 26 | #include <syslog.h> |
26dee9c4 | 27 | #include <rpc/rpc.h> |
e61abf83 | 28 | #include <rpcsvc/nis.h> |
26dee9c4 UD |
29 | #include <rpc/key_prot.h> |
30 | extern int xdecrypt (char *, char *); | |
e61abf83 UD |
31 | |
32 | #include <nss-nisplus.h> | |
33 | ||
26dee9c4 | 34 | /* If we haven't found the entry, we give a SUCCESS and an empty key back. */ |
e61abf83 | 35 | enum nss_status |
d71b808a | 36 | _nss_nisplus_getpublickey (const char *netname, char *pkey, int *errnop) |
e61abf83 UD |
37 | { |
38 | nis_result *res; | |
39 | enum nss_status retval; | |
0ecb606c | 40 | char buf[NIS_MAXNAMELEN + 2]; |
40a55d20 | 41 | size_t slen; |
e61abf83 UD |
42 | char *domain, *cptr; |
43 | int len; | |
44 | ||
45 | pkey[0] = 0; | |
46 | ||
47 | if (netname == NULL) | |
48 | { | |
d71b808a | 49 | *errnop = EINVAL; |
e61abf83 UD |
50 | return NSS_STATUS_UNAVAIL; |
51 | } | |
52 | ||
53 | domain = strchr (netname, '@'); | |
54 | if (!domain) | |
55 | return NSS_STATUS_UNAVAIL; | |
56 | domain++; | |
57 | ||
40a55d20 UD |
58 | slen = snprintf (buf, NIS_MAXNAMELEN, |
59 | "[auth_name=%s,auth_type=DES],cred.org_dir.%s", | |
60 | netname, domain); | |
e61abf83 | 61 | |
a680290a UD |
62 | if (slen >= NIS_MAXNAMELEN) |
63 | { | |
64 | *errnop = EINVAL; | |
65 | return NSS_STATUS_UNAVAIL; | |
66 | } | |
67 | ||
40a55d20 UD |
68 | if (buf[slen - 1] != '.') |
69 | { | |
70 | buf[slen++] = '.'; | |
71 | buf[slen] = '\0'; | |
72 | } | |
e61abf83 | 73 | |
2d7da676 UD |
74 | res = nis_list (buf, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH, |
75 | NULL, NULL); | |
e61abf83 | 76 | |
901956a5 UD |
77 | if (res == NULL) |
78 | { | |
79 | *errnop = ENOMEM; | |
80 | return NSS_STATUS_TRYAGAIN; | |
81 | } | |
e61abf83 UD |
82 | retval = niserr2nss (res->status); |
83 | ||
84 | if (retval != NSS_STATUS_SUCCESS) | |
85 | { | |
86 | if (retval == NSS_STATUS_TRYAGAIN) | |
d71b808a | 87 | *errnop = errno; |
26dee9c4 UD |
88 | if (res->status == NIS_NOTFOUND) |
89 | retval = NSS_STATUS_SUCCESS; | |
e61abf83 UD |
90 | nis_freeresult (res); |
91 | return retval; | |
92 | } | |
93 | ||
0ecb606c | 94 | if (NIS_RES_NUMOBJ (res) > 1) |
e61abf83 UD |
95 | { |
96 | /* | |
97 | * More than one principal with same uid? | |
98 | * something wrong with cred table. Should be unique | |
99 | * Warn user and continue. | |
100 | */ | |
0ecb606c | 101 | syslog (LOG_ERR, _("DES entry for netname %s not unique\n"), netname); |
e61abf83 UD |
102 | nis_freeresult (res); |
103 | return NSS_STATUS_SUCCESS; | |
104 | } | |
105 | ||
0ecb606c JJ |
106 | len = ENTRY_LEN (NIS_RES_OBJECT (res), 3); |
107 | memcpy (pkey, ENTRY_VAL (NIS_RES_OBJECT (res),3), len); | |
e61abf83 UD |
108 | pkey[len] = 0; |
109 | cptr = strchr (pkey, ':'); | |
110 | if (cptr) | |
111 | cptr[0] = '\0'; | |
112 | nis_freeresult (res); | |
113 | ||
114 | return NSS_STATUS_SUCCESS; | |
115 | } | |
116 | ||
0ecb606c | 117 | |
e61abf83 | 118 | enum nss_status |
d71b808a UD |
119 | _nss_nisplus_getsecretkey (const char *netname, char *skey, char *passwd, |
120 | int *errnop) | |
e61abf83 UD |
121 | { |
122 | nis_result *res; | |
123 | enum nss_status retval; | |
0ecb606c | 124 | char buf[NIS_MAXNAMELEN + 2]; |
40a55d20 | 125 | size_t slen; |
e61abf83 UD |
126 | char *domain, *cptr; |
127 | int len; | |
128 | ||
129 | skey[0] = 0; | |
130 | ||
131 | if (netname == NULL) | |
132 | { | |
d71b808a | 133 | *errnop = EINVAL; |
e61abf83 UD |
134 | return NSS_STATUS_UNAVAIL; |
135 | } | |
136 | ||
137 | domain = strchr (netname, '@'); | |
138 | if (!domain) | |
139 | return NSS_STATUS_UNAVAIL; | |
140 | domain++; | |
141 | ||
40a55d20 UD |
142 | slen = snprintf (buf, NIS_MAXNAMELEN, |
143 | "[auth_name=%s,auth_type=DES],cred.org_dir.%s", | |
144 | netname, domain); | |
e61abf83 | 145 | |
a680290a UD |
146 | if (slen >= NIS_MAXNAMELEN) |
147 | { | |
148 | *errnop = EINVAL; | |
149 | return NSS_STATUS_UNAVAIL; | |
150 | } | |
151 | ||
40a55d20 UD |
152 | if (buf[slen - 1] != '.') |
153 | { | |
154 | buf[slen++] = '.'; | |
155 | buf[slen] = '\0'; | |
156 | } | |
e61abf83 | 157 | |
0ecb606c | 158 | res = nis_list (buf, USE_DGRAM | NO_AUTHINFO | FOLLOW_LINKS | FOLLOW_PATH, |
e61abf83 UD |
159 | NULL, NULL); |
160 | ||
901956a5 UD |
161 | if (res == NULL) |
162 | { | |
163 | *errnop = ENOMEM; | |
164 | return NSS_STATUS_TRYAGAIN; | |
165 | } | |
e61abf83 UD |
166 | retval = niserr2nss (res->status); |
167 | ||
168 | if (retval != NSS_STATUS_SUCCESS) | |
169 | { | |
170 | if (retval == NSS_STATUS_TRYAGAIN) | |
d71b808a | 171 | *errnop = errno; |
e61abf83 UD |
172 | nis_freeresult (res); |
173 | return retval; | |
174 | } | |
175 | ||
0ecb606c | 176 | if (NIS_RES_NUMOBJ (res) > 1) |
e61abf83 UD |
177 | { |
178 | /* | |
179 | * More than one principal with same uid? | |
180 | * something wrong with cred table. Should be unique | |
181 | * Warn user and continue. | |
182 | */ | |
0ecb606c | 183 | syslog (LOG_ERR, _("DES entry for netname %s not unique\n"), netname); |
e61abf83 UD |
184 | nis_freeresult (res); |
185 | return NSS_STATUS_SUCCESS; | |
186 | } | |
187 | ||
0ecb606c JJ |
188 | len = ENTRY_LEN (NIS_RES_OBJECT (res), 4); |
189 | memcpy (buf, ENTRY_VAL (NIS_RES_OBJECT (res), 4), len); | |
650425ce UD |
190 | buf[len] = '\0'; |
191 | cptr = strchr (buf, ':'); | |
e61abf83 UD |
192 | if (cptr) |
193 | cptr[0] = '\0'; | |
194 | nis_freeresult (res); | |
195 | ||
196 | if (!xdecrypt (buf, passwd)) | |
197 | return NSS_STATUS_SUCCESS; | |
198 | ||
199 | if (memcmp (buf, &(buf[HEXKEYBYTES]), KEYCHECKSUMSIZE) != 0) | |
200 | return NSS_STATUS_SUCCESS; | |
201 | ||
202 | buf[HEXKEYBYTES] = 0; | |
203 | strcpy (skey, buf); | |
204 | ||
205 | return NSS_STATUS_SUCCESS; | |
206 | } | |
207 | ||
0ecb606c | 208 | |
e61abf83 UD |
209 | /* Parse information from the passed string. |
210 | The format of the string passed is gid,grp,grp, ... */ | |
211 | static enum nss_status | |
d71b808a UD |
212 | parse_grp_str (const char *s, gid_t *gidp, int *gidlenp, gid_t *gidlist, |
213 | int *errnop) | |
e61abf83 | 214 | { |
8e9b2075 | 215 | char *ep; |
e61abf83 UD |
216 | int gidlen; |
217 | ||
218 | if (!s || (!isdigit (*s))) | |
219 | { | |
f1f0edfe | 220 | syslog (LOG_ERR, _("netname2user: missing group id list in `%s'."), s); |
e61abf83 UD |
221 | return NSS_STATUS_NOTFOUND; |
222 | } | |
223 | ||
8e9b2075 | 224 | *gidp = strtoul (s, &ep, 10); |
e61abf83 UD |
225 | |
226 | gidlen = 0; | |
227 | ||
8e9b2075 | 228 | /* After strtoul() ep should point to the marker ',', which means |
0ecb606c JJ |
229 | here starts a new value. |
230 | ||
231 | The Sun man pages show that GIDLIST should contain at least NGRPS | |
232 | elements. Limiting the number written by this value is the best | |
233 | we can do. */ | |
234 | while (ep != NULL && *ep == ',' && gidlen < NGRPS) | |
e61abf83 | 235 | { |
8e9b2075 UD |
236 | ep++; |
237 | s = ep; | |
238 | gidlist[gidlen++] = strtoul (s, &ep, 10); | |
e61abf83 UD |
239 | } |
240 | *gidlenp = gidlen; | |
241 | ||
242 | return NSS_STATUS_SUCCESS; | |
243 | } | |
244 | ||
245 | enum nss_status | |
246 | _nss_nisplus_netname2user (char netname[MAXNETNAMELEN + 1], uid_t *uidp, | |
d71b808a | 247 | gid_t *gidp, int *gidlenp, gid_t *gidlist, int *errnop) |
e61abf83 UD |
248 | { |
249 | char *domain; | |
250 | nis_result *res; | |
0ecb606c | 251 | char sname[NIS_MAXNAMELEN + 2]; /* search criteria + table name */ |
40a55d20 | 252 | size_t slen; |
0ecb606c | 253 | char principal[NIS_MAXNAMELEN + 1]; |
e61abf83 UD |
254 | int len; |
255 | ||
256 | /* 1. Get home domain of user. */ | |
257 | domain = strchr (netname, '@'); | |
258 | if (! domain) | |
259 | return NSS_STATUS_UNAVAIL; | |
260 | ||
d71b808a | 261 | ++domain; /* skip '@' */ |
e61abf83 UD |
262 | |
263 | /* 2. Get user's nisplus principal name. */ | |
40a55d20 UD |
264 | slen = snprintf (sname, NIS_MAXNAMELEN, |
265 | "[auth_name=%s,auth_type=DES],cred.org_dir.%s", | |
266 | netname, domain); | |
267 | ||
a680290a UD |
268 | if (slen >= NIS_MAXNAMELEN) |
269 | { | |
270 | *errnop = EINVAL; | |
271 | return NSS_STATUS_UNAVAIL; | |
272 | } | |
273 | ||
40a55d20 UD |
274 | if (sname[slen - 1] != '.') |
275 | { | |
276 | sname[slen++] = '.'; | |
277 | sname[slen] = '\0'; | |
278 | } | |
e61abf83 UD |
279 | |
280 | /* must use authenticated call here */ | |
281 | /* XXX but we cant, for now. XXX */ | |
282 | res = nis_list (sname, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH, | |
283 | NULL, NULL); | |
901956a5 UD |
284 | if (res == NULL) |
285 | { | |
286 | *errnop = ENOMEM; | |
287 | return NSS_STATUS_TRYAGAIN; | |
288 | } | |
2d7da676 | 289 | switch (res->status) |
e61abf83 UD |
290 | { |
291 | case NIS_SUCCESS: | |
292 | case NIS_S_SUCCESS: | |
293 | break; /* go and do something useful */ | |
294 | case NIS_NOTFOUND: | |
295 | case NIS_PARTIAL: | |
296 | case NIS_NOSUCHNAME: | |
297 | case NIS_NOSUCHTABLE: | |
298 | nis_freeresult (res); | |
299 | return NSS_STATUS_NOTFOUND; | |
300 | case NIS_S_NOTFOUND: | |
301 | case NIS_TRYAGAIN: | |
40a55d20 | 302 | syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"), |
e61abf83 UD |
303 | nis_sperrno (res->status)); |
304 | nis_freeresult (res); | |
d71b808a | 305 | *errnop = errno; |
e61abf83 UD |
306 | return NSS_STATUS_TRYAGAIN; |
307 | default: | |
40a55d20 | 308 | syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"), |
e61abf83 UD |
309 | nis_sperrno (res->status)); |
310 | nis_freeresult (res); | |
311 | return NSS_STATUS_UNAVAIL; | |
312 | } | |
313 | ||
0ecb606c | 314 | if (NIS_RES_NUMOBJ (res) > 1) |
d71b808a UD |
315 | /* |
316 | * A netname belonging to more than one principal? | |
317 | * Something wrong with cred table. should be unique. | |
318 | * Warn user and continue. | |
319 | */ | |
320 | syslog (LOG_ALERT, | |
321 | _("netname2user: DES entry for %s in directory %s not unique"), | |
322 | netname, domain); | |
e61abf83 | 323 | |
0ecb606c JJ |
324 | len = ENTRY_LEN (NIS_RES_OBJECT (res), 0); |
325 | strncpy (principal, ENTRY_VAL (NIS_RES_OBJECT (res), 0), len); | |
e61abf83 | 326 | principal[len] = '\0'; |
2d7da676 | 327 | nis_freeresult (res); |
e61abf83 UD |
328 | |
329 | if (principal[0] == '\0') | |
330 | return NSS_STATUS_UNAVAIL; | |
331 | ||
332 | /* | |
ac9f45cf UD |
333 | * 3. Use principal name to look up uid/gid information in |
334 | * LOCAL entry in **local** cred table. | |
e61abf83 UD |
335 | */ |
336 | domain = nis_local_directory (); | |
0ecb606c | 337 | if (strlen (principal) + strlen (domain) + 45 > (size_t) NIS_MAXNAMELEN) |
e61abf83 | 338 | { |
f1f0edfe | 339 | syslog (LOG_ERR, _("netname2user: principal name `%s' too long"), |
e61abf83 UD |
340 | principal); |
341 | return NSS_STATUS_UNAVAIL; | |
342 | } | |
40a55d20 | 343 | |
0ecb606c JJ |
344 | slen = snprintf (sname, sizeof (sname), |
345 | "[cname=%s,auth_type=LOCAL],cred.org_dir.%s", | |
346 | principal, domain); | |
40a55d20 UD |
347 | |
348 | if (sname[slen - 1] != '.') | |
349 | { | |
350 | sname[slen++] = '.'; | |
351 | sname[slen] = '\0'; | |
352 | } | |
e61abf83 UD |
353 | |
354 | /* must use authenticated call here */ | |
355 | /* XXX but we cant, for now. XXX */ | |
2d7da676 UD |
356 | res = nis_list (sname, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH, |
357 | NULL, NULL); | |
901956a5 UD |
358 | if (res == NULL) |
359 | { | |
360 | *errnop = ENOMEM; | |
361 | return NSS_STATUS_TRYAGAIN; | |
362 | } | |
2d7da676 UD |
363 | switch(res->status) |
364 | { | |
365 | case NIS_NOTFOUND: | |
366 | case NIS_PARTIAL: | |
367 | case NIS_NOSUCHNAME: | |
368 | case NIS_NOSUCHTABLE: | |
369 | nis_freeresult (res); | |
370 | return NSS_STATUS_NOTFOUND; | |
371 | case NIS_S_NOTFOUND: | |
372 | case NIS_TRYAGAIN: | |
40a55d20 | 373 | syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"), |
2d7da676 UD |
374 | nis_sperrno (res->status)); |
375 | nis_freeresult (res); | |
d71b808a | 376 | *errnop = errno; |
2d7da676 UD |
377 | return NSS_STATUS_TRYAGAIN; |
378 | case NIS_SUCCESS: | |
379 | case NIS_S_SUCCESS: | |
380 | break; /* go and do something useful */ | |
381 | default: | |
40a55d20 | 382 | syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"), |
2d7da676 UD |
383 | nis_sperrno (res->status)); |
384 | nis_freeresult (res); | |
385 | return NSS_STATUS_UNAVAIL; | |
386 | } | |
e61abf83 | 387 | |
0ecb606c | 388 | if (NIS_RES_NUMOBJ (res) > 1) |
d71b808a UD |
389 | /* |
390 | * A principal can have more than one LOCAL entry? | |
391 | * Something wrong with cred table. | |
392 | * Warn user and continue. | |
393 | */ | |
394 | syslog (LOG_ALERT, | |
395 | _("netname2user: LOCAL entry for %s in directory %s not unique"), | |
396 | netname, domain); | |
e61abf83 | 397 | /* Fetch the uid */ |
0ecb606c | 398 | *uidp = strtoul (ENTRY_VAL (NIS_RES_OBJECT (res), 2), NULL, 10); |
e61abf83 UD |
399 | |
400 | if (*uidp == 0) | |
401 | { | |
402 | syslog (LOG_ERR, _("netname2user: should not have uid 0")); | |
0ecb606c | 403 | nis_freeresult (res); |
e61abf83 UD |
404 | return NSS_STATUS_NOTFOUND; |
405 | } | |
406 | ||
0ecb606c | 407 | parse_grp_str (ENTRY_VAL (NIS_RES_OBJECT (res), 3), |
d71b808a | 408 | gidp, gidlenp, gidlist, errnop); |
e61abf83 UD |
409 | |
410 | nis_freeresult (res); | |
411 | return NSS_STATUS_SUCCESS; | |
412 | } |