]> git.ipfire.org Git - thirdparty/glibc.git/blame - nis/nss_nisplus/nisplus-publickey.c
(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
[thirdparty/glibc.git] / nis / nss_nisplus / nisplus-publickey.c
CommitLineData
a334319f 1/* Copyright (c) 1997, 1999, 2001, 2003 Free Software Foundation, Inc.
e61abf83 2 This file is part of the GNU C Library.
a680290a 3 Contributed by Thorsten Kukuk <kukuk@suse.de>, 1997.
e61abf83
UD
4
5 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
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.
e61abf83
UD
9
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
41bdb6e2 13 Lesser General Public License for more details.
e61abf83 14
41bdb6e2
AJ
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. */
e61abf83
UD
19
20#include <nss.h>
21#include <ctype.h>
22#include <errno.h>
23#include <stdio.h>
24#include <string.h>
4360eafd 25#include <libintl.h>
e61abf83 26#include <syslog.h>
26dee9c4 27#include <rpc/rpc.h>
e61abf83 28#include <rpcsvc/nis.h>
26dee9c4
UD
29#include <rpc/key_prot.h>
30extern int xdecrypt (char *, char *);
e61abf83
UD
31
32#include <nss-nisplus.h>
33
26dee9c4 34/* If we haven't found the entry, we give a SUCCESS and an empty key back. */
e61abf83 35enum nss_status
d71b808a 36_nss_nisplus_getpublickey (const char *netname, char *pkey, int *errnop)
e61abf83
UD
37{
38 nis_result *res;
39 enum nss_status retval;
a334319f 40 char buf[NIS_MAXNAMELEN+2];
40a55d20 41 size_t slen;
e61abf83
UD
42 char *domain, *cptr;
43 int len;
44
45 pkey[0] = 0;
46
47 if (netname == NULL)
48 {
d71b808a 49 *errnop = EINVAL;
e61abf83
UD
50 return NSS_STATUS_UNAVAIL;
51 }
52
53 domain = strchr (netname, '@');
54 if (!domain)
55 return NSS_STATUS_UNAVAIL;
56 domain++;
57
40a55d20
UD
58 slen = snprintf (buf, NIS_MAXNAMELEN,
59 "[auth_name=%s,auth_type=DES],cred.org_dir.%s",
60 netname, domain);
e61abf83 61
a680290a
UD
62 if (slen >= NIS_MAXNAMELEN)
63 {
64 *errnop = EINVAL;
65 return NSS_STATUS_UNAVAIL;
66 }
67
40a55d20
UD
68 if (buf[slen - 1] != '.')
69 {
70 buf[slen++] = '.';
71 buf[slen] = '\0';
72 }
e61abf83 73
2d7da676
UD
74 res = nis_list (buf, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH,
75 NULL, NULL);
e61abf83 76
901956a5
UD
77 if (res == NULL)
78 {
79 *errnop = ENOMEM;
80 return NSS_STATUS_TRYAGAIN;
81 }
e61abf83
UD
82 retval = niserr2nss (res->status);
83
84 if (retval != NSS_STATUS_SUCCESS)
85 {
86 if (retval == NSS_STATUS_TRYAGAIN)
d71b808a 87 *errnop = errno;
26dee9c4
UD
88 if (res->status == NIS_NOTFOUND)
89 retval = NSS_STATUS_SUCCESS;
e61abf83
UD
90 nis_freeresult (res);
91 return retval;
92 }
93
a334319f 94 if (res->objects.objects_len > 1)
e61abf83
UD
95 {
96 /*
97 * More than one principal with same uid?
98 * something wrong with cred table. Should be unique
99 * Warn user and continue.
100 */
a334319f 101 printf (_("DES entry for netname %s not unique\n"), netname);
e61abf83
UD
102 nis_freeresult (res);
103 return NSS_STATUS_SUCCESS;
104 }
105
a334319f
UD
106 len = ENTRY_LEN (res->objects.objects_val, 3);
107 memcpy (pkey, ENTRY_VAL (res->objects.objects_val,3), len);
e61abf83
UD
108 pkey[len] = 0;
109 cptr = strchr (pkey, ':');
110 if (cptr)
111 cptr[0] = '\0';
112 nis_freeresult (res);
113
114 return NSS_STATUS_SUCCESS;
115}
116
117enum nss_status
d71b808a
UD
118_nss_nisplus_getsecretkey (const char *netname, char *skey, char *passwd,
119 int *errnop)
e61abf83
UD
120{
121 nis_result *res;
122 enum nss_status retval;
a334319f 123 char buf[NIS_MAXNAMELEN+2];
40a55d20 124 size_t slen;
e61abf83
UD
125 char *domain, *cptr;
126 int len;
127
128 skey[0] = 0;
129
130 if (netname == NULL)
131 {
d71b808a 132 *errnop = EINVAL;
e61abf83
UD
133 return NSS_STATUS_UNAVAIL;
134 }
135
136 domain = strchr (netname, '@');
137 if (!domain)
138 return NSS_STATUS_UNAVAIL;
139 domain++;
140
40a55d20
UD
141 slen = snprintf (buf, NIS_MAXNAMELEN,
142 "[auth_name=%s,auth_type=DES],cred.org_dir.%s",
143 netname, domain);
e61abf83 144
a680290a
UD
145 if (slen >= NIS_MAXNAMELEN)
146 {
147 *errnop = EINVAL;
148 return NSS_STATUS_UNAVAIL;
149 }
150
40a55d20
UD
151 if (buf[slen - 1] != '.')
152 {
153 buf[slen++] = '.';
154 buf[slen] = '\0';
155 }
e61abf83 156
a334319f 157 res = nis_list (buf, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH,
e61abf83
UD
158 NULL, NULL);
159
901956a5
UD
160 if (res == NULL)
161 {
162 *errnop = ENOMEM;
163 return NSS_STATUS_TRYAGAIN;
164 }
e61abf83
UD
165 retval = niserr2nss (res->status);
166
167 if (retval != NSS_STATUS_SUCCESS)
168 {
169 if (retval == NSS_STATUS_TRYAGAIN)
d71b808a 170 *errnop = errno;
e61abf83
UD
171 nis_freeresult (res);
172 return retval;
173 }
174
a334319f 175 if (res->objects.objects_len > 1)
e61abf83
UD
176 {
177 /*
178 * More than one principal with same uid?
179 * something wrong with cred table. Should be unique
180 * Warn user and continue.
181 */
a334319f 182 printf (_("DES entry for netname %s not unique\n"), netname);
e61abf83
UD
183 nis_freeresult (res);
184 return NSS_STATUS_SUCCESS;
185 }
186
a334319f
UD
187 len = ENTRY_LEN (res->objects.objects_val, 4);
188 memcpy (buf, ENTRY_VAL (res->objects.objects_val,4), len);
650425ce
UD
189 buf[len] = '\0';
190 cptr = strchr (buf, ':');
e61abf83
UD
191 if (cptr)
192 cptr[0] = '\0';
193 nis_freeresult (res);
194
195 if (!xdecrypt (buf, passwd))
196 return NSS_STATUS_SUCCESS;
197
198 if (memcmp (buf, &(buf[HEXKEYBYTES]), KEYCHECKSUMSIZE) != 0)
199 return NSS_STATUS_SUCCESS;
200
201 buf[HEXKEYBYTES] = 0;
202 strcpy (skey, buf);
203
204 return NSS_STATUS_SUCCESS;
205}
206
207/* Parse information from the passed string.
208 The format of the string passed is gid,grp,grp, ... */
209static enum nss_status
d71b808a
UD
210parse_grp_str (const char *s, gid_t *gidp, int *gidlenp, gid_t *gidlist,
211 int *errnop)
e61abf83 212{
8e9b2075 213 char *ep;
e61abf83
UD
214 int gidlen;
215
216 if (!s || (!isdigit (*s)))
217 {
f1f0edfe 218 syslog (LOG_ERR, _("netname2user: missing group id list in `%s'."), s);
e61abf83
UD
219 return NSS_STATUS_NOTFOUND;
220 }
221
8e9b2075 222 *gidp = strtoul (s, &ep, 10);
e61abf83
UD
223
224 gidlen = 0;
225
8e9b2075 226 /* After strtoul() ep should point to the marker ',', which means
a334319f
UD
227 here starts a new value. */
228 while (ep != NULL && *ep == ',')
e61abf83 229 {
8e9b2075
UD
230 ep++;
231 s = ep;
232 gidlist[gidlen++] = strtoul (s, &ep, 10);
e61abf83
UD
233 }
234 *gidlenp = gidlen;
235
236 return NSS_STATUS_SUCCESS;
237}
238
239enum nss_status
240_nss_nisplus_netname2user (char netname[MAXNETNAMELEN + 1], uid_t *uidp,
d71b808a 241 gid_t *gidp, int *gidlenp, gid_t *gidlist, int *errnop)
e61abf83
UD
242{
243 char *domain;
244 nis_result *res;
a334319f 245 char sname[NIS_MAXNAMELEN+2]; /* search criteria + table name */
40a55d20 246 size_t slen;
a334319f 247 char principal[NIS_MAXNAMELEN+1];
e61abf83
UD
248 int len;
249
250 /* 1. Get home domain of user. */
251 domain = strchr (netname, '@');
252 if (! domain)
253 return NSS_STATUS_UNAVAIL;
254
d71b808a 255 ++domain; /* skip '@' */
e61abf83
UD
256
257 /* 2. Get user's nisplus principal name. */
a334319f
UD
258 if ((strlen (netname) + strlen (domain)+45) >
259 (size_t) NIS_MAXNAMELEN)
260 return NSS_STATUS_UNAVAIL;
261
40a55d20
UD
262 slen = snprintf (sname, NIS_MAXNAMELEN,
263 "[auth_name=%s,auth_type=DES],cred.org_dir.%s",
264 netname, domain);
265
a680290a
UD
266 if (slen >= NIS_MAXNAMELEN)
267 {
268 *errnop = EINVAL;
269 return NSS_STATUS_UNAVAIL;
270 }
271
40a55d20
UD
272 if (sname[slen - 1] != '.')
273 {
274 sname[slen++] = '.';
275 sname[slen] = '\0';
276 }
e61abf83
UD
277
278 /* must use authenticated call here */
279 /* XXX but we cant, for now. XXX */
280 res = nis_list (sname, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH,
281 NULL, NULL);
901956a5
UD
282 if (res == NULL)
283 {
284 *errnop = ENOMEM;
285 return NSS_STATUS_TRYAGAIN;
286 }
2d7da676 287 switch (res->status)
e61abf83
UD
288 {
289 case NIS_SUCCESS:
290 case NIS_S_SUCCESS:
291 break; /* go and do something useful */
292 case NIS_NOTFOUND:
293 case NIS_PARTIAL:
294 case NIS_NOSUCHNAME:
295 case NIS_NOSUCHTABLE:
296 nis_freeresult (res);
297 return NSS_STATUS_NOTFOUND;
298 case NIS_S_NOTFOUND:
299 case NIS_TRYAGAIN:
40a55d20 300 syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"),
e61abf83
UD
301 nis_sperrno (res->status));
302 nis_freeresult (res);
d71b808a 303 *errnop = errno;
e61abf83
UD
304 return NSS_STATUS_TRYAGAIN;
305 default:
40a55d20 306 syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"),
e61abf83
UD
307 nis_sperrno (res->status));
308 nis_freeresult (res);
309 return NSS_STATUS_UNAVAIL;
310 }
311
a334319f 312 if (res->objects.objects_len > 1)
d71b808a
UD
313 /*
314 * A netname belonging to more than one principal?
315 * Something wrong with cred table. should be unique.
316 * Warn user and continue.
317 */
318 syslog (LOG_ALERT,
319 _("netname2user: DES entry for %s in directory %s not unique"),
320 netname, domain);
e61abf83 321
a334319f
UD
322 len = ENTRY_LEN (res->objects.objects_val, 0);
323 strncpy (principal, ENTRY_VAL (res->objects.objects_val, 0), len);
e61abf83 324 principal[len] = '\0';
2d7da676 325 nis_freeresult (res);
e61abf83
UD
326
327 if (principal[0] == '\0')
328 return NSS_STATUS_UNAVAIL;
329
330 /*
ac9f45cf
UD
331 * 3. Use principal name to look up uid/gid information in
332 * LOCAL entry in **local** cred table.
e61abf83
UD
333 */
334 domain = nis_local_directory ();
a334319f 335 if ((strlen (principal) + strlen (domain) + 45) > (size_t) NIS_MAXNAMELEN)
e61abf83 336 {
f1f0edfe 337 syslog (LOG_ERR, _("netname2user: principal name `%s' too long"),
e61abf83
UD
338 principal);
339 return NSS_STATUS_UNAVAIL;
340 }
40a55d20 341
a334319f
UD
342 slen = sprintf (sname, "[cname=%s,auth_type=LOCAL],cred.org_dir.%s",
343 principal, domain);
40a55d20
UD
344
345 if (sname[slen - 1] != '.')
346 {
347 sname[slen++] = '.';
348 sname[slen] = '\0';
349 }
e61abf83
UD
350
351 /* must use authenticated call here */
352 /* XXX but we cant, for now. XXX */
2d7da676
UD
353 res = nis_list (sname, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH,
354 NULL, NULL);
901956a5
UD
355 if (res == NULL)
356 {
357 *errnop = ENOMEM;
358 return NSS_STATUS_TRYAGAIN;
359 }
2d7da676
UD
360 switch(res->status)
361 {
362 case NIS_NOTFOUND:
363 case NIS_PARTIAL:
364 case NIS_NOSUCHNAME:
365 case NIS_NOSUCHTABLE:
366 nis_freeresult (res);
367 return NSS_STATUS_NOTFOUND;
368 case NIS_S_NOTFOUND:
369 case NIS_TRYAGAIN:
40a55d20 370 syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"),
2d7da676
UD
371 nis_sperrno (res->status));
372 nis_freeresult (res);
d71b808a 373 *errnop = errno;
2d7da676
UD
374 return NSS_STATUS_TRYAGAIN;
375 case NIS_SUCCESS:
376 case NIS_S_SUCCESS:
377 break; /* go and do something useful */
378 default:
40a55d20 379 syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"),
2d7da676
UD
380 nis_sperrno (res->status));
381 nis_freeresult (res);
382 return NSS_STATUS_UNAVAIL;
383 }
e61abf83 384
a334319f 385 if (res->objects.objects_len > 1)
d71b808a
UD
386 /*
387 * A principal can have more than one LOCAL entry?
388 * Something wrong with cred table.
389 * Warn user and continue.
390 */
391 syslog (LOG_ALERT,
392 _("netname2user: LOCAL entry for %s in directory %s not unique"),
393 netname, domain);
e61abf83 394 /* Fetch the uid */
a334319f 395 *uidp = strtoul (ENTRY_VAL (res->objects.objects_val, 2), NULL, 10);
e61abf83
UD
396
397 if (*uidp == 0)
398 {
399 syslog (LOG_ERR, _("netname2user: should not have uid 0"));
400 return NSS_STATUS_NOTFOUND;
401 }
402
a334319f 403 parse_grp_str (ENTRY_VAL (res->objects.objects_val, 3),
d71b808a 404 gidp, gidlenp, gidlist, errnop);
e61abf83
UD
405
406 nis_freeresult (res);
407 return NSS_STATUS_SUCCESS;
408}