1 /* Copyright (c) 1997, 1999, 2001, 2003 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, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 #include <rpcsvc/nis.h>
29 #include <rpc/key_prot.h>
30 extern int xdecrypt (char *, char *);
32 #include <nss-nisplus.h>
34 /* If we haven't found the entry, we give a SUCCESS and an empty key back. */
36 _nss_nisplus_getpublickey (const char *netname
, char *pkey
, int *errnop
)
39 enum nss_status retval
;
40 char buf
[NIS_MAXNAMELEN
+2];
50 return NSS_STATUS_UNAVAIL
;
53 domain
= strchr (netname
, '@');
55 return NSS_STATUS_UNAVAIL
;
58 slen
= snprintf (buf
, NIS_MAXNAMELEN
,
59 "[auth_name=%s,auth_type=DES],cred.org_dir.%s",
62 if (slen
>= NIS_MAXNAMELEN
)
65 return NSS_STATUS_UNAVAIL
;
68 if (buf
[slen
- 1] != '.')
74 res
= nis_list (buf
, USE_DGRAM
+NO_AUTHINFO
+FOLLOW_LINKS
+FOLLOW_PATH
,
80 return NSS_STATUS_TRYAGAIN
;
82 retval
= niserr2nss (res
->status
);
84 if (retval
!= NSS_STATUS_SUCCESS
)
86 if (retval
== NSS_STATUS_TRYAGAIN
)
88 if (res
->status
== NIS_NOTFOUND
)
89 retval
= NSS_STATUS_SUCCESS
;
94 if (res
->objects
.objects_len
> 1)
97 * More than one principal with same uid?
98 * something wrong with cred table. Should be unique
99 * Warn user and continue.
101 printf (_("DES entry for netname %s not unique\n"), netname
);
102 nis_freeresult (res
);
103 return NSS_STATUS_SUCCESS
;
106 len
= ENTRY_LEN (res
->objects
.objects_val
, 3);
107 memcpy (pkey
, ENTRY_VAL (res
->objects
.objects_val
,3), len
);
109 cptr
= strchr (pkey
, ':');
112 nis_freeresult (res
);
114 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 (res
->objects
.objects_len
> 1)
178 * More than one principal with same uid?
179 * something wrong with cred table. Should be unique
180 * Warn user and continue.
182 printf (_("DES entry for netname %s not unique\n"), netname
);
183 nis_freeresult (res
);
184 return NSS_STATUS_SUCCESS
;
187 len
= ENTRY_LEN (res
->objects
.objects_val
, 4);
188 memcpy (buf
, ENTRY_VAL (res
->objects
.objects_val
,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
;
207 /* Parse information from the passed string.
208 The format of the string passed is gid,grp,grp, ... */
209 static enum nss_status
210 parse_grp_str (const char *s
, gid_t
*gidp
, int *gidlenp
, gid_t
*gidlist
,
216 if (!s
|| (!isdigit (*s
)))
218 syslog (LOG_ERR
, _("netname2user: missing group id list in `%s'."), s
);
219 return NSS_STATUS_NOTFOUND
;
222 *gidp
= strtoul (s
, &ep
, 10);
226 /* After strtoul() ep should point to the marker ',', which means
227 here starts a new value. */
228 while (ep
!= NULL
&& *ep
== ',')
232 gidlist
[gidlen
++] = strtoul (s
, &ep
, 10);
236 return NSS_STATUS_SUCCESS
;
240 _nss_nisplus_netname2user (char netname
[MAXNETNAMELEN
+ 1], uid_t
*uidp
,
241 gid_t
*gidp
, int *gidlenp
, gid_t
*gidlist
, int *errnop
)
245 char sname
[NIS_MAXNAMELEN
+2]; /* search criteria + table name */
247 char principal
[NIS_MAXNAMELEN
+1];
250 /* 1. Get home domain of user. */
251 domain
= strchr (netname
, '@');
253 return NSS_STATUS_UNAVAIL
;
255 ++domain
; /* skip '@' */
257 /* 2. Get user's nisplus principal name. */
258 if ((strlen (netname
) + strlen (domain
)+45) >
259 (size_t) NIS_MAXNAMELEN
)
260 return NSS_STATUS_UNAVAIL
;
262 slen
= snprintf (sname
, NIS_MAXNAMELEN
,
263 "[auth_name=%s,auth_type=DES],cred.org_dir.%s",
266 if (slen
>= NIS_MAXNAMELEN
)
269 return NSS_STATUS_UNAVAIL
;
272 if (sname
[slen
- 1] != '.')
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
,
285 return NSS_STATUS_TRYAGAIN
;
291 break; /* go and do something useful */
295 case NIS_NOSUCHTABLE
:
296 nis_freeresult (res
);
297 return NSS_STATUS_NOTFOUND
;
300 syslog (LOG_ERR
, _("netname2user: (nis+ lookup): %s\n"),
301 nis_sperrno (res
->status
));
302 nis_freeresult (res
);
304 return NSS_STATUS_TRYAGAIN
;
306 syslog (LOG_ERR
, _("netname2user: (nis+ lookup): %s\n"),
307 nis_sperrno (res
->status
));
308 nis_freeresult (res
);
309 return NSS_STATUS_UNAVAIL
;
312 if (res
->objects
.objects_len
> 1)
314 * A netname belonging to more than one principal?
315 * Something wrong with cred table. should be unique.
316 * Warn user and continue.
319 _("netname2user: DES entry for %s in directory %s not unique"),
322 len
= ENTRY_LEN (res
->objects
.objects_val
, 0);
323 strncpy (principal
, ENTRY_VAL (res
->objects
.objects_val
, 0), len
);
324 principal
[len
] = '\0';
325 nis_freeresult (res
);
327 if (principal
[0] == '\0')
328 return NSS_STATUS_UNAVAIL
;
331 * 3. Use principal name to look up uid/gid information in
332 * LOCAL entry in **local** cred table.
334 domain
= nis_local_directory ();
335 if ((strlen (principal
) + strlen (domain
) + 45) > (size_t) NIS_MAXNAMELEN
)
337 syslog (LOG_ERR
, _("netname2user: principal name `%s' too long"),
339 return NSS_STATUS_UNAVAIL
;
342 slen
= sprintf (sname
, "[cname=%s,auth_type=LOCAL],cred.org_dir.%s",
345 if (sname
[slen
- 1] != '.')
351 /* must use authenticated call here */
352 /* XXX but we cant, for now. XXX */
353 res
= nis_list (sname
, USE_DGRAM
+NO_AUTHINFO
+FOLLOW_LINKS
+FOLLOW_PATH
,
358 return NSS_STATUS_TRYAGAIN
;
365 case NIS_NOSUCHTABLE
:
366 nis_freeresult (res
);
367 return NSS_STATUS_NOTFOUND
;
370 syslog (LOG_ERR
, _("netname2user: (nis+ lookup): %s\n"),
371 nis_sperrno (res
->status
));
372 nis_freeresult (res
);
374 return NSS_STATUS_TRYAGAIN
;
377 break; /* go and do something useful */
379 syslog (LOG_ERR
, _("netname2user: (nis+ lookup): %s\n"),
380 nis_sperrno (res
->status
));
381 nis_freeresult (res
);
382 return NSS_STATUS_UNAVAIL
;
385 if (res
->objects
.objects_len
> 1)
387 * A principal can have more than one LOCAL entry?
388 * Something wrong with cred table.
389 * Warn user and continue.
392 _("netname2user: LOCAL entry for %s in directory %s not unique"),
395 *uidp
= strtoul (ENTRY_VAL (res
->objects
.objects_val
, 2), NULL
, 10);
399 syslog (LOG_ERR
, _("netname2user: should not have uid 0"));
400 return NSS_STATUS_NOTFOUND
;
403 parse_grp_str (ENTRY_VAL (res
->objects
.objects_val
, 3),
404 gidp
, gidlenp
, gidlist
, errnop
);
406 nis_freeresult (res
);
407 return NSS_STATUS_SUCCESS
;