1 /* Copyright (c) 1997, 1999, 2001, 2003, 2005 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 slen
= snprintf (sname
, NIS_MAXNAMELEN
,
259 "[auth_name=%s,auth_type=DES],cred.org_dir.%s",
262 if (slen
>= NIS_MAXNAMELEN
)
265 return NSS_STATUS_UNAVAIL
;
268 if (sname
[slen
- 1] != '.')
274 /* must use authenticated call here */
275 /* XXX but we cant, for now. XXX */
276 res
= nis_list (sname
, USE_DGRAM
+NO_AUTHINFO
+FOLLOW_LINKS
+FOLLOW_PATH
,
281 return NSS_STATUS_TRYAGAIN
;
287 break; /* go and do something useful */
291 case NIS_NOSUCHTABLE
:
292 nis_freeresult (res
);
293 return NSS_STATUS_NOTFOUND
;
296 syslog (LOG_ERR
, _("netname2user: (nis+ lookup): %s\n"),
297 nis_sperrno (res
->status
));
298 nis_freeresult (res
);
300 return NSS_STATUS_TRYAGAIN
;
302 syslog (LOG_ERR
, _("netname2user: (nis+ lookup): %s\n"),
303 nis_sperrno (res
->status
));
304 nis_freeresult (res
);
305 return NSS_STATUS_UNAVAIL
;
308 if (res
->objects
.objects_len
> 1)
310 * A netname belonging to more than one principal?
311 * Something wrong with cred table. should be unique.
312 * Warn user and continue.
315 _("netname2user: DES entry for %s in directory %s not unique"),
318 len
= ENTRY_LEN (res
->objects
.objects_val
, 0);
319 strncpy (principal
, ENTRY_VAL (res
->objects
.objects_val
, 0), len
);
320 principal
[len
] = '\0';
321 nis_freeresult (res
);
323 if (principal
[0] == '\0')
324 return NSS_STATUS_UNAVAIL
;
327 * 3. Use principal name to look up uid/gid information in
328 * LOCAL entry in **local** cred table.
330 domain
= nis_local_directory ();
331 if ((strlen (principal
) + strlen (domain
) + 45) > (size_t) NIS_MAXNAMELEN
)
333 syslog (LOG_ERR
, _("netname2user: principal name `%s' too long"),
335 return NSS_STATUS_UNAVAIL
;
338 slen
= snprintf (sname
, sizeof (sname
),
339 "[cname=%s,auth_type=LOCAL],cred.org_dir.%s",
342 if (sname
[slen
- 1] != '.')
348 /* must use authenticated call here */
349 /* XXX but we cant, for now. XXX */
350 res
= nis_list (sname
, USE_DGRAM
+NO_AUTHINFO
+FOLLOW_LINKS
+FOLLOW_PATH
,
355 return NSS_STATUS_TRYAGAIN
;
362 case NIS_NOSUCHTABLE
:
363 nis_freeresult (res
);
364 return NSS_STATUS_NOTFOUND
;
367 syslog (LOG_ERR
, _("netname2user: (nis+ lookup): %s\n"),
368 nis_sperrno (res
->status
));
369 nis_freeresult (res
);
371 return NSS_STATUS_TRYAGAIN
;
374 break; /* go and do something useful */
376 syslog (LOG_ERR
, _("netname2user: (nis+ lookup): %s\n"),
377 nis_sperrno (res
->status
));
378 nis_freeresult (res
);
379 return NSS_STATUS_UNAVAIL
;
382 if (res
->objects
.objects_len
> 1)
384 * A principal can have more than one LOCAL entry?
385 * Something wrong with cred table.
386 * Warn user and continue.
389 _("netname2user: LOCAL entry for %s in directory %s not unique"),
392 *uidp
= strtoul (ENTRY_VAL (res
->objects
.objects_val
, 2), NULL
, 10);
396 syslog (LOG_ERR
, _("netname2user: should not have uid 0"));
397 return NSS_STATUS_NOTFOUND
;
400 parse_grp_str (ENTRY_VAL (res
->objects
.objects_val
, 3),
401 gidp
, gidlenp
, gidlist
, errnop
);
403 nis_freeresult (res
);
404 return NSS_STATUS_SUCCESS
;