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.
231 The Sun man pages show that GIDLIST should contain at least NGRPS
232 elements. Limiting the number written by this value is the best
234 while (ep
!= NULL
&& *ep
== ',' && gidlen
< NGRPS
)
238 gidlist
[gidlen
++] = strtoul (s
, &ep
, 10);
242 return NSS_STATUS_SUCCESS
;
246 _nss_nisplus_netname2user (char netname
[MAXNETNAMELEN
+ 1], uid_t
*uidp
,
247 gid_t
*gidp
, int *gidlenp
, gid_t
*gidlist
, int *errnop
)
251 char sname
[NIS_MAXNAMELEN
+ 2]; /* search criteria + table name */
253 char principal
[NIS_MAXNAMELEN
+ 1];
256 /* 1. Get home domain of user. */
257 domain
= strchr (netname
, '@');
259 return NSS_STATUS_UNAVAIL
;
261 ++domain
; /* skip '@' */
263 /* 2. Get user's nisplus principal name. */
264 slen
= snprintf (sname
, NIS_MAXNAMELEN
,
265 "[auth_name=%s,auth_type=DES],cred.org_dir.%s",
268 if (slen
>= NIS_MAXNAMELEN
)
271 return NSS_STATUS_UNAVAIL
;
274 if (sname
[slen
- 1] != '.')
280 /* must use authenticated call here */
281 /* XXX but we cant, for now. XXX */
282 res
= nis_list (sname
, USE_DGRAM
+NO_AUTHINFO
+FOLLOW_LINKS
+FOLLOW_PATH
,
287 return NSS_STATUS_TRYAGAIN
;
293 break; /* go and do something useful */
297 case NIS_NOSUCHTABLE
:
298 nis_freeresult (res
);
299 return NSS_STATUS_NOTFOUND
;
302 syslog (LOG_ERR
, _("netname2user: (nis+ lookup): %s\n"),
303 nis_sperrno (res
->status
));
304 nis_freeresult (res
);
306 return NSS_STATUS_TRYAGAIN
;
308 syslog (LOG_ERR
, _("netname2user: (nis+ lookup): %s\n"),
309 nis_sperrno (res
->status
));
310 nis_freeresult (res
);
311 return NSS_STATUS_UNAVAIL
;
314 if (NIS_RES_NUMOBJ (res
) > 1)
316 * A netname belonging to more than one principal?
317 * Something wrong with cred table. should be unique.
318 * Warn user and continue.
321 _("netname2user: DES entry for %s in directory %s not unique"),
324 len
= ENTRY_LEN (NIS_RES_OBJECT (res
), 0);
325 strncpy (principal
, ENTRY_VAL (NIS_RES_OBJECT (res
), 0), len
);
326 principal
[len
] = '\0';
327 nis_freeresult (res
);
329 if (principal
[0] == '\0')
330 return NSS_STATUS_UNAVAIL
;
333 * 3. Use principal name to look up uid/gid information in
334 * LOCAL entry in **local** cred table.
336 domain
= nis_local_directory ();
337 if (strlen (principal
) + strlen (domain
) + 45 > (size_t) NIS_MAXNAMELEN
)
339 syslog (LOG_ERR
, _("netname2user: principal name `%s' too long"),
341 return NSS_STATUS_UNAVAIL
;
344 slen
= snprintf (sname
, sizeof (sname
),
345 "[cname=%s,auth_type=LOCAL],cred.org_dir.%s",
348 if (sname
[slen
- 1] != '.')
354 /* must use authenticated call here */
355 /* XXX but we cant, for now. XXX */
356 res
= nis_list (sname
, USE_DGRAM
+NO_AUTHINFO
+FOLLOW_LINKS
+FOLLOW_PATH
,
361 return NSS_STATUS_TRYAGAIN
;
368 case NIS_NOSUCHTABLE
:
369 nis_freeresult (res
);
370 return NSS_STATUS_NOTFOUND
;
373 syslog (LOG_ERR
, _("netname2user: (nis+ lookup): %s\n"),
374 nis_sperrno (res
->status
));
375 nis_freeresult (res
);
377 return NSS_STATUS_TRYAGAIN
;
380 break; /* go and do something useful */
382 syslog (LOG_ERR
, _("netname2user: (nis+ lookup): %s\n"),
383 nis_sperrno (res
->status
));
384 nis_freeresult (res
);
385 return NSS_STATUS_UNAVAIL
;
388 if (NIS_RES_NUMOBJ (res
) > 1)
390 * A principal can have more than one LOCAL entry?
391 * Something wrong with cred table.
392 * Warn user and continue.
395 _("netname2user: LOCAL entry for %s in directory %s not unique"),
398 *uidp
= strtoul (ENTRY_VAL (NIS_RES_OBJECT (res
), 2), NULL
, 10);
402 syslog (LOG_ERR
, _("netname2user: should not have uid 0"));
403 nis_freeresult (res
);
404 return NSS_STATUS_NOTFOUND
;
407 parse_grp_str (ENTRY_VAL (NIS_RES_OBJECT (res
), 3),
408 gidp
, gidlenp
, gidlist
, errnop
);
410 nis_freeresult (res
);
411 return NSS_STATUS_SUCCESS
;