Updated.
[glibc.git] / nis / nss_nisplus / nisplus-publickey.c
blob1be613997798a0adb30c7a6e3f57fa5cd22a3693
1 /* Copyright (c) 1997, 1999 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 int gidlen;
205 if (!s || (!isdigit (*s)))
207 syslog (LOG_ERR, _("netname2user: missing group id list in `%s'."), s);
208 return NSS_STATUS_NOTFOUND;
211 *gidp = atoi (s);
213 gidlen = 0;
215 while ((s = strchr (s, ',')) != NULL)
217 s++;
218 gidlist[gidlen++] = atoi (s);
220 *gidlenp = gidlen;
222 return NSS_STATUS_SUCCESS;
225 enum nss_status
226 _nss_nisplus_netname2user (char netname[MAXNETNAMELEN + 1], uid_t *uidp,
227 gid_t *gidp, int *gidlenp, gid_t *gidlist, int *errnop)
229 char *domain;
230 nis_result *res;
231 char sname[NIS_MAXNAMELEN+2]; /* search criteria + table name */
232 size_t slen;
233 char principal[NIS_MAXNAMELEN+1];
234 int len;
236 /* 1. Get home domain of user. */
237 domain = strchr (netname, '@');
238 if (! domain)
239 return NSS_STATUS_UNAVAIL;
241 ++domain; /* skip '@' */
243 /* 2. Get user's nisplus principal name. */
244 if ((strlen (netname) + strlen (domain)+45) >
245 (size_t) NIS_MAXNAMELEN)
246 return NSS_STATUS_UNAVAIL;
248 slen = snprintf (sname, NIS_MAXNAMELEN,
249 "[auth_name=%s,auth_type=DES],cred.org_dir.%s",
250 netname, domain);
252 if (slen >= NIS_MAXNAMELEN)
254 *errnop = EINVAL;
255 return NSS_STATUS_UNAVAIL;
258 if (sname[slen - 1] != '.')
260 sname[slen++] = '.';
261 sname[slen] = '\0';
264 /* must use authenticated call here */
265 /* XXX but we cant, for now. XXX */
266 res = nis_list (sname, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH,
267 NULL, NULL);
268 switch (res->status)
270 case NIS_SUCCESS:
271 case NIS_S_SUCCESS:
272 break; /* go and do something useful */
273 case NIS_NOTFOUND:
274 case NIS_PARTIAL:
275 case NIS_NOSUCHNAME:
276 case NIS_NOSUCHTABLE:
277 nis_freeresult (res);
278 return NSS_STATUS_NOTFOUND;
279 case NIS_S_NOTFOUND:
280 case NIS_TRYAGAIN:
281 syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"),
282 nis_sperrno (res->status));
283 nis_freeresult (res);
284 *errnop = errno;
285 return NSS_STATUS_TRYAGAIN;
286 default:
287 syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"),
288 nis_sperrno (res->status));
289 nis_freeresult (res);
290 return NSS_STATUS_UNAVAIL;
293 if (res->objects.objects_len > 1)
295 * A netname belonging to more than one principal?
296 * Something wrong with cred table. should be unique.
297 * Warn user and continue.
299 syslog (LOG_ALERT,
300 _("netname2user: DES entry for %s in directory %s not unique"),
301 netname, domain);
303 len = ENTRY_LEN (res->objects.objects_val, 0);
304 strncpy (principal, ENTRY_VAL (res->objects.objects_val, 0), len);
305 principal[len] = '\0';
306 nis_freeresult (res);
308 if (principal[0] == '\0')
309 return NSS_STATUS_UNAVAIL;
312 * 3. Use principal name to look up uid/gid information in
313 * LOCAL entry in **local** cred table.
315 domain = nis_local_directory ();
316 if ((strlen (principal) + strlen (domain) + 45) > (size_t) NIS_MAXNAMELEN)
318 syslog (LOG_ERR, _("netname2user: principal name `%s' too long"),
319 principal);
320 return NSS_STATUS_UNAVAIL;
323 slen = sprintf (sname, "[cname=%s,auth_type=LOCAL],cred.org_dir.%s",
324 principal, domain);
326 if (sname[slen - 1] != '.')
328 sname[slen++] = '.';
329 sname[slen] = '\0';
332 /* must use authenticated call here */
333 /* XXX but we cant, for now. XXX */
334 res = nis_list (sname, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH,
335 NULL, NULL);
336 switch(res->status)
338 case NIS_NOTFOUND:
339 case NIS_PARTIAL:
340 case NIS_NOSUCHNAME:
341 case NIS_NOSUCHTABLE:
342 nis_freeresult (res);
343 return NSS_STATUS_NOTFOUND;
344 case NIS_S_NOTFOUND:
345 case NIS_TRYAGAIN:
346 syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"),
347 nis_sperrno (res->status));
348 nis_freeresult (res);
349 *errnop = errno;
350 return NSS_STATUS_TRYAGAIN;
351 case NIS_SUCCESS:
352 case NIS_S_SUCCESS:
353 break; /* go and do something useful */
354 default:
355 syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"),
356 nis_sperrno (res->status));
357 nis_freeresult (res);
358 return NSS_STATUS_UNAVAIL;
361 if (res->objects.objects_len > 1)
363 * A principal can have more than one LOCAL entry?
364 * Something wrong with cred table.
365 * Warn user and continue.
367 syslog (LOG_ALERT,
368 _("netname2user: LOCAL entry for %s in directory %s not unique"),
369 netname, domain);
370 /* Fetch the uid */
371 *uidp = atoi (ENTRY_VAL (res->objects.objects_val, 2));
373 if (*uidp == 0)
375 syslog (LOG_ERR, _("netname2user: should not have uid 0"));
376 return NSS_STATUS_NOTFOUND;
379 parse_grp_str (ENTRY_VAL (res->objects.objects_val, 3),
380 gidp, gidlenp, gidlist, errnop);
382 nis_freeresult (res);
383 return NSS_STATUS_SUCCESS;