]>
Commit | Line | Data |
---|---|---|
a334319f | 1 | /* Copyright (c) 1997, 1999, 2001, 2003 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; | |
a334319f | 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 | ||
a334319f | 94 | if (res->objects.objects_len > 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 | */ | |
a334319f | 101 | printf (_("DES entry for netname %s not unique\n"), netname); |
e61abf83 UD |
102 | nis_freeresult (res); |
103 | return NSS_STATUS_SUCCESS; | |
104 | } | |
105 | ||
a334319f UD |
106 | len = ENTRY_LEN (res->objects.objects_val, 3); |
107 | memcpy (pkey, ENTRY_VAL (res->objects.objects_val,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 | ||
117 | enum nss_status | |
d71b808a UD |
118 | _nss_nisplus_getsecretkey (const char *netname, char *skey, char *passwd, |
119 | int *errnop) | |
e61abf83 UD |
120 | { |
121 | nis_result *res; | |
122 | enum nss_status retval; | |
a334319f | 123 | char buf[NIS_MAXNAMELEN+2]; |
40a55d20 | 124 | size_t slen; |
e61abf83 UD |
125 | char *domain, *cptr; |
126 | int len; | |
127 | ||
128 | skey[0] = 0; | |
129 | ||
130 | if (netname == NULL) | |
131 | { | |
d71b808a | 132 | *errnop = EINVAL; |
e61abf83 UD |
133 | return NSS_STATUS_UNAVAIL; |
134 | } | |
135 | ||
136 | domain = strchr (netname, '@'); | |
137 | if (!domain) | |
138 | return NSS_STATUS_UNAVAIL; | |
139 | domain++; | |
140 | ||
40a55d20 UD |
141 | slen = snprintf (buf, NIS_MAXNAMELEN, |
142 | "[auth_name=%s,auth_type=DES],cred.org_dir.%s", | |
143 | netname, domain); | |
e61abf83 | 144 | |
a680290a UD |
145 | if (slen >= NIS_MAXNAMELEN) |
146 | { | |
147 | *errnop = EINVAL; | |
148 | return NSS_STATUS_UNAVAIL; | |
149 | } | |
150 | ||
40a55d20 UD |
151 | if (buf[slen - 1] != '.') |
152 | { | |
153 | buf[slen++] = '.'; | |
154 | buf[slen] = '\0'; | |
155 | } | |
e61abf83 | 156 | |
a334319f | 157 | res = nis_list (buf, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH, |
e61abf83 UD |
158 | NULL, NULL); |
159 | ||
901956a5 UD |
160 | if (res == NULL) |
161 | { | |
162 | *errnop = ENOMEM; | |
163 | return NSS_STATUS_TRYAGAIN; | |
164 | } | |
e61abf83 UD |
165 | retval = niserr2nss (res->status); |
166 | ||
167 | if (retval != NSS_STATUS_SUCCESS) | |
168 | { | |
169 | if (retval == NSS_STATUS_TRYAGAIN) | |
d71b808a | 170 | *errnop = errno; |
e61abf83 UD |
171 | nis_freeresult (res); |
172 | return retval; | |
173 | } | |
174 | ||
a334319f | 175 | if (res->objects.objects_len > 1) |
e61abf83 UD |
176 | { |
177 | /* | |
178 | * More than one principal with same uid? | |
179 | * something wrong with cred table. Should be unique | |
180 | * Warn user and continue. | |
181 | */ | |
a334319f | 182 | printf (_("DES entry for netname %s not unique\n"), netname); |
e61abf83 UD |
183 | nis_freeresult (res); |
184 | return NSS_STATUS_SUCCESS; | |
185 | } | |
186 | ||
a334319f UD |
187 | len = ENTRY_LEN (res->objects.objects_val, 4); |
188 | memcpy (buf, ENTRY_VAL (res->objects.objects_val,4), len); | |
650425ce UD |
189 | buf[len] = '\0'; |
190 | cptr = strchr (buf, ':'); | |
e61abf83 UD |
191 | if (cptr) |
192 | cptr[0] = '\0'; | |
193 | nis_freeresult (res); | |
194 | ||
195 | if (!xdecrypt (buf, passwd)) | |
196 | return NSS_STATUS_SUCCESS; | |
197 | ||
198 | if (memcmp (buf, &(buf[HEXKEYBYTES]), KEYCHECKSUMSIZE) != 0) | |
199 | return NSS_STATUS_SUCCESS; | |
200 | ||
201 | buf[HEXKEYBYTES] = 0; | |
202 | strcpy (skey, buf); | |
203 | ||
204 | return NSS_STATUS_SUCCESS; | |
205 | } | |
206 | ||
207 | /* Parse information from the passed string. | |
208 | The format of the string passed is gid,grp,grp, ... */ | |
209 | static enum nss_status | |
d71b808a UD |
210 | parse_grp_str (const char *s, gid_t *gidp, int *gidlenp, gid_t *gidlist, |
211 | int *errnop) | |
e61abf83 | 212 | { |
8e9b2075 | 213 | char *ep; |
e61abf83 UD |
214 | int gidlen; |
215 | ||
216 | if (!s || (!isdigit (*s))) | |
217 | { | |
f1f0edfe | 218 | syslog (LOG_ERR, _("netname2user: missing group id list in `%s'."), s); |
e61abf83 UD |
219 | return NSS_STATUS_NOTFOUND; |
220 | } | |
221 | ||
8e9b2075 | 222 | *gidp = strtoul (s, &ep, 10); |
e61abf83 UD |
223 | |
224 | gidlen = 0; | |
225 | ||
8e9b2075 | 226 | /* After strtoul() ep should point to the marker ',', which means |
a334319f UD |
227 | here starts a new value. */ |
228 | while (ep != NULL && *ep == ',') | |
e61abf83 | 229 | { |
8e9b2075 UD |
230 | ep++; |
231 | s = ep; | |
232 | gidlist[gidlen++] = strtoul (s, &ep, 10); | |
e61abf83 UD |
233 | } |
234 | *gidlenp = gidlen; | |
235 | ||
236 | return NSS_STATUS_SUCCESS; | |
237 | } | |
238 | ||
239 | enum nss_status | |
240 | _nss_nisplus_netname2user (char netname[MAXNETNAMELEN + 1], uid_t *uidp, | |
d71b808a | 241 | gid_t *gidp, int *gidlenp, gid_t *gidlist, int *errnop) |
e61abf83 UD |
242 | { |
243 | char *domain; | |
244 | nis_result *res; | |
a334319f | 245 | char sname[NIS_MAXNAMELEN+2]; /* search criteria + table name */ |
40a55d20 | 246 | size_t slen; |
a334319f | 247 | char principal[NIS_MAXNAMELEN+1]; |
e61abf83 UD |
248 | int len; |
249 | ||
250 | /* 1. Get home domain of user. */ | |
251 | domain = strchr (netname, '@'); | |
252 | if (! domain) | |
253 | return NSS_STATUS_UNAVAIL; | |
254 | ||
d71b808a | 255 | ++domain; /* skip '@' */ |
e61abf83 UD |
256 | |
257 | /* 2. Get user's nisplus principal name. */ | |
a334319f UD |
258 | if ((strlen (netname) + strlen (domain)+45) > |
259 | (size_t) NIS_MAXNAMELEN) | |
260 | return NSS_STATUS_UNAVAIL; | |
261 | ||
40a55d20 UD |
262 | slen = snprintf (sname, NIS_MAXNAMELEN, |
263 | "[auth_name=%s,auth_type=DES],cred.org_dir.%s", | |
264 | netname, domain); | |
265 | ||
a680290a UD |
266 | if (slen >= NIS_MAXNAMELEN) |
267 | { | |
268 | *errnop = EINVAL; | |
269 | return NSS_STATUS_UNAVAIL; | |
270 | } | |
271 | ||
40a55d20 UD |
272 | if (sname[slen - 1] != '.') |
273 | { | |
274 | sname[slen++] = '.'; | |
275 | sname[slen] = '\0'; | |
276 | } | |
e61abf83 UD |
277 | |
278 | /* must use authenticated call here */ | |
279 | /* XXX but we cant, for now. XXX */ | |
280 | res = nis_list (sname, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH, | |
281 | NULL, NULL); | |
901956a5 UD |
282 | if (res == NULL) |
283 | { | |
284 | *errnop = ENOMEM; | |
285 | return NSS_STATUS_TRYAGAIN; | |
286 | } | |
2d7da676 | 287 | switch (res->status) |
e61abf83 UD |
288 | { |
289 | case NIS_SUCCESS: | |
290 | case NIS_S_SUCCESS: | |
291 | break; /* go and do something useful */ | |
292 | case NIS_NOTFOUND: | |
293 | case NIS_PARTIAL: | |
294 | case NIS_NOSUCHNAME: | |
295 | case NIS_NOSUCHTABLE: | |
296 | nis_freeresult (res); | |
297 | return NSS_STATUS_NOTFOUND; | |
298 | case NIS_S_NOTFOUND: | |
299 | case NIS_TRYAGAIN: | |
40a55d20 | 300 | syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"), |
e61abf83 UD |
301 | nis_sperrno (res->status)); |
302 | nis_freeresult (res); | |
d71b808a | 303 | *errnop = errno; |
e61abf83 UD |
304 | return NSS_STATUS_TRYAGAIN; |
305 | default: | |
40a55d20 | 306 | syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"), |
e61abf83 UD |
307 | nis_sperrno (res->status)); |
308 | nis_freeresult (res); | |
309 | return NSS_STATUS_UNAVAIL; | |
310 | } | |
311 | ||
a334319f | 312 | if (res->objects.objects_len > 1) |
d71b808a UD |
313 | /* |
314 | * A netname belonging to more than one principal? | |
315 | * Something wrong with cred table. should be unique. | |
316 | * Warn user and continue. | |
317 | */ | |
318 | syslog (LOG_ALERT, | |
319 | _("netname2user: DES entry for %s in directory %s not unique"), | |
320 | netname, domain); | |
e61abf83 | 321 | |
a334319f UD |
322 | len = ENTRY_LEN (res->objects.objects_val, 0); |
323 | strncpy (principal, ENTRY_VAL (res->objects.objects_val, 0), len); | |
e61abf83 | 324 | principal[len] = '\0'; |
2d7da676 | 325 | nis_freeresult (res); |
e61abf83 UD |
326 | |
327 | if (principal[0] == '\0') | |
328 | return NSS_STATUS_UNAVAIL; | |
329 | ||
330 | /* | |
ac9f45cf UD |
331 | * 3. Use principal name to look up uid/gid information in |
332 | * LOCAL entry in **local** cred table. | |
e61abf83 UD |
333 | */ |
334 | domain = nis_local_directory (); | |
a334319f | 335 | if ((strlen (principal) + strlen (domain) + 45) > (size_t) NIS_MAXNAMELEN) |
e61abf83 | 336 | { |
f1f0edfe | 337 | syslog (LOG_ERR, _("netname2user: principal name `%s' too long"), |
e61abf83 UD |
338 | principal); |
339 | return NSS_STATUS_UNAVAIL; | |
340 | } | |
40a55d20 | 341 | |
a334319f UD |
342 | slen = sprintf (sname, "[cname=%s,auth_type=LOCAL],cred.org_dir.%s", |
343 | principal, domain); | |
40a55d20 UD |
344 | |
345 | if (sname[slen - 1] != '.') | |
346 | { | |
347 | sname[slen++] = '.'; | |
348 | sname[slen] = '\0'; | |
349 | } | |
e61abf83 UD |
350 | |
351 | /* must use authenticated call here */ | |
352 | /* XXX but we cant, for now. XXX */ | |
2d7da676 UD |
353 | res = nis_list (sname, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH, |
354 | NULL, NULL); | |
901956a5 UD |
355 | if (res == NULL) |
356 | { | |
357 | *errnop = ENOMEM; | |
358 | return NSS_STATUS_TRYAGAIN; | |
359 | } | |
2d7da676 UD |
360 | switch(res->status) |
361 | { | |
362 | case NIS_NOTFOUND: | |
363 | case NIS_PARTIAL: | |
364 | case NIS_NOSUCHNAME: | |
365 | case NIS_NOSUCHTABLE: | |
366 | nis_freeresult (res); | |
367 | return NSS_STATUS_NOTFOUND; | |
368 | case NIS_S_NOTFOUND: | |
369 | case NIS_TRYAGAIN: | |
40a55d20 | 370 | syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"), |
2d7da676 UD |
371 | nis_sperrno (res->status)); |
372 | nis_freeresult (res); | |
d71b808a | 373 | *errnop = errno; |
2d7da676 UD |
374 | return NSS_STATUS_TRYAGAIN; |
375 | case NIS_SUCCESS: | |
376 | case NIS_S_SUCCESS: | |
377 | break; /* go and do something useful */ | |
378 | default: | |
40a55d20 | 379 | syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"), |
2d7da676 UD |
380 | nis_sperrno (res->status)); |
381 | nis_freeresult (res); | |
382 | return NSS_STATUS_UNAVAIL; | |
383 | } | |
e61abf83 | 384 | |
a334319f | 385 | if (res->objects.objects_len > 1) |
d71b808a UD |
386 | /* |
387 | * A principal can have more than one LOCAL entry? | |
388 | * Something wrong with cred table. | |
389 | * Warn user and continue. | |
390 | */ | |
391 | syslog (LOG_ALERT, | |
392 | _("netname2user: LOCAL entry for %s in directory %s not unique"), | |
393 | netname, domain); | |
e61abf83 | 394 | /* Fetch the uid */ |
a334319f | 395 | *uidp = strtoul (ENTRY_VAL (res->objects.objects_val, 2), NULL, 10); |
e61abf83 UD |
396 | |
397 | if (*uidp == 0) | |
398 | { | |
399 | syslog (LOG_ERR, _("netname2user: should not have uid 0")); | |
400 | return NSS_STATUS_NOTFOUND; | |
401 | } | |
402 | ||
a334319f | 403 | parse_grp_str (ENTRY_VAL (res->objects.objects_val, 3), |
d71b808a | 404 | gidp, gidlenp, gidlist, errnop); |
e61abf83 UD |
405 | |
406 | nis_freeresult (res); | |
407 | return NSS_STATUS_SUCCESS; | |
408 | } |