Update copyright notices with scripts/update-copyrights
[glibc.git] / nis / nss_nisplus / nisplus-publickey.c
blob4aef42450c64f4fb93ad4672568361e640845902
1 /* Copyright (c) 1997-2014 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, see
17 <http://www.gnu.org/licenses/>. */
19 #include <nss.h>
20 #include <ctype.h>
21 #include <errno.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <libintl.h>
25 #include <syslog.h>
26 #include <rpc/rpc.h>
27 #include <rpcsvc/nis.h>
28 #include <rpc/key_prot.h>
29 extern int xdecrypt (char *, char *);
31 #include <nss-nisplus.h>
33 /* If we haven't found the entry, we give a SUCCESS and an empty key back. */
34 enum nss_status
35 _nss_nisplus_getpublickey (const char *netname, char *pkey, int *errnop)
37 nis_result *res;
38 enum nss_status retval;
39 char buf[NIS_MAXNAMELEN + 2];
40 size_t slen;
41 char *domain, *cptr;
42 int len;
44 pkey[0] = 0;
46 if (netname == NULL)
48 *errnop = EINVAL;
49 return NSS_STATUS_UNAVAIL;
52 domain = strchr (netname, '@');
53 if (!domain)
54 return NSS_STATUS_UNAVAIL;
55 domain++;
57 slen = snprintf (buf, NIS_MAXNAMELEN,
58 "[auth_name=%s,auth_type=DES],cred.org_dir.%s",
59 netname, domain);
61 if (slen >= NIS_MAXNAMELEN)
63 *errnop = EINVAL;
64 return NSS_STATUS_UNAVAIL;
67 if (buf[slen - 1] != '.')
69 buf[slen++] = '.';
70 buf[slen] = '\0';
73 res = nis_list (buf, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH,
74 NULL, NULL);
76 if (res == NULL)
78 *errnop = ENOMEM;
79 return NSS_STATUS_TRYAGAIN;
81 retval = niserr2nss (res->status);
83 if (retval != NSS_STATUS_SUCCESS)
85 if (retval == NSS_STATUS_TRYAGAIN)
86 *errnop = errno;
87 if (res->status == NIS_NOTFOUND)
88 retval = NSS_STATUS_SUCCESS;
89 nis_freeresult (res);
90 return retval;
93 if (NIS_RES_NUMOBJ (res) > 1)
96 * More than one principal with same uid?
97 * something wrong with cred table. Should be unique
98 * Warn user and continue.
100 syslog (LOG_ERR, _("DES entry for netname %s not unique\n"), netname);
101 nis_freeresult (res);
102 return NSS_STATUS_SUCCESS;
105 len = ENTRY_LEN (NIS_RES_OBJECT (res), 3);
106 memcpy (pkey, ENTRY_VAL (NIS_RES_OBJECT (res),3), len);
107 pkey[len] = 0;
108 cptr = strchr (pkey, ':');
109 if (cptr)
110 cptr[0] = '\0';
111 nis_freeresult (res);
113 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 (NIS_RES_NUMOBJ (res) > 1)
178 * More than one principal with same uid?
179 * something wrong with cred table. Should be unique
180 * Warn user and continue.
182 syslog (LOG_ERR, _("DES entry for netname %s not unique\n"), netname);
183 nis_freeresult (res);
184 return NSS_STATUS_SUCCESS;
187 len = ENTRY_LEN (NIS_RES_OBJECT (res), 4);
188 memcpy (buf, ENTRY_VAL (NIS_RES_OBJECT (res), 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;
208 /* Parse information from the passed string.
209 The format of the string passed is gid,grp,grp, ... */
210 static enum nss_status
211 parse_grp_str (const char *s, gid_t *gidp, int *gidlenp, gid_t *gidlist,
212 int *errnop)
214 char *ep;
215 int gidlen;
217 if (!s || (!isdigit (*s)))
219 syslog (LOG_ERR, _("netname2user: missing group id list in `%s'"), s);
220 return NSS_STATUS_NOTFOUND;
223 *gidp = strtoul (s, &ep, 10);
225 gidlen = 0;
227 /* After strtoul() ep should point to the marker ',', which means
228 here starts a new value.
230 The Sun man pages show that GIDLIST should contain at least NGRPS
231 elements. Limiting the number written by this value is the best
232 we can do. */
233 while (ep != NULL && *ep == ',' && gidlen < NGRPS)
235 ep++;
236 s = ep;
237 gidlist[gidlen++] = strtoul (s, &ep, 10);
239 *gidlenp = gidlen;
241 return NSS_STATUS_SUCCESS;
244 enum nss_status
245 _nss_nisplus_netname2user (char netname[MAXNETNAMELEN + 1], uid_t *uidp,
246 gid_t *gidp, int *gidlenp, gid_t *gidlist, int *errnop)
248 char *domain;
249 nis_result *res;
250 char sname[NIS_MAXNAMELEN + 2]; /* search criteria + table name */
251 size_t slen;
252 char principal[NIS_MAXNAMELEN + 1];
253 int len;
255 /* 1. Get home domain of user. */
256 domain = strchr (netname, '@');
257 if (! domain)
258 return NSS_STATUS_UNAVAIL;
260 ++domain; /* skip '@' */
262 /* 2. Get user's nisplus principal name. */
263 slen = snprintf (sname, NIS_MAXNAMELEN,
264 "[auth_name=%s,auth_type=DES],cred.org_dir.%s",
265 netname, domain);
267 if (slen >= NIS_MAXNAMELEN)
269 *errnop = EINVAL;
270 return NSS_STATUS_UNAVAIL;
273 if (sname[slen - 1] != '.')
275 sname[slen++] = '.';
276 sname[slen] = '\0';
279 /* must use authenticated call here */
280 /* XXX but we cant, for now. XXX */
281 res = nis_list (sname, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH,
282 NULL, NULL);
283 if (res == NULL)
285 *errnop = ENOMEM;
286 return NSS_STATUS_TRYAGAIN;
288 switch (res->status)
290 case NIS_SUCCESS:
291 case NIS_S_SUCCESS:
292 break; /* go and do something useful */
293 case NIS_NOTFOUND:
294 case NIS_PARTIAL:
295 case NIS_NOSUCHNAME:
296 case NIS_NOSUCHTABLE:
297 nis_freeresult (res);
298 return NSS_STATUS_NOTFOUND;
299 case NIS_S_NOTFOUND:
300 case NIS_TRYAGAIN:
301 syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"),
302 nis_sperrno (res->status));
303 nis_freeresult (res);
304 *errnop = errno;
305 return NSS_STATUS_TRYAGAIN;
306 default:
307 syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"),
308 nis_sperrno (res->status));
309 nis_freeresult (res);
310 return NSS_STATUS_UNAVAIL;
313 if (NIS_RES_NUMOBJ (res) > 1)
315 * A netname belonging to more than one principal?
316 * Something wrong with cred table. should be unique.
317 * Warn user and continue.
319 syslog (LOG_ALERT,
320 _("netname2user: DES entry for %s in directory %s not unique"),
321 netname, domain);
323 len = ENTRY_LEN (NIS_RES_OBJECT (res), 0);
324 strncpy (principal, ENTRY_VAL (NIS_RES_OBJECT (res), 0), len);
325 principal[len] = '\0';
326 nis_freeresult (res);
328 if (principal[0] == '\0')
329 return NSS_STATUS_UNAVAIL;
332 * 3. Use principal name to look up uid/gid information in
333 * LOCAL entry in **local** cred table.
335 domain = nis_local_directory ();
336 if (strlen (principal) + strlen (domain) + 45 > (size_t) NIS_MAXNAMELEN)
338 syslog (LOG_ERR, _("netname2user: principal name `%s' too long"),
339 principal);
340 return NSS_STATUS_UNAVAIL;
343 slen = snprintf (sname, sizeof (sname),
344 "[cname=%s,auth_type=LOCAL],cred.org_dir.%s",
345 principal, domain);
347 if (sname[slen - 1] != '.')
349 sname[slen++] = '.';
350 sname[slen] = '\0';
353 /* must use authenticated call here */
354 /* XXX but we cant, for now. XXX */
355 res = nis_list (sname, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH,
356 NULL, NULL);
357 if (res == NULL)
359 *errnop = ENOMEM;
360 return NSS_STATUS_TRYAGAIN;
362 switch(res->status)
364 case NIS_NOTFOUND:
365 case NIS_PARTIAL:
366 case NIS_NOSUCHNAME:
367 case NIS_NOSUCHTABLE:
368 nis_freeresult (res);
369 return NSS_STATUS_NOTFOUND;
370 case NIS_S_NOTFOUND:
371 case NIS_TRYAGAIN:
372 syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"),
373 nis_sperrno (res->status));
374 nis_freeresult (res);
375 *errnop = errno;
376 return NSS_STATUS_TRYAGAIN;
377 case NIS_SUCCESS:
378 case NIS_S_SUCCESS:
379 break; /* go and do something useful */
380 default:
381 syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"),
382 nis_sperrno (res->status));
383 nis_freeresult (res);
384 return NSS_STATUS_UNAVAIL;
387 if (NIS_RES_NUMOBJ (res) > 1)
389 * A principal can have more than one LOCAL entry?
390 * Something wrong with cred table.
391 * Warn user and continue.
393 syslog (LOG_ALERT,
394 _("netname2user: LOCAL entry for %s in directory %s not unique"),
395 netname, domain);
396 /* Fetch the uid */
397 *uidp = strtoul (ENTRY_VAL (NIS_RES_OBJECT (res), 2), NULL, 10);
399 if (*uidp == 0)
401 syslog (LOG_ERR, _("netname2user: should not have uid 0"));
402 nis_freeresult (res);
403 return NSS_STATUS_NOTFOUND;
406 parse_grp_str (ENTRY_VAL (NIS_RES_OBJECT (res), 3),
407 gidp, gidlenp, gidlist, errnop);
409 nis_freeresult (res);
410 return NSS_STATUS_SUCCESS;