* sysdeps/unix/sysv/linux/m68k/sysdep-cancel.h: Support cancellation
[glibc.git] / nis / nss_nisplus / nisplus-publickey.c
blobec1290a683f4b0d5e15aa09b520bf701281da4ab
1 /* Copyright (c) 1997, 1999, 2001 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 retval = niserr2nss (res->status);
79 if (retval != NSS_STATUS_SUCCESS)
81 if (retval == NSS_STATUS_TRYAGAIN)
82 *errnop = errno;
83 if (res->status == NIS_NOTFOUND)
84 retval = NSS_STATUS_SUCCESS;
85 nis_freeresult (res);
86 return retval;
89 if (res->objects.objects_len > 1)
92 * More than one principal with same uid?
93 * something wrong with cred table. Should be unique
94 * Warn user and continue.
96 printf (_("DES entry for netname %s not unique\n"), netname);
97 nis_freeresult (res);
98 return NSS_STATUS_SUCCESS;
101 len = ENTRY_LEN (res->objects.objects_val, 3);
102 memcpy (pkey, ENTRY_VAL (res->objects.objects_val,3), len);
103 pkey[len] = 0;
104 cptr = strchr (pkey, ':');
105 if (cptr)
106 cptr[0] = '\0';
107 nis_freeresult (res);
109 return NSS_STATUS_SUCCESS;
112 enum nss_status
113 _nss_nisplus_getsecretkey (const char *netname, char *skey, char *passwd,
114 int *errnop)
116 nis_result *res;
117 enum nss_status retval;
118 char buf[NIS_MAXNAMELEN+2];
119 size_t slen;
120 char *domain, *cptr;
121 int len;
123 skey[0] = 0;
125 if (netname == NULL)
127 *errnop = EINVAL;
128 return NSS_STATUS_UNAVAIL;
131 domain = strchr (netname, '@');
132 if (!domain)
133 return NSS_STATUS_UNAVAIL;
134 domain++;
136 slen = snprintf (buf, NIS_MAXNAMELEN,
137 "[auth_name=%s,auth_type=DES],cred.org_dir.%s",
138 netname, domain);
140 if (slen >= NIS_MAXNAMELEN)
142 *errnop = EINVAL;
143 return NSS_STATUS_UNAVAIL;
146 if (buf[slen - 1] != '.')
148 buf[slen++] = '.';
149 buf[slen] = '\0';
152 res = nis_list (buf, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH,
153 NULL, NULL);
155 retval = niserr2nss (res->status);
157 if (retval != NSS_STATUS_SUCCESS)
159 if (retval == NSS_STATUS_TRYAGAIN)
160 *errnop = errno;
161 nis_freeresult (res);
162 return retval;
165 if (res->objects.objects_len > 1)
168 * More than one principal with same uid?
169 * something wrong with cred table. Should be unique
170 * Warn user and continue.
172 printf (_("DES entry for netname %s not unique\n"), netname);
173 nis_freeresult (res);
174 return NSS_STATUS_SUCCESS;
177 len = ENTRY_LEN (res->objects.objects_val, 4);
178 memcpy (buf, ENTRY_VAL (res->objects.objects_val,4), len);
179 buf[len] = '\0';
180 cptr = strchr (buf, ':');
181 if (cptr)
182 cptr[0] = '\0';
183 nis_freeresult (res);
185 if (!xdecrypt (buf, passwd))
186 return NSS_STATUS_SUCCESS;
188 if (memcmp (buf, &(buf[HEXKEYBYTES]), KEYCHECKSUMSIZE) != 0)
189 return NSS_STATUS_SUCCESS;
191 buf[HEXKEYBYTES] = 0;
192 strcpy (skey, buf);
194 return NSS_STATUS_SUCCESS;
197 /* Parse information from the passed string.
198 The format of the string passed is gid,grp,grp, ... */
199 static enum nss_status
200 parse_grp_str (const char *s, gid_t *gidp, int *gidlenp, gid_t *gidlist,
201 int *errnop)
203 char *ep;
204 int gidlen;
206 if (!s || (!isdigit (*s)))
208 syslog (LOG_ERR, _("netname2user: missing group id list in `%s'."), s);
209 return NSS_STATUS_NOTFOUND;
212 *gidp = strtoul (s, &ep, 10);
214 gidlen = 0;
216 /* After strtoul() ep should point to the marker ',', which means
217 here starts a new value. */
218 while (ep != NULL && *ep == ',')
220 ep++;
221 s = ep;
222 gidlist[gidlen++] = strtoul (s, &ep, 10);
224 *gidlenp = gidlen;
226 return NSS_STATUS_SUCCESS;
229 enum nss_status
230 _nss_nisplus_netname2user (char netname[MAXNETNAMELEN + 1], uid_t *uidp,
231 gid_t *gidp, int *gidlenp, gid_t *gidlist, int *errnop)
233 char *domain;
234 nis_result *res;
235 char sname[NIS_MAXNAMELEN+2]; /* search criteria + table name */
236 size_t slen;
237 char principal[NIS_MAXNAMELEN+1];
238 int len;
240 /* 1. Get home domain of user. */
241 domain = strchr (netname, '@');
242 if (! domain)
243 return NSS_STATUS_UNAVAIL;
245 ++domain; /* skip '@' */
247 /* 2. Get user's nisplus principal name. */
248 if ((strlen (netname) + strlen (domain)+45) >
249 (size_t) NIS_MAXNAMELEN)
250 return NSS_STATUS_UNAVAIL;
252 slen = snprintf (sname, NIS_MAXNAMELEN,
253 "[auth_name=%s,auth_type=DES],cred.org_dir.%s",
254 netname, domain);
256 if (slen >= NIS_MAXNAMELEN)
258 *errnop = EINVAL;
259 return NSS_STATUS_UNAVAIL;
262 if (sname[slen - 1] != '.')
264 sname[slen++] = '.';
265 sname[slen] = '\0';
268 /* must use authenticated call here */
269 /* XXX but we cant, for now. XXX */
270 res = nis_list (sname, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH,
271 NULL, NULL);
272 switch (res->status)
274 case NIS_SUCCESS:
275 case NIS_S_SUCCESS:
276 break; /* go and do something useful */
277 case NIS_NOTFOUND:
278 case NIS_PARTIAL:
279 case NIS_NOSUCHNAME:
280 case NIS_NOSUCHTABLE:
281 nis_freeresult (res);
282 return NSS_STATUS_NOTFOUND;
283 case NIS_S_NOTFOUND:
284 case NIS_TRYAGAIN:
285 syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"),
286 nis_sperrno (res->status));
287 nis_freeresult (res);
288 *errnop = errno;
289 return NSS_STATUS_TRYAGAIN;
290 default:
291 syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"),
292 nis_sperrno (res->status));
293 nis_freeresult (res);
294 return NSS_STATUS_UNAVAIL;
297 if (res->objects.objects_len > 1)
299 * A netname belonging to more than one principal?
300 * Something wrong with cred table. should be unique.
301 * Warn user and continue.
303 syslog (LOG_ALERT,
304 _("netname2user: DES entry for %s in directory %s not unique"),
305 netname, domain);
307 len = ENTRY_LEN (res->objects.objects_val, 0);
308 strncpy (principal, ENTRY_VAL (res->objects.objects_val, 0), len);
309 principal[len] = '\0';
310 nis_freeresult (res);
312 if (principal[0] == '\0')
313 return NSS_STATUS_UNAVAIL;
316 * 3. Use principal name to look up uid/gid information in
317 * LOCAL entry in **local** cred table.
319 domain = nis_local_directory ();
320 if ((strlen (principal) + strlen (domain) + 45) > (size_t) NIS_MAXNAMELEN)
322 syslog (LOG_ERR, _("netname2user: principal name `%s' too long"),
323 principal);
324 return NSS_STATUS_UNAVAIL;
327 slen = sprintf (sname, "[cname=%s,auth_type=LOCAL],cred.org_dir.%s",
328 principal, domain);
330 if (sname[slen - 1] != '.')
332 sname[slen++] = '.';
333 sname[slen] = '\0';
336 /* must use authenticated call here */
337 /* XXX but we cant, for now. XXX */
338 res = nis_list (sname, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH,
339 NULL, NULL);
340 switch(res->status)
342 case NIS_NOTFOUND:
343 case NIS_PARTIAL:
344 case NIS_NOSUCHNAME:
345 case NIS_NOSUCHTABLE:
346 nis_freeresult (res);
347 return NSS_STATUS_NOTFOUND;
348 case NIS_S_NOTFOUND:
349 case NIS_TRYAGAIN:
350 syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"),
351 nis_sperrno (res->status));
352 nis_freeresult (res);
353 *errnop = errno;
354 return NSS_STATUS_TRYAGAIN;
355 case NIS_SUCCESS:
356 case NIS_S_SUCCESS:
357 break; /* go and do something useful */
358 default:
359 syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"),
360 nis_sperrno (res->status));
361 nis_freeresult (res);
362 return NSS_STATUS_UNAVAIL;
365 if (res->objects.objects_len > 1)
367 * A principal can have more than one LOCAL entry?
368 * Something wrong with cred table.
369 * Warn user and continue.
371 syslog (LOG_ALERT,
372 _("netname2user: LOCAL entry for %s in directory %s not unique"),
373 netname, domain);
374 /* Fetch the uid */
375 *uidp = strtoul (ENTRY_VAL (res->objects.objects_val, 2), NULL, 10);
377 if (*uidp == 0)
379 syslog (LOG_ERR, _("netname2user: should not have uid 0"));
380 return NSS_STATUS_NOTFOUND;
383 parse_grp_str (ENTRY_VAL (res->objects.objects_val, 3),
384 gidp, gidlenp, gidlist, errnop);
386 nis_freeresult (res);
387 return NSS_STATUS_SUCCESS;