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