1 /* Copyright (c) 1997,1999,2001,2003,2005,2006 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 (NIS_RES_NUMOBJ (res
) > 1)
97 * More than one principal with same uid?
98 * something wrong with cred table. Should be unique
99 * Warn user and continue.
101 syslog (LOG_ERR
, _("DES entry for netname %s not unique\n"), netname
);
102 nis_freeresult (res
);
103 return NSS_STATUS_SUCCESS
;
106 len
= ENTRY_LEN (NIS_RES_OBJECT (res
), 3);
107 memcpy (pkey
, ENTRY_VAL (NIS_RES_OBJECT (res
),3), len
);
109 cptr
= strchr (pkey
, ':');
112 nis_freeresult (res
);
114 return NSS_STATUS_SUCCESS
;
119 _nss_nisplus_getsecretkey (const char *netname
, char *skey
, char *passwd
,
123 enum nss_status retval
;
124 char buf
[NIS_MAXNAMELEN
+ 2];
134 return NSS_STATUS_UNAVAIL
;
137 domain
= strchr (netname
, '@');
139 return NSS_STATUS_UNAVAIL
;
142 slen
= snprintf (buf
, NIS_MAXNAMELEN
,
143 "[auth_name=%s,auth_type=DES],cred.org_dir.%s",
146 if (slen
>= NIS_MAXNAMELEN
)
149 return NSS_STATUS_UNAVAIL
;
152 if (buf
[slen
- 1] != '.')
158 res
= nis_list (buf
, USE_DGRAM
| NO_AUTHINFO
| FOLLOW_LINKS
| FOLLOW_PATH
,
164 return NSS_STATUS_TRYAGAIN
;
166 retval
= niserr2nss (res
->status
);
168 if (retval
!= NSS_STATUS_SUCCESS
)
170 if (retval
== NSS_STATUS_TRYAGAIN
)
172 nis_freeresult (res
);
176 if (NIS_RES_NUMOBJ (res
) > 1)
179 * More than one principal with same uid?
180 * something wrong with cred table. Should be unique
181 * Warn user and continue.
183 syslog (LOG_ERR
, _("DES entry for netname %s not unique\n"), netname
);
184 nis_freeresult (res
);
185 return NSS_STATUS_SUCCESS
;
188 len
= ENTRY_LEN (NIS_RES_OBJECT (res
), 4);
189 memcpy (buf
, ENTRY_VAL (NIS_RES_OBJECT (res
), 4), len
);
191 cptr
= strchr (buf
, ':');
194 nis_freeresult (res
);
196 if (!xdecrypt (buf
, passwd
))
197 return NSS_STATUS_SUCCESS
;
199 if (memcmp (buf
, &(buf
[HEXKEYBYTES
]), KEYCHECKSUMSIZE
) != 0)
200 return NSS_STATUS_SUCCESS
;
202 buf
[HEXKEYBYTES
] = 0;
205 return NSS_STATUS_SUCCESS
;
209 /* Parse information from the passed string.
210 The format of the string passed is gid,grp,grp, ... */
211 static enum nss_status
212 parse_grp_str (const char *s
, gid_t
*gidp
, int *gidlenp
, gid_t
*gidlist
,
218 if (!s
|| (!isdigit (*s
)))
220 syslog (LOG_ERR
, _("netname2user: missing group id list in `%s'."), s
);
221 return NSS_STATUS_NOTFOUND
;
224 *gidp
= strtoul (s
, &ep
, 10);
228 /* After strtoul() ep should point to the marker ',', which means
229 here starts a new value. */
230 while (ep
!= NULL
&& *ep
== ',')
234 gidlist
[gidlen
++] = strtoul (s
, &ep
, 10);
238 return NSS_STATUS_SUCCESS
;
242 _nss_nisplus_netname2user (char netname
[MAXNETNAMELEN
+ 1], uid_t
*uidp
,
243 gid_t
*gidp
, int *gidlenp
, gid_t
*gidlist
, int *errnop
)
247 char sname
[NIS_MAXNAMELEN
+ 2]; /* search criteria + table name */
249 char principal
[NIS_MAXNAMELEN
+ 1];
252 /* 1. Get home domain of user. */
253 domain
= strchr (netname
, '@');
255 return NSS_STATUS_UNAVAIL
;
257 ++domain
; /* skip '@' */
259 /* 2. Get user's nisplus principal name. */
260 slen
= snprintf (sname
, NIS_MAXNAMELEN
,
261 "[auth_name=%s,auth_type=DES],cred.org_dir.%s",
264 if (slen
>= NIS_MAXNAMELEN
)
267 return NSS_STATUS_UNAVAIL
;
270 if (sname
[slen
- 1] != '.')
276 /* must use authenticated call here */
277 /* XXX but we cant, for now. XXX */
278 res
= nis_list (sname
, USE_DGRAM
+NO_AUTHINFO
+FOLLOW_LINKS
+FOLLOW_PATH
,
283 return NSS_STATUS_TRYAGAIN
;
289 break; /* go and do something useful */
293 case NIS_NOSUCHTABLE
:
294 nis_freeresult (res
);
295 return NSS_STATUS_NOTFOUND
;
298 syslog (LOG_ERR
, _("netname2user: (nis+ lookup): %s\n"),
299 nis_sperrno (res
->status
));
300 nis_freeresult (res
);
302 return NSS_STATUS_TRYAGAIN
;
304 syslog (LOG_ERR
, _("netname2user: (nis+ lookup): %s\n"),
305 nis_sperrno (res
->status
));
306 nis_freeresult (res
);
307 return NSS_STATUS_UNAVAIL
;
310 if (NIS_RES_NUMOBJ (res
) > 1)
312 * A netname belonging to more than one principal?
313 * Something wrong with cred table. should be unique.
314 * Warn user and continue.
317 _("netname2user: DES entry for %s in directory %s not unique"),
320 len
= ENTRY_LEN (NIS_RES_OBJECT (res
), 0);
321 strncpy (principal
, ENTRY_VAL (NIS_RES_OBJECT (res
), 0), len
);
322 principal
[len
] = '\0';
323 nis_freeresult (res
);
325 if (principal
[0] == '\0')
326 return NSS_STATUS_UNAVAIL
;
329 * 3. Use principal name to look up uid/gid information in
330 * LOCAL entry in **local** cred table.
332 domain
= nis_local_directory ();
333 if (strlen (principal
) + strlen (domain
) + 45 > (size_t) NIS_MAXNAMELEN
)
335 syslog (LOG_ERR
, _("netname2user: principal name `%s' too long"),
337 return NSS_STATUS_UNAVAIL
;
340 slen
= snprintf (sname
, sizeof (sname
),
341 "[cname=%s,auth_type=LOCAL],cred.org_dir.%s",
344 if (sname
[slen
- 1] != '.')
350 /* must use authenticated call here */
351 /* XXX but we cant, for now. XXX */
352 res
= nis_list (sname
, USE_DGRAM
+NO_AUTHINFO
+FOLLOW_LINKS
+FOLLOW_PATH
,
357 return NSS_STATUS_TRYAGAIN
;
364 case NIS_NOSUCHTABLE
:
365 nis_freeresult (res
);
366 return NSS_STATUS_NOTFOUND
;
369 syslog (LOG_ERR
, _("netname2user: (nis+ lookup): %s\n"),
370 nis_sperrno (res
->status
));
371 nis_freeresult (res
);
373 return NSS_STATUS_TRYAGAIN
;
376 break; /* go and do something useful */
378 syslog (LOG_ERR
, _("netname2user: (nis+ lookup): %s\n"),
379 nis_sperrno (res
->status
));
380 nis_freeresult (res
);
381 return NSS_STATUS_UNAVAIL
;
384 if (NIS_RES_NUMOBJ (res
) > 1)
386 * A principal can have more than one LOCAL entry?
387 * Something wrong with cred table.
388 * Warn user and continue.
391 _("netname2user: LOCAL entry for %s in directory %s not unique"),
394 *uidp
= strtoul (ENTRY_VAL (NIS_RES_OBJECT (res
), 2), NULL
, 10);
398 syslog (LOG_ERR
, _("netname2user: should not have uid 0"));
399 nis_freeresult (res
);
400 return NSS_STATUS_NOTFOUND
;
403 parse_grp_str (ENTRY_VAL (NIS_RES_OBJECT (res
), 3),
404 gidp
, gidlenp
, gidlist
, errnop
);
406 nis_freeresult (res
);
407 return NSS_STATUS_SUCCESS
;