Updated to fedora-glibc-20051219T1003
[glibc.git] / nis / nss_nisplus / nisplus-publickey.c
blobc24e898137a256b3e6aebe1ff0f8f789183c24c2
1 /* Copyright (c) 1997, 1999, 2001, 2003, 2005 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Thorsten Kukuk <kukuk@suse.de>, 1997.
5 The GNU C Library is free software; you can redistribute it and/or
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.
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 Lesser General Public License for more details.
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. */
20 #include <nss.h>
21 #include <ctype.h>
22 #include <errno.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <libintl.h>
26 #include <syslog.h>
27 #include <rpc/rpc.h>
28 #include <rpcsvc/nis.h>
29 #include <rpc/key_prot.h>
30 extern int xdecrypt (char *, char *);
32 #include <nss-nisplus.h>
34 /* If we haven't found the entry, we give a SUCCESS and an empty key back. */
35 enum nss_status
36 _nss_nisplus_getpublickey (const char *netname, char *pkey, int *errnop)
38 nis_result *res;
39 enum nss_status retval;
40 char buf[NIS_MAXNAMELEN + 2];
41 size_t slen;
42 char *domain, *cptr;
43 int len;
45 pkey[0] = 0;
47 if (netname == NULL)
49 *errnop = EINVAL;
50 return NSS_STATUS_UNAVAIL;
53 domain = strchr (netname, '@');
54 if (!domain)
55 return NSS_STATUS_UNAVAIL;
56 domain++;
58 slen = snprintf (buf, NIS_MAXNAMELEN,
59 "[auth_name=%s,auth_type=DES],cred.org_dir.%s",
60 netname, domain);
62 if (slen >= NIS_MAXNAMELEN)
64 *errnop = EINVAL;
65 return NSS_STATUS_UNAVAIL;
68 if (buf[slen - 1] != '.')
70 buf[slen++] = '.';
71 buf[slen] = '\0';
74 res = nis_list (buf, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH,
75 NULL, NULL);
77 if (res == NULL)
79 *errnop = ENOMEM;
80 return NSS_STATUS_TRYAGAIN;
82 retval = niserr2nss (res->status);
84 if (retval != NSS_STATUS_SUCCESS)
86 if (retval == NSS_STATUS_TRYAGAIN)
87 *errnop = errno;
88 if (res->status == NIS_NOTFOUND)
89 retval = NSS_STATUS_SUCCESS;
90 nis_freeresult (res);
91 return retval;
94 if (res->objects.objects_len > 1)
97 * More than one principal with same uid?
98 * something wrong with cred table. Should be unique
99 * Warn user and continue.
101 printf (_("DES entry for netname %s not unique\n"), netname);
102 nis_freeresult (res);
103 return NSS_STATUS_SUCCESS;
106 len = ENTRY_LEN (res->objects.objects_val, 3);
107 memcpy (pkey, ENTRY_VAL (res->objects.objects_val,3), len);
108 pkey[len] = 0;
109 cptr = strchr (pkey, ':');
110 if (cptr)
111 cptr[0] = '\0';
112 nis_freeresult (res);
114 return NSS_STATUS_SUCCESS;
117 enum nss_status
118 _nss_nisplus_getsecretkey (const char *netname, char *skey, char *passwd,
119 int *errnop)
121 nis_result *res;
122 enum nss_status retval;
123 char buf[NIS_MAXNAMELEN + 2];
124 size_t slen;
125 char *domain, *cptr;
126 int len;
128 skey[0] = 0;
130 if (netname == NULL)
132 *errnop = EINVAL;
133 return NSS_STATUS_UNAVAIL;
136 domain = strchr (netname, '@');
137 if (!domain)
138 return NSS_STATUS_UNAVAIL;
139 domain++;
141 slen = snprintf (buf, NIS_MAXNAMELEN,
142 "[auth_name=%s,auth_type=DES],cred.org_dir.%s",
143 netname, domain);
145 if (slen >= NIS_MAXNAMELEN)
147 *errnop = EINVAL;
148 return NSS_STATUS_UNAVAIL;
151 if (buf[slen - 1] != '.')
153 buf[slen++] = '.';
154 buf[slen] = '\0';
157 res = nis_list (buf, USE_DGRAM | NO_AUTHINFO | FOLLOW_LINKS | FOLLOW_PATH,
158 NULL, NULL);
160 if (res == NULL)
162 *errnop = ENOMEM;
163 return NSS_STATUS_TRYAGAIN;
165 retval = niserr2nss (res->status);
167 if (retval != NSS_STATUS_SUCCESS)
169 if (retval == NSS_STATUS_TRYAGAIN)
170 *errnop = errno;
171 nis_freeresult (res);
172 return retval;
175 if (res->objects.objects_len > 1)
178 * More than one principal with same uid?
179 * something wrong with cred table. Should be unique
180 * Warn user and continue.
182 printf (_("DES entry for netname %s not unique\n"), netname);
183 nis_freeresult (res);
184 return NSS_STATUS_SUCCESS;
187 len = ENTRY_LEN (res->objects.objects_val, 4);
188 memcpy (buf, ENTRY_VAL (res->objects.objects_val,4), len);
189 buf[len] = '\0';
190 cptr = strchr (buf, ':');
191 if (cptr)
192 cptr[0] = '\0';
193 nis_freeresult (res);
195 if (!xdecrypt (buf, passwd))
196 return NSS_STATUS_SUCCESS;
198 if (memcmp (buf, &(buf[HEXKEYBYTES]), KEYCHECKSUMSIZE) != 0)
199 return NSS_STATUS_SUCCESS;
201 buf[HEXKEYBYTES] = 0;
202 strcpy (skey, buf);
204 return NSS_STATUS_SUCCESS;
207 /* Parse information from the passed string.
208 The format of the string passed is gid,grp,grp, ... */
209 static enum nss_status
210 parse_grp_str (const char *s, gid_t *gidp, int *gidlenp, gid_t *gidlist,
211 int *errnop)
213 char *ep;
214 int gidlen;
216 if (!s || (!isdigit (*s)))
218 syslog (LOG_ERR, _("netname2user: missing group id list in `%s'."), s);
219 return NSS_STATUS_NOTFOUND;
222 *gidp = strtoul (s, &ep, 10);
224 gidlen = 0;
226 /* After strtoul() ep should point to the marker ',', which means
227 here starts a new value. */
228 while (ep != NULL && *ep == ',')
230 ep++;
231 s = ep;
232 gidlist[gidlen++] = strtoul (s, &ep, 10);
234 *gidlenp = gidlen;
236 return NSS_STATUS_SUCCESS;
239 enum nss_status
240 _nss_nisplus_netname2user (char netname[MAXNETNAMELEN + 1], uid_t *uidp,
241 gid_t *gidp, int *gidlenp, gid_t *gidlist, int *errnop)
243 char *domain;
244 nis_result *res;
245 char sname[NIS_MAXNAMELEN + 2]; /* search criteria + table name */
246 size_t slen;
247 char principal[NIS_MAXNAMELEN + 1];
248 int len;
250 /* 1. Get home domain of user. */
251 domain = strchr (netname, '@');
252 if (! domain)
253 return NSS_STATUS_UNAVAIL;
255 ++domain; /* skip '@' */
257 /* 2. Get user's nisplus principal name. */
258 slen = snprintf (sname, NIS_MAXNAMELEN,
259 "[auth_name=%s,auth_type=DES],cred.org_dir.%s",
260 netname, domain);
262 if (slen >= NIS_MAXNAMELEN)
264 *errnop = EINVAL;
265 return NSS_STATUS_UNAVAIL;
268 if (sname[slen - 1] != '.')
270 sname[slen++] = '.';
271 sname[slen] = '\0';
274 /* must use authenticated call here */
275 /* XXX but we cant, for now. XXX */
276 res = nis_list (sname, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH,
277 NULL, NULL);
278 if (res == NULL)
280 *errnop = ENOMEM;
281 return NSS_STATUS_TRYAGAIN;
283 switch (res->status)
285 case NIS_SUCCESS:
286 case NIS_S_SUCCESS:
287 break; /* go and do something useful */
288 case NIS_NOTFOUND:
289 case NIS_PARTIAL:
290 case NIS_NOSUCHNAME:
291 case NIS_NOSUCHTABLE:
292 nis_freeresult (res);
293 return NSS_STATUS_NOTFOUND;
294 case NIS_S_NOTFOUND:
295 case NIS_TRYAGAIN:
296 syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"),
297 nis_sperrno (res->status));
298 nis_freeresult (res);
299 *errnop = errno;
300 return NSS_STATUS_TRYAGAIN;
301 default:
302 syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"),
303 nis_sperrno (res->status));
304 nis_freeresult (res);
305 return NSS_STATUS_UNAVAIL;
308 if (res->objects.objects_len > 1)
310 * A netname belonging to more than one principal?
311 * Something wrong with cred table. should be unique.
312 * Warn user and continue.
314 syslog (LOG_ALERT,
315 _("netname2user: DES entry for %s in directory %s not unique"),
316 netname, domain);
318 len = ENTRY_LEN (res->objects.objects_val, 0);
319 strncpy (principal, ENTRY_VAL (res->objects.objects_val, 0), len);
320 principal[len] = '\0';
321 nis_freeresult (res);
323 if (principal[0] == '\0')
324 return NSS_STATUS_UNAVAIL;
327 * 3. Use principal name to look up uid/gid information in
328 * LOCAL entry in **local** cred table.
330 domain = nis_local_directory ();
331 if ((strlen (principal) + strlen (domain) + 45) > (size_t) NIS_MAXNAMELEN)
333 syslog (LOG_ERR, _("netname2user: principal name `%s' too long"),
334 principal);
335 return NSS_STATUS_UNAVAIL;
338 slen = snprintf (sname, sizeof (sname),
339 "[cname=%s,auth_type=LOCAL],cred.org_dir.%s",
340 principal, domain);
342 if (sname[slen - 1] != '.')
344 sname[slen++] = '.';
345 sname[slen] = '\0';
348 /* must use authenticated call here */
349 /* XXX but we cant, for now. XXX */
350 res = nis_list (sname, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH,
351 NULL, NULL);
352 if (res == NULL)
354 *errnop = ENOMEM;
355 return NSS_STATUS_TRYAGAIN;
357 switch(res->status)
359 case NIS_NOTFOUND:
360 case NIS_PARTIAL:
361 case NIS_NOSUCHNAME:
362 case NIS_NOSUCHTABLE:
363 nis_freeresult (res);
364 return NSS_STATUS_NOTFOUND;
365 case NIS_S_NOTFOUND:
366 case NIS_TRYAGAIN:
367 syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"),
368 nis_sperrno (res->status));
369 nis_freeresult (res);
370 *errnop = errno;
371 return NSS_STATUS_TRYAGAIN;
372 case NIS_SUCCESS:
373 case NIS_S_SUCCESS:
374 break; /* go and do something useful */
375 default:
376 syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"),
377 nis_sperrno (res->status));
378 nis_freeresult (res);
379 return NSS_STATUS_UNAVAIL;
382 if (res->objects.objects_len > 1)
384 * A principal can have more than one LOCAL entry?
385 * Something wrong with cred table.
386 * Warn user and continue.
388 syslog (LOG_ALERT,
389 _("netname2user: LOCAL entry for %s in directory %s not unique"),
390 netname, domain);
391 /* Fetch the uid */
392 *uidp = strtoul (ENTRY_VAL (res->objects.objects_val, 2), NULL, 10);
394 if (*uidp == 0)
396 syslog (LOG_ERR, _("netname2user: should not have uid 0"));
397 return NSS_STATUS_NOTFOUND;
400 parse_grp_str (ENTRY_VAL (res->objects.objects_val, 3),
401 gidp, gidlenp, gidlist, errnop);
403 nis_freeresult (res);
404 return NSS_STATUS_SUCCESS;