]> git.ipfire.org Git - thirdparty/glibc.git/blame - nis/nss_nisplus/nisplus-publickey.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / nis / nss_nisplus / nisplus-publickey.c
CommitLineData
d614a753 1/* Copyright (c) 1997-2020 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 15 You should have received a copy of the GNU Lesser General Public
59ba27a6 16 License along with the GNU C Library; if not, see
5a82c748 17 <https://www.gnu.org/licenses/>. */
e61abf83
UD
18
19#include <nss.h>
20#include <ctype.h>
21#include <errno.h>
22#include <stdio.h>
23#include <string.h>
4360eafd 24#include <libintl.h>
e61abf83 25#include <syslog.h>
26dee9c4 26#include <rpc/rpc.h>
e61abf83 27#include <rpcsvc/nis.h>
26dee9c4
UD
28#include <rpc/key_prot.h>
29extern int xdecrypt (char *, char *);
e61abf83
UD
30
31#include <nss-nisplus.h>
32
26dee9c4 33/* If we haven't found the entry, we give a SUCCESS and an empty key back. */
e61abf83 34enum nss_status
d71b808a 35_nss_nisplus_getpublickey (const char *netname, char *pkey, int *errnop)
e61abf83
UD
36{
37 nis_result *res;
38 enum nss_status retval;
8e64faef 39 char buf[NIS_MAXNAMELEN + 2];
40a55d20 40 size_t slen;
e61abf83
UD
41 char *domain, *cptr;
42 int len;
43
44 pkey[0] = 0;
45
46 if (netname == NULL)
47 {
d71b808a 48 *errnop = EINVAL;
e61abf83
UD
49 return NSS_STATUS_UNAVAIL;
50 }
51
52 domain = strchr (netname, '@');
53 if (!domain)
54 return NSS_STATUS_UNAVAIL;
55 domain++;
56
40a55d20
UD
57 slen = snprintf (buf, NIS_MAXNAMELEN,
58 "[auth_name=%s,auth_type=DES],cred.org_dir.%s",
59 netname, domain);
e61abf83 60
a680290a
UD
61 if (slen >= NIS_MAXNAMELEN)
62 {
63 *errnop = EINVAL;
64 return NSS_STATUS_UNAVAIL;
65 }
66
40a55d20
UD
67 if (buf[slen - 1] != '.')
68 {
69 buf[slen++] = '.';
70 buf[slen] = '\0';
71 }
e61abf83 72
2d7da676
UD
73 res = nis_list (buf, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH,
74 NULL, NULL);
e61abf83 75
901956a5
UD
76 if (res == NULL)
77 {
78 *errnop = ENOMEM;
79 return NSS_STATUS_TRYAGAIN;
80 }
e61abf83
UD
81 retval = niserr2nss (res->status);
82
83 if (retval != NSS_STATUS_SUCCESS)
84 {
85 if (retval == NSS_STATUS_TRYAGAIN)
d71b808a 86 *errnop = errno;
26dee9c4
UD
87 if (res->status == NIS_NOTFOUND)
88 retval = NSS_STATUS_SUCCESS;
e61abf83
UD
89 nis_freeresult (res);
90 return retval;
91 }
92
004c6219 93 if (NIS_RES_NUMOBJ (res) > 1)
e61abf83
UD
94 {
95 /*
96 * More than one principal with same uid?
97 * something wrong with cred table. Should be unique
98 * Warn user and continue.
99 */
004c6219 100 syslog (LOG_ERR, _("DES entry for netname %s not unique\n"), netname);
e61abf83
UD
101 nis_freeresult (res);
102 return NSS_STATUS_SUCCESS;
103 }
104
004c6219
UD
105 len = ENTRY_LEN (NIS_RES_OBJECT (res), 3);
106 memcpy (pkey, ENTRY_VAL (NIS_RES_OBJECT (res),3), len);
e61abf83
UD
107 pkey[len] = 0;
108 cptr = strchr (pkey, ':');
109 if (cptr)
110 cptr[0] = '\0';
111 nis_freeresult (res);
112
113 return NSS_STATUS_SUCCESS;
114}
115
004c6219 116
e61abf83 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;
8e64faef 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
8e64faef 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
004c6219 175 if (NIS_RES_NUMOBJ (res) > 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 */
004c6219 182 syslog (LOG_ERR, _("DES entry for netname %s not unique\n"), netname);
e61abf83
UD
183 nis_freeresult (res);
184 return NSS_STATUS_SUCCESS;
185 }
186
004c6219
UD
187 len = ENTRY_LEN (NIS_RES_OBJECT (res), 4);
188 memcpy (buf, ENTRY_VAL (NIS_RES_OBJECT (res), 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
004c6219 207
e61abf83
UD
208/* Parse information from the passed string.
209 The format of the string passed is gid,grp,grp, ... */
210static enum nss_status
d71b808a
UD
211parse_grp_str (const char *s, gid_t *gidp, int *gidlenp, gid_t *gidlist,
212 int *errnop)
e61abf83 213{
8e9b2075 214 char *ep;
e61abf83
UD
215 int gidlen;
216
217 if (!s || (!isdigit (*s)))
218 {
11bf311e 219 syslog (LOG_ERR, _("netname2user: missing group id list in `%s'"), s);
e61abf83
UD
220 return NSS_STATUS_NOTFOUND;
221 }
222
8e9b2075 223 *gidp = strtoul (s, &ep, 10);
e61abf83
UD
224
225 gidlen = 0;
226
8e9b2075 227 /* After strtoul() ep should point to the marker ',', which means
5493f3dd
UD
228 here starts a new value.
229
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)
e61abf83 234 {
8e9b2075
UD
235 ep++;
236 s = ep;
237 gidlist[gidlen++] = strtoul (s, &ep, 10);
e61abf83
UD
238 }
239 *gidlenp = gidlen;
240
241 return NSS_STATUS_SUCCESS;
242}
243
244enum nss_status
245_nss_nisplus_netname2user (char netname[MAXNETNAMELEN + 1], uid_t *uidp,
d71b808a 246 gid_t *gidp, int *gidlenp, gid_t *gidlist, int *errnop)
e61abf83
UD
247{
248 char *domain;
249 nis_result *res;
8e64faef 250 char sname[NIS_MAXNAMELEN + 2]; /* search criteria + table name */
40a55d20 251 size_t slen;
8e64faef 252 char principal[NIS_MAXNAMELEN + 1];
e61abf83
UD
253 int len;
254
255 /* 1. Get home domain of user. */
256 domain = strchr (netname, '@');
257 if (! domain)
258 return NSS_STATUS_UNAVAIL;
259
d71b808a 260 ++domain; /* skip '@' */
e61abf83
UD
261
262 /* 2. Get user's nisplus principal name. */
40a55d20
UD
263 slen = snprintf (sname, NIS_MAXNAMELEN,
264 "[auth_name=%s,auth_type=DES],cred.org_dir.%s",
265 netname, domain);
266
a680290a
UD
267 if (slen >= NIS_MAXNAMELEN)
268 {
269 *errnop = EINVAL;
270 return NSS_STATUS_UNAVAIL;
271 }
272
40a55d20
UD
273 if (sname[slen - 1] != '.')
274 {
275 sname[slen++] = '.';
276 sname[slen] = '\0';
277 }
e61abf83
UD
278
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);
901956a5
UD
283 if (res == NULL)
284 {
285 *errnop = ENOMEM;
286 return NSS_STATUS_TRYAGAIN;
287 }
2d7da676 288 switch (res->status)
e61abf83
UD
289 {
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:
40a55d20 301 syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"),
e61abf83
UD
302 nis_sperrno (res->status));
303 nis_freeresult (res);
d71b808a 304 *errnop = errno;
e61abf83
UD
305 return NSS_STATUS_TRYAGAIN;
306 default:
40a55d20 307 syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"),
e61abf83
UD
308 nis_sperrno (res->status));
309 nis_freeresult (res);
310 return NSS_STATUS_UNAVAIL;
311 }
312
004c6219 313 if (NIS_RES_NUMOBJ (res) > 1)
d71b808a
UD
314 /*
315 * A netname belonging to more than one principal?
316 * Something wrong with cred table. should be unique.
317 * Warn user and continue.
318 */
319 syslog (LOG_ALERT,
320 _("netname2user: DES entry for %s in directory %s not unique"),
321 netname, domain);
e61abf83 322
004c6219
UD
323 len = ENTRY_LEN (NIS_RES_OBJECT (res), 0);
324 strncpy (principal, ENTRY_VAL (NIS_RES_OBJECT (res), 0), len);
e61abf83 325 principal[len] = '\0';
2d7da676 326 nis_freeresult (res);
e61abf83
UD
327
328 if (principal[0] == '\0')
329 return NSS_STATUS_UNAVAIL;
330
331 /*
ac9f45cf
UD
332 * 3. Use principal name to look up uid/gid information in
333 * LOCAL entry in **local** cred table.
e61abf83
UD
334 */
335 domain = nis_local_directory ();
004c6219 336 if (strlen (principal) + strlen (domain) + 45 > (size_t) NIS_MAXNAMELEN)
e61abf83 337 {
f1f0edfe 338 syslog (LOG_ERR, _("netname2user: principal name `%s' too long"),
e61abf83
UD
339 principal);
340 return NSS_STATUS_UNAVAIL;
341 }
40a55d20 342
8e64faef
UD
343 slen = snprintf (sname, sizeof (sname),
344 "[cname=%s,auth_type=LOCAL],cred.org_dir.%s",
345 principal, domain);
40a55d20
UD
346
347 if (sname[slen - 1] != '.')
348 {
349 sname[slen++] = '.';
350 sname[slen] = '\0';
351 }
e61abf83
UD
352
353 /* must use authenticated call here */
354 /* XXX but we cant, for now. XXX */
2d7da676
UD
355 res = nis_list (sname, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH,
356 NULL, NULL);
901956a5
UD
357 if (res == NULL)
358 {
359 *errnop = ENOMEM;
360 return NSS_STATUS_TRYAGAIN;
361 }
2d7da676
UD
362 switch(res->status)
363 {
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:
40a55d20 372 syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"),
2d7da676
UD
373 nis_sperrno (res->status));
374 nis_freeresult (res);
d71b808a 375 *errnop = errno;
2d7da676
UD
376 return NSS_STATUS_TRYAGAIN;
377 case NIS_SUCCESS:
378 case NIS_S_SUCCESS:
379 break; /* go and do something useful */
380 default:
40a55d20 381 syslog (LOG_ERR, _("netname2user: (nis+ lookup): %s\n"),
2d7da676
UD
382 nis_sperrno (res->status));
383 nis_freeresult (res);
384 return NSS_STATUS_UNAVAIL;
385 }
e61abf83 386
004c6219 387 if (NIS_RES_NUMOBJ (res) > 1)
d71b808a
UD
388 /*
389 * A principal can have more than one LOCAL entry?
390 * Something wrong with cred table.
391 * Warn user and continue.
392 */
393 syslog (LOG_ALERT,
394 _("netname2user: LOCAL entry for %s in directory %s not unique"),
395 netname, domain);
e61abf83 396 /* Fetch the uid */
004c6219 397 *uidp = strtoul (ENTRY_VAL (NIS_RES_OBJECT (res), 2), NULL, 10);
e61abf83
UD
398
399 if (*uidp == 0)
400 {
401 syslog (LOG_ERR, _("netname2user: should not have uid 0"));
0292b0dd 402 nis_freeresult (res);
e61abf83
UD
403 return NSS_STATUS_NOTFOUND;
404 }
405
004c6219 406 parse_grp_str (ENTRY_VAL (NIS_RES_OBJECT (res), 3),
d71b808a 407 gidp, gidlenp, gidlist, errnop);
e61abf83
UD
408
409 nis_freeresult (res);
410 return NSS_STATUS_SUCCESS;
411}