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