4 * nsswitch idmapping functions.
6 * Copyright (c) 2004 The Regents of the University of Michigan.
9 * J. Bruce Fields <bfields@umich.edu>
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
25 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
31 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 #include <sys/types.h>
48 #include "nfsidmap_internal.h"
53 * NSS Translation Methods
55 * These are all just wrappers around getpwnam and friends;
56 * we tack on the given domain to the results of getpwnam when looking up a uid,
57 * and ignore the domain entirely when looking up a name.
60 static int write_name(char *dest
, char *localname
, char *domain
, size_t len
)
62 if (strlen(localname
) + 1 + strlen(domain
) + 1 > len
) {
63 return -ENOMEM
; /* XXX: Is there an -ETOOLONG? */
65 strcpy(dest
, localname
);
71 static int nss_uid_to_name(uid_t uid
, char *domain
, char *name
, size_t len
)
73 struct passwd
*pw
= NULL
;
76 size_t buflen
= sysconf(_SC_GETPW_R_SIZE_MAX
);
83 domain
= get_default_domain();
84 err
= -getpwuid_r(uid
, &pwbuf
, buf
, buflen
, &pw
);
89 err
= write_name(name
, pw
->pw_name
, domain
, len
);
96 static int nss_gid_to_name(gid_t gid
, char *domain
, char *name
, size_t len
)
98 struct group
*gr
= NULL
;
101 size_t buflen
= sysconf(_SC_GETGR_R_SIZE_MAX
);
105 domain
= get_default_domain();
109 buf
= malloc(buflen
);
112 err
= -getgrgid_r(gid
, &grbuf
, buf
, buflen
, &gr
);
113 if (gr
== NULL
&& !err
)
115 if (err
== -ERANGE
) {
119 } while (err
== -ERANGE
);
123 err
= write_name(name
, gr
->gr_name
, domain
, len
);
130 /* XXX: actually should return error, so can distinguish between
131 * memory allocation failure and failure to match domain */
132 static char *strip_domain(const char *name
, const char *domain
)
138 c
= strrchr(name
, '@');
139 if (c
== NULL
&& domain
!= NULL
)
141 if (c
== NULL
&& domain
== NULL
) {
142 len
= strlen(name
) + 1;
144 if (domain
&& strcasecmp(c
+ 1, domain
) != 0)
152 memcpy(l
, name
, len
);
163 static struct passwd
*nss_getpwnam(const char *name
, const char *domain
, int *err_p
)
167 size_t buflen
= sysconf(_SC_GETPW_R_SIZE_MAX
);
171 buf
= malloc(sizeof(*buf
) + buflen
);
176 localname
= strip_domain(name
, domain
);
177 IDMAP_LOG(4, ("nss_getpwnam: name '%s' domain '%s': "
178 "resulting localname '%s'\n", name
, domain
, localname
));
179 if (localname
== NULL
) {
180 IDMAP_LOG(0, ("nss_getpwnam: name '%s' does not map "
181 "into domain '%s'\n", name
,
182 domain
? domain
: "<not-provided>"));
186 err
= getpwnam_r(localname
, &buf
->pwbuf
, buf
->buf
, buflen
, &pw
);
187 if (pw
== NULL
&& domain
!= NULL
)
189 ("nss_getpwnam: name '%s' not found in domain '%s'\n",
192 if (err
== 0 && pw
!= NULL
) {
195 } else if (err
== 0 && pw
== NULL
) {
206 static int nss_name_to_uid(char *name
, uid_t
*uid
)
208 struct passwd
*pw
= NULL
;
212 domain
= get_default_domain();
213 pw
= nss_getpwnam(name
, domain
, &err
);
223 static int nss_name_to_gid(char *name
, gid_t
*gid
)
225 struct group
*gr
= NULL
;
227 char *buf
, *localname
, *domain
;
228 size_t buflen
= sysconf(_SC_GETGR_R_SIZE_MAX
);
231 domain
= get_default_domain();
232 localname
= strip_domain(name
, domain
);
238 buf
= malloc(buflen
);
241 err
= -getgrnam_r(localname
, &grbuf
, buf
, buflen
, &gr
);
242 if (gr
== NULL
&& !err
)
244 if (err
== -ERANGE
) {
248 } while (err
== -ERANGE
);
261 static int nss_gss_princ_to_ids(char *secname
, char *princ
,
262 uid_t
*uid
, uid_t
*gid
,
263 extra_mapping_params
**ex
)
268 struct conf_list
*realms
;
269 struct conf_list_node
*r
;
272 if (strcmp(secname
, "spkm3") == 0)
275 if (strcmp(secname
, "krb5") != 0)
278 /* get princ's realm */
279 princ_realm
= strstr(princ
, "@");
280 if (princ_realm
== NULL
)
284 /* get list of "local-equivalent" realms and
285 * check against the principal's realm */
286 realms
= get_local_realms();
287 TAILQ_FOREACH(r
, &realms
->fields
, link
) {
288 if (strcmp(r
->field
, princ_realm
) == 0) {
294 IDMAP_LOG(1, ("nss_gss_princ_to_ids: Local-Realm '%s': NOT FOUND",
298 /* XXX: this should call something like getgssauthnam instead? */
299 pw
= nss_getpwnam(princ
, NULL
, &err
);
311 int nss_gss_princ_to_grouplist(char *secname
, char *princ
,
312 gid_t
*groups
, int *ngroups
,
313 extra_mapping_params
**ex
)
318 if (strcmp(secname
, "krb5") != 0)
320 /* XXX: not quite right? Need to know default realm? */
321 /* XXX: this should call something like getgssauthnam instead? */
322 pw
= nss_getpwnam(princ
, NULL
, &ret
);
327 if (getgrouplist(pw
->pw_name
, pw
->pw_gid
, groups
, ngroups
) < 0)
335 struct trans_func nss_trans
= {
338 .princ_to_ids
= nss_gss_princ_to_ids
,
339 .name_to_uid
= nss_name_to_uid
,
340 .name_to_gid
= nss_name_to_gid
,
341 .uid_to_name
= nss_uid_to_name
,
342 .gid_to_name
= nss_gid_to_name
,
343 .gss_princ_to_grouplist
= nss_gss_princ_to_grouplist
,
346 struct trans_func
*libnfsidmap_plugin_init()