]> git.ipfire.org Git - thirdparty/glibc.git/blame - nis/nss_nisplus/nisplus-publickey.c
.
[thirdparty/glibc.git] / nis / nss_nisplus / nisplus-publickey.c
CommitLineData
0292b0dd 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>
30extern 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 35enum 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;
8e64faef 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
004c6219 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 */
004c6219 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
004c6219
UD
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
004c6219 117
e61abf83 118enum 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;
8e64faef 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
8e64faef 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
004c6219 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 */
004c6219 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
004c6219
UD
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
004c6219 208
e61abf83
UD
209/* Parse information from the passed string.
210 The format of the string passed is gid,grp,grp, ... */
211static enum nss_status
d71b808a
UD
212parse_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 {
32c075e1 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
5493f3dd
UD
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
245enum 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;
8e64faef 251 char sname[NIS_MAXNAMELEN + 2]; /* search criteria + table name */
40a55d20 252 size_t slen;
8e64faef 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
004c6219 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
004c6219
UD
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 ();
004c6219 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
8e64faef
UD
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
004c6219 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 */
004c6219 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"));
0292b0dd 403 nis_freeresult (res);
e61abf83
UD
404 return NSS_STATUS_NOTFOUND;
405 }
406
004c6219 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}