1 /* Copyright (c) 1997-2016 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/>. */
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. */
35 _nss_nisplus_getpublickey (const char *netname
, char *pkey
, int *errnop
)
38 enum nss_status retval
;
39 char buf
[NIS_MAXNAMELEN
+ 2];
49 return NSS_STATUS_UNAVAIL
;
52 domain
= strchr (netname
, '@');
54 return NSS_STATUS_UNAVAIL
;
57 slen
= snprintf (buf
, NIS_MAXNAMELEN
,
58 "[auth_name=%s,auth_type=DES],cred.org_dir.%s",
61 if (slen
>= NIS_MAXNAMELEN
)
64 return NSS_STATUS_UNAVAIL
;
67 if (buf
[slen
- 1] != '.')
73 res
= nis_list (buf
, USE_DGRAM
+NO_AUTHINFO
+FOLLOW_LINKS
+FOLLOW_PATH
,
79 return NSS_STATUS_TRYAGAIN
;
81 retval
= niserr2nss (res
->status
);
83 if (retval
!= NSS_STATUS_SUCCESS
)
85 if (retval
== NSS_STATUS_TRYAGAIN
)
87 if (res
->status
== NIS_NOTFOUND
)
88 retval
= NSS_STATUS_SUCCESS
;
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
);
108 cptr
= strchr (pkey
, ':');
111 nis_freeresult (res
);
113 return NSS_STATUS_SUCCESS
;
118 _nss_nisplus_getsecretkey (const char *netname
, char *skey
, char *passwd
,
122 enum nss_status retval
;
123 char buf
[NIS_MAXNAMELEN
+ 2];
133 return NSS_STATUS_UNAVAIL
;
136 domain
= strchr (netname
, '@');
138 return NSS_STATUS_UNAVAIL
;
141 slen
= snprintf (buf
, NIS_MAXNAMELEN
,
142 "[auth_name=%s,auth_type=DES],cred.org_dir.%s",
145 if (slen
>= NIS_MAXNAMELEN
)
148 return NSS_STATUS_UNAVAIL
;
151 if (buf
[slen
- 1] != '.')
157 res
= nis_list (buf
, USE_DGRAM
| NO_AUTHINFO
| FOLLOW_LINKS
| FOLLOW_PATH
,
163 return NSS_STATUS_TRYAGAIN
;
165 retval
= niserr2nss (res
->status
);
167 if (retval
!= NSS_STATUS_SUCCESS
)
169 if (retval
== NSS_STATUS_TRYAGAIN
)
171 nis_freeresult (res
);
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
);
190 cptr
= strchr (buf
, ':');
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;
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
,
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);
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
233 while (ep
!= NULL
&& *ep
== ',' && gidlen
< NGRPS
)
237 gidlist
[gidlen
++] = strtoul (s
, &ep
, 10);
241 return NSS_STATUS_SUCCESS
;
245 _nss_nisplus_netname2user (char netname
[MAXNETNAMELEN
+ 1], uid_t
*uidp
,
246 gid_t
*gidp
, int *gidlenp
, gid_t
*gidlist
, int *errnop
)
250 char sname
[NIS_MAXNAMELEN
+ 2]; /* search criteria + table name */
252 char principal
[NIS_MAXNAMELEN
+ 1];
255 /* 1. Get home domain of user. */
256 domain
= strchr (netname
, '@');
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",
267 if (slen
>= NIS_MAXNAMELEN
)
270 return NSS_STATUS_UNAVAIL
;
273 if (sname
[slen
- 1] != '.')
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
,
286 return NSS_STATUS_TRYAGAIN
;
292 break; /* go and do something useful */
296 case NIS_NOSUCHTABLE
:
297 nis_freeresult (res
);
298 return NSS_STATUS_NOTFOUND
;
301 syslog (LOG_ERR
, _("netname2user: (nis+ lookup): %s\n"),
302 nis_sperrno (res
->status
));
303 nis_freeresult (res
);
305 return NSS_STATUS_TRYAGAIN
;
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.
320 _("netname2user: DES entry for %s in directory %s not unique"),
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"),
340 return NSS_STATUS_UNAVAIL
;
343 slen
= snprintf (sname
, sizeof (sname
),
344 "[cname=%s,auth_type=LOCAL],cred.org_dir.%s",
347 if (sname
[slen
- 1] != '.')
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
,
360 return NSS_STATUS_TRYAGAIN
;
367 case NIS_NOSUCHTABLE
:
368 nis_freeresult (res
);
369 return NSS_STATUS_NOTFOUND
;
372 syslog (LOG_ERR
, _("netname2user: (nis+ lookup): %s\n"),
373 nis_sperrno (res
->status
));
374 nis_freeresult (res
);
376 return NSS_STATUS_TRYAGAIN
;
379 break; /* go and do something useful */
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.
394 _("netname2user: LOCAL entry for %s in directory %s not unique"),
397 *uidp
= strtoul (ENTRY_VAL (NIS_RES_OBJECT (res
), 2), NULL
, 10);
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
;