* nis/nss_nisplus/nisplus-publickey.c: Minor cleanups throughout.
[glibc.git] / nis / nss_nisplus / nisplus-publickey.c
blobfe269b2c4892cd699228b75deb7f9f0c83ec78ad
1 /* Copyright (c) 1997,1999,2001,2003,2005,2006 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 (NIS_RES_NUMOBJ (res) > 1)
97 * More than one principal with same uid?
98 * something wrong with cred table. Should be unique
99 * Warn user and continue.
101 syslog (LOG_ERR, _("DES entry for netname %s not unique\n"), netname);
102 nis_freeresult (res);
103 return NSS_STATUS_SUCCESS;
106 len = ENTRY_LEN (NIS_RES_OBJECT (res), 3);
107 memcpy (pkey, ENTRY_VAL (NIS_RES_OBJECT (res),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;
118 enum nss_status
119 _nss_nisplus_getsecretkey (const char *netname, char *skey, char *passwd,
120 int *errnop)
122 nis_result *res;
123 enum nss_status retval;
124 char buf[NIS_MAXNAMELEN + 2];
125 size_t slen;
126 char *domain, *cptr;
127 int len;
129 skey[0] = 0;
131 if (netname == NULL)
133 *errnop = EINVAL;
134 return NSS_STATUS_UNAVAIL;
137 domain = strchr (netname, '@');
138 if (!domain)
139 return NSS_STATUS_UNAVAIL;
140 domain++;
142 slen = snprintf (buf, NIS_MAXNAMELEN,
143 "[auth_name=%s,auth_type=DES],cred.org_dir.%s",
144 netname, domain);
146 if (slen >= NIS_MAXNAMELEN)
148 *errnop = EINVAL;
149 return NSS_STATUS_UNAVAIL;
152 if (buf[slen - 1] != '.')
154 buf[slen++] = '.';
155 buf[slen] = '\0';
158 res = nis_list (buf, USE_DGRAM | NO_AUTHINFO | FOLLOW_LINKS | FOLLOW_PATH,
159 NULL, NULL);
161 if (res == NULL)
163 *errnop = ENOMEM;
164 return NSS_STATUS_TRYAGAIN;
166 retval = niserr2nss (res->status);
168 if (retval != NSS_STATUS_SUCCESS)
170 if (retval == NSS_STATUS_TRYAGAIN)
171 *errnop = errno;
172 nis_freeresult (res);
173 return retval;
176 if (NIS_RES_NUMOBJ (res) > 1)
179 * More than one principal with same uid?
180 * something wrong with cred table. Should be unique
181 * Warn user and continue.
183 syslog (LOG_ERR, _("DES entry for netname %s not unique\n"), netname);
184 nis_freeresult (res);
185 return NSS_STATUS_SUCCESS;
188 len = ENTRY_LEN (NIS_RES_OBJECT (res), 4);
189 memcpy (buf, ENTRY_VAL (NIS_RES_OBJECT (res), 4), len);
190 buf[len] = '\0';
191 cptr = strchr (buf, ':');
192 if (cptr)
193 cptr[0] = '\0';
194 nis_freeresult (res);
196 if (!xdecrypt (buf, passwd))
197 return NSS_STATUS_SUCCESS;
199 if (memcmp (buf, &(buf[HEXKEYBYTES]), KEYCHECKSUMSIZE) != 0)
200 return NSS_STATUS_SUCCESS;
202 buf[HEXKEYBYTES] = 0;
203 strcpy (skey, buf);
205 return NSS_STATUS_SUCCESS;
209 /* Parse information from the passed string.
210 The format of the string passed is gid,grp,grp, ... */
211 static enum nss_status
212 parse_grp_str (const char *s, gid_t *gidp, int *gidlenp, gid_t *gidlist,
213 int *errnop)
215 char *ep;
216 int gidlen;
218 if (!s || (!isdigit (*s)))
220 syslog (LOG_ERR, _("netname2user: missing group id list in `%s'."), s);
221 return NSS_STATUS_NOTFOUND;
224 *gidp = strtoul (s, &ep, 10);
226 gidlen = 0;
228 /* After strtoul() ep should point to the marker ',', which means
229 here starts a new value. */
230 while (ep != NULL && *ep == ',')
232 ep++;
233 s = ep;
234 gidlist[gidlen++] = strtoul (s, &ep, 10);
236 *gidlenp = gidlen;
238 return NSS_STATUS_SUCCESS;
241 enum nss_status
242 _nss_nisplus_netname2user (char netname[MAXNETNAMELEN + 1], uid_t *uidp,
243 gid_t *gidp, int *gidlenp, gid_t *gidlist, int *errnop)
245 char *domain;
246 nis_result *res;
247 char sname[NIS_MAXNAMELEN + 2]; /* search criteria + table name */
248 size_t slen;
249 char principal[NIS_MAXNAMELEN + 1];
250 int len;
252 /* 1. Get home domain of user. */
253 domain = strchr (netname, '@');
254 if (! domain)
255 return NSS_STATUS_UNAVAIL;
257 ++domain; /* skip '@' */
259 /* 2. Get user's nisplus principal name. */
260 slen = snprintf (sname, NIS_MAXNAMELEN,
261 "[auth_name=%s,auth_type=DES],cred.org_dir.%s",
262 netname, domain);
264 if (slen >= NIS_MAXNAMELEN)
266 *errnop = EINVAL;
267 return NSS_STATUS_UNAVAIL;
270 if (sname[slen - 1] != '.')
272 sname[slen++] = '.';
273 sname[slen] = '\0';
276 /* must use authenticated call here */
277 /* XXX but we cant, for now. XXX */
278 res = nis_list (sname, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH,
279 NULL, NULL);
280 if (res == NULL)
282 *errnop = ENOMEM;
283 return NSS_STATUS_TRYAGAIN;
285 switch (res->status)
287 case NIS_SUCCESS:
288 case NIS_S_SUCCESS:
289 break; /* go and do something useful */
290 case NIS_NOTFOUND:
291 case NIS_PARTIAL:
292 case NIS_NOSUCHNAME:
293 case NIS_NOSUCHTABLE:
294 nis_freeresult (res);
295 return NSS_STATUS_NOTFOUND;
296 case NIS_S_NOTFOUND:
297 case NIS_TRYAGAIN:
298 syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"),
299 nis_sperrno (res->status));
300 nis_freeresult (res);
301 *errnop = errno;
302 return NSS_STATUS_TRYAGAIN;
303 default:
304 syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"),
305 nis_sperrno (res->status));
306 nis_freeresult (res);
307 return NSS_STATUS_UNAVAIL;
310 if (NIS_RES_NUMOBJ (res) > 1)
312 * A netname belonging to more than one principal?
313 * Something wrong with cred table. should be unique.
314 * Warn user and continue.
316 syslog (LOG_ALERT,
317 _("netname2user: DES entry for %s in directory %s not unique"),
318 netname, domain);
320 len = ENTRY_LEN (NIS_RES_OBJECT (res), 0);
321 strncpy (principal, ENTRY_VAL (NIS_RES_OBJECT (res), 0), len);
322 principal[len] = '\0';
323 nis_freeresult (res);
325 if (principal[0] == '\0')
326 return NSS_STATUS_UNAVAIL;
329 * 3. Use principal name to look up uid/gid information in
330 * LOCAL entry in **local** cred table.
332 domain = nis_local_directory ();
333 if (strlen (principal) + strlen (domain) + 45 > (size_t) NIS_MAXNAMELEN)
335 syslog (LOG_ERR, _("netname2user: principal name `%s' too long"),
336 principal);
337 return NSS_STATUS_UNAVAIL;
340 slen = snprintf (sname, sizeof (sname),
341 "[cname=%s,auth_type=LOCAL],cred.org_dir.%s",
342 principal, domain);
344 if (sname[slen - 1] != '.')
346 sname[slen++] = '.';
347 sname[slen] = '\0';
350 /* must use authenticated call here */
351 /* XXX but we cant, for now. XXX */
352 res = nis_list (sname, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH,
353 NULL, NULL);
354 if (res == NULL)
356 *errnop = ENOMEM;
357 return NSS_STATUS_TRYAGAIN;
359 switch(res->status)
361 case NIS_NOTFOUND:
362 case NIS_PARTIAL:
363 case NIS_NOSUCHNAME:
364 case NIS_NOSUCHTABLE:
365 nis_freeresult (res);
366 return NSS_STATUS_NOTFOUND;
367 case NIS_S_NOTFOUND:
368 case NIS_TRYAGAIN:
369 syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"),
370 nis_sperrno (res->status));
371 nis_freeresult (res);
372 *errnop = errno;
373 return NSS_STATUS_TRYAGAIN;
374 case NIS_SUCCESS:
375 case NIS_S_SUCCESS:
376 break; /* go and do something useful */
377 default:
378 syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"),
379 nis_sperrno (res->status));
380 nis_freeresult (res);
381 return NSS_STATUS_UNAVAIL;
384 if (NIS_RES_NUMOBJ (res) > 1)
386 * A principal can have more than one LOCAL entry?
387 * Something wrong with cred table.
388 * Warn user and continue.
390 syslog (LOG_ALERT,
391 _("netname2user: LOCAL entry for %s in directory %s not unique"),
392 netname, domain);
393 /* Fetch the uid */
394 *uidp = strtoul (ENTRY_VAL (NIS_RES_OBJECT (res), 2), NULL, 10);
396 if (*uidp == 0)
398 syslog (LOG_ERR, _("netname2user: should not have uid 0"));
399 nis_freeresult (res);
400 return NSS_STATUS_NOTFOUND;
403 parse_grp_str (ENTRY_VAL (NIS_RES_OBJECT (res), 3),
404 gidp, gidlenp, gidlist, errnop);
406 nis_freeresult (res);
407 return NSS_STATUS_SUCCESS;