diff options
-rw-r--r-- | usr/src/cmd/fs.d/nfs/nfsmapid/Makefile | 2 | ||||
-rw-r--r-- | usr/src/cmd/fs.d/nfs/nfsmapid/nfsmapid_server.c | 245 | ||||
-rw-r--r-- | usr/src/cmd/fs.d/nfs/nfsmapid/nfsmapid_test.c | 49 | ||||
-rw-r--r-- | usr/src/cmd/fs.d/nfs/svc/mapid.xml | 14 | ||||
-rw-r--r-- | usr/src/cmd/idmap/idmapd/dbutils.c | 29 | ||||
-rw-r--r-- | usr/src/lib/libidmap/common/idmap.h | 17 | ||||
-rw-r--r-- | usr/src/lib/libidmap/common/idmap_api.c | 128 | ||||
-rw-r--r-- | usr/src/lib/libidmap/common/mapfile-vers | 4 |
8 files changed, 376 insertions, 112 deletions
diff --git a/usr/src/cmd/fs.d/nfs/nfsmapid/Makefile b/usr/src/cmd/fs.d/nfs/nfsmapid/Makefile index 57cf975cfc..7ffb2b5722 100644 --- a/usr/src/cmd/fs.d/nfs/nfsmapid/Makefile +++ b/usr/src/cmd/fs.d/nfs/nfsmapid/Makefile @@ -33,7 +33,7 @@ ATTMK = $(TYPEPROG) include ../../Makefile.fstype LDLIBS += -L$(ROOT)/usr/lib/nfs -R/usr/lib/nfs -LDLIBS += -lnsl -lmapid -ldoor -ldtrace +LDLIBS += -lnsl -lmapid -ldoor -ldtrace -lidmap SRCS = nfsmapid.c nfsmapid_server.c DSRC = nfsmapid_dt.d DOBJ = $(DSRC:%.d=%.o) diff --git a/usr/src/cmd/fs.d/nfs/nfsmapid/nfsmapid_server.c b/usr/src/cmd/fs.d/nfs/nfsmapid/nfsmapid_server.c index 4edd849773..0bc197d7b0 100644 --- a/usr/src/cmd/fs.d/nfs/nfsmapid/nfsmapid_server.c +++ b/usr/src/cmd/fs.d/nfs/nfsmapid/nfsmapid_server.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -52,18 +52,8 @@ #include <nfs/nfsid_map.h> #include <nfs/mapid.h> #include <sys/sdt.h> - -/* - * We cannot use the backend nscd as it may make syscalls that may - * cause further nfsmapid upcalls introducing deadlock. - * Use the internal uncached versions of get*_r. - */ -extern struct group *_uncached_getgrgid_r(gid_t, struct group *, char *, int); -extern struct group *_uncached_getgrnam_r(const char *, struct group *, - char *, int); -extern struct passwd *_uncached_getpwuid_r(uid_t, struct passwd *, char *, int); -extern struct passwd *_uncached_getpwnam_r(const char *, struct passwd *, - char *, int); +#include <sys/idmap.h> +#include <idmap.h> #define UID_MAX_STR_LEN 11 /* Digits in UID_MAX + 1 */ #define DIAG_FILE "/var/run/nfs4_domain" @@ -100,9 +90,12 @@ nfsmapid_str_uid(struct mapid_arg *argp, size_t arg_size) { struct mapid_res result; struct passwd pwd; + struct passwd *pwd_ptr; + int pwd_rc; char *pwd_buf; char *user; char *domain; + idmap_stat rc; if (argp->u_arg.len <= 0 || arg_size < MAPID_ARG_LEN(argp->u_arg.len)) { result.status = NFSMAPID_INVALID; @@ -111,10 +104,10 @@ nfsmapid_str_uid(struct mapid_arg *argp, size_t arg_size) } if (!extract_domain(argp->str, &user, &domain)) { - long id; + unsigned long id; /* - * Invalid "user@dns_domain" string. Still, the user + * Invalid "user@domain" string. Still, the user * part might be an encoded uid, so do a final check. * Remember, domain part of string was not set since * not a valid string. @@ -125,14 +118,13 @@ nfsmapid_str_uid(struct mapid_arg *argp, size_t arg_size) goto done; } - /* - * Since atoi() does not return proper errors for - * invalid translation, use strtol() instead. - */ errno = 0; - id = strtol(user, (char **)NULL, 10); + id = strtoul(user, (char **)NULL, 10); - if (errno || id < 0 || id > UID_MAX) { + /* + * We don't accept ephemeral ids from the wire. + */ + if (errno || id > UID_MAX) { result.status = NFSMAPID_UNMAPPABLE; result.u_res.uid = UID_NOBODY; goto done; @@ -145,19 +137,29 @@ nfsmapid_str_uid(struct mapid_arg *argp, size_t arg_size) /* * String properly constructed. Now we check for domain and - * group validity. Note that we only look at the domain iff - * the local domain is configured. + * group validity. */ if (!cur_domain_null() && !valid_domain(domain)) { - result.status = NFSMAPID_BADDOMAIN; - result.u_res.uid = UID_NOBODY; + /* + * If the domain part of the string does not + * match the NFS domain, try to map it using + * idmap service. + */ + rc = idmap_getuidbywinname(user, domain, &result.u_res.uid); + if (rc != IDMAP_SUCCESS) { + result.status = NFSMAPID_BADDOMAIN; + result.u_res.uid = UID_NOBODY; + goto done; + } + result.status = NFSMAPID_OK; goto done; } if ((pwd_buf = malloc(pwd_buflen)) == NULL || - _uncached_getpwnam_r(user, &pwd, pwd_buf, pwd_buflen) == NULL) { + (pwd_rc = getpwnam_r(user, &pwd, pwd_buf, pwd_buflen, &pwd_ptr)) + != 0 || pwd_ptr == NULL) { - if (pwd_buf == NULL) + if (pwd_buf == NULL || pwd_rc != 0) result.status = NFSMAPID_INTERNAL; else { /* @@ -187,8 +189,9 @@ nfsmapid_uid_str(struct mapid_arg *argp, size_t arg_size) struct mapid_res result; struct mapid_res *resp; struct passwd pwd; - int pwd_len; - char *pwd_buf; + struct passwd *pwd_ptr; + char *pwd_buf = NULL; + char *idmap_buf = NULL; uid_t uid = argp->u_arg.uid; size_t uid_str_len; char *pw_str; @@ -197,10 +200,11 @@ nfsmapid_uid_str(struct mapid_arg *argp, size_t arg_size) size_t at_str_len; char dom_str[DNAMEMAX]; size_t dom_str_len; + idmap_stat rc; - if (uid < 0 || uid > UID_MAX) { + if (uid == (uid_t)-1) { /* - * Negative uid or greater than UID_MAX + * Sentinel uid is not a valid id */ resp = &result; resp->status = NFSMAPID_BADID; @@ -220,6 +224,35 @@ nfsmapid_uid_str(struct mapid_arg *argp, size_t arg_size) } /* + * If uid is ephemeral then resolve it using idmap service + */ + if (uid > UID_MAX) { + rc = idmap_getwinnamebyuid(uid, &idmap_buf, NULL); + if (rc != IDMAP_SUCCESS) { + /* + * We don't put stringified ephemeral uids on + * the wire. + */ + resp = &result; + resp->status = NFSMAPID_UNMAPPABLE; + resp->u_res.len = 0; + goto done; + } + + /* + * idmap_buf is already in the desired form i.e. name@domain + */ + pw_str = idmap_buf; + pw_str_len = strlen(pw_str); + at_str_len = dom_str_len = 0; + at_str = ""; + dom_str[0] = '\0'; + goto gen_result; + } + + /* + * Handling non-ephemeral uids + * * We want to encode the uid into a literal string... : * * - upon failure to allocate space from the heap @@ -227,7 +260,8 @@ nfsmapid_uid_str(struct mapid_arg *argp, size_t arg_size) * - if there is no such uid in the passwd DB's */ if ((pwd_buf = malloc(pwd_buflen)) == NULL || dom_str_len == 0 || - _uncached_getpwuid_r(uid, &pwd, pwd_buf, pwd_buflen) == NULL) { + getpwuid_r(uid, &pwd, pwd_buf, pwd_buflen, &pwd_ptr) != 0 || + pwd_ptr == NULL) { /* * If we could not allocate from the heap, try @@ -244,27 +278,34 @@ nfsmapid_uid_str(struct mapid_arg *argp, size_t arg_size) /* * Constructing literal string without '@' so that * we'll know that it's not a user, but rather a - * uid encoded string. Can't overflow because we - * already checked UID_MAX. + * uid encoded string. */ pw_str = pwd_buf; - (void) sprintf(pw_str, "%d", (int)uid); + (void) sprintf(pw_str, "%u", uid); pw_str_len = strlen(pw_str); at_str_len = dom_str_len = 0; at_str = ""; dom_str[0] = '\0'; } else { /* - * Otherwise, we construct the "user@domain" string + * Otherwise, we construct the "user@domain" string if + * it's not already in that form. */ pw_str = pwd.pw_name; pw_str_len = strlen(pw_str); - at_str = "@"; - at_str_len = 1; + if (strchr(pw_str, '@') == NULL) { + at_str = "@"; + at_str_len = 1; + } else { + at_str_len = dom_str_len = 0; + at_str = ""; + dom_str[0] = '\0'; + } } +gen_result: uid_str_len = pw_str_len + at_str_len + dom_str_len; - if ((resp = alloca(MAPID_RES_LEN(UID_MAX_STR_LEN))) == NULL) { + if ((resp = alloca(MAPID_RES_LEN(uid_str_len))) == NULL) { resp = &result; resp->status = NFSMAPID_INTERNAL; resp->u_res.len = 0; @@ -273,7 +314,10 @@ nfsmapid_uid_str(struct mapid_arg *argp, size_t arg_size) /* LINTED format argument to sprintf */ (void) sprintf(resp->str, "%s%s%s", pw_str, at_str, dom_str); resp->u_res.len = uid_str_len; - free(pwd_buf); + if (pwd_buf) + free(pwd_buf); + if (idmap_buf) + idmap_free(idmap_buf); resp->status = NFSMAPID_OK; done: @@ -286,7 +330,7 @@ done: resp->status = NFSMAPID_INTERNAL; resp->u_res.len = 0; (void) door_return((char *)&result, sizeof (struct mapid_res), - NULL, 0); + NULL, 0); } } @@ -295,22 +339,25 @@ nfsmapid_str_gid(struct mapid_arg *argp, size_t arg_size) { struct mapid_res result; struct group grp; + struct group *grp_ptr; + int grp_rc; char *grp_buf; char *group; char *domain; + idmap_stat rc; if (argp->u_arg.len <= 0 || - arg_size < MAPID_ARG_LEN(argp->u_arg.len)) { + arg_size < MAPID_ARG_LEN(argp->u_arg.len)) { result.status = NFSMAPID_INVALID; result.u_res.gid = GID_NOBODY; goto done; } if (!extract_domain(argp->str, &group, &domain)) { - long id; + unsigned long id; /* - * Invalid "group@dns_domain" string. Still, the + * Invalid "group@domain" string. Still, the * group part might be an encoded gid, so do a * final check. Remember, domain part of string * was not set since not a valid string. @@ -321,14 +368,13 @@ nfsmapid_str_gid(struct mapid_arg *argp, size_t arg_size) goto done; } - /* - * Since atoi() does not return proper errors for - * invalid translation, use strtol() instead. - */ errno = 0; - id = strtol(group, (char **)NULL, 10); + id = strtoul(group, (char **)NULL, 10); - if (errno || id < 0 || id > UID_MAX) { + /* + * We don't accept ephemeral ids from the wire. + */ + if (errno || id > UID_MAX) { result.status = NFSMAPID_UNMAPPABLE; result.u_res.gid = GID_NOBODY; goto done; @@ -341,19 +387,29 @@ nfsmapid_str_gid(struct mapid_arg *argp, size_t arg_size) /* * String properly constructed. Now we check for domain and - * group validity. Note that we only look at the domain iff - * the local domain is configured. + * group validity. */ if (!cur_domain_null() && !valid_domain(domain)) { - result.status = NFSMAPID_BADDOMAIN; - result.u_res.gid = GID_NOBODY; + /* + * If the domain part of the string does not + * match the NFS domain, try to map it using + * idmap service. + */ + rc = idmap_getgidbywinname(group, domain, &result.u_res.gid); + if (rc != IDMAP_SUCCESS) { + result.status = NFSMAPID_BADDOMAIN; + result.u_res.gid = GID_NOBODY; + goto done; + } + result.status = NFSMAPID_OK; goto done; } if ((grp_buf = malloc(grp_buflen)) == NULL || - _uncached_getgrnam_r(group, &grp, grp_buf, grp_buflen) == NULL) { + (grp_rc = getgrnam_r(group, &grp, grp_buf, grp_buflen, &grp_ptr)) + != 0 || grp_ptr == NULL) { - if (grp_buf == NULL) + if (grp_buf == NULL || grp_rc != 0) result.status = NFSMAPID_INTERNAL; else { /* @@ -383,7 +439,10 @@ nfsmapid_gid_str(struct mapid_arg *argp, size_t arg_size) struct mapid_res result; struct mapid_res *resp; struct group grp; - char *grp_buf; + struct group *grp_ptr; + char *grp_buf = NULL; + char *idmap_buf = NULL; + idmap_stat rc; gid_t gid = argp->u_arg.gid; size_t gid_str_len; char *gr_str; @@ -393,9 +452,9 @@ nfsmapid_gid_str(struct mapid_arg *argp, size_t arg_size) char dom_str[DNAMEMAX]; size_t dom_str_len; - if (gid < 0 || gid > UID_MAX) { + if (gid == (gid_t)-1) { /* - * Negative gid or greater than UID_MAX + * Sentinel gid is not a valid id */ resp = &result; resp->status = NFSMAPID_BADID; @@ -417,6 +476,35 @@ nfsmapid_gid_str(struct mapid_arg *argp, size_t arg_size) } /* + * If gid is ephemeral then resolve it using idmap service + */ + if (gid > UID_MAX) { + rc = idmap_getwinnamebygid(gid, &idmap_buf, NULL); + if (rc != IDMAP_SUCCESS) { + /* + * We don't put stringified ephemeral gids on + * the wire. + */ + resp = &result; + resp->status = NFSMAPID_UNMAPPABLE; + resp->u_res.len = 0; + goto done; + } + + /* + * idmap_buf is already in the desired form i.e. name@domain + */ + gr_str = idmap_buf; + gr_str_len = strlen(gr_str); + at_str_len = dom_str_len = 0; + at_str = ""; + dom_str[0] = '\0'; + goto gen_result; + } + + /* + * Handling non-ephemeral gids + * * We want to encode the gid into a literal string... : * * - upon failure to allocate space from the heap @@ -424,7 +512,8 @@ nfsmapid_gid_str(struct mapid_arg *argp, size_t arg_size) * - if there is no such gid in the group DB's */ if ((grp_buf = malloc(grp_buflen)) == NULL || dom_str_len == 0 || - _uncached_getgrgid_r(gid, &grp, grp_buf, grp_buflen) == NULL) { + getgrgid_r(gid, &grp, grp_buf, grp_buflen, &grp_ptr) != 0 || + grp_ptr == NULL) { /* * If we could not allocate from the heap, try @@ -441,27 +530,34 @@ nfsmapid_gid_str(struct mapid_arg *argp, size_t arg_size) /* * Constructing literal string without '@' so that * we'll know that it's not a group, but rather a - * gid encoded string. Can't overflow because we - * already checked UID_MAX. + * gid encoded string. */ gr_str = grp_buf; - (void) sprintf(gr_str, "%d", (int)gid); + (void) sprintf(gr_str, "%u", gid); gr_str_len = strlen(gr_str); at_str_len = dom_str_len = 0; at_str = ""; dom_str[0] = '\0'; } else { /* - * Otherwise, we construct the "group@domain" string + * Otherwise, we construct the "group@domain" string if + * it's not already in that form. */ gr_str = grp.gr_name; gr_str_len = strlen(gr_str); - at_str = "@"; - at_str_len = 1; + if (strchr(gr_str, '@') == NULL) { + at_str = "@"; + at_str_len = 1; + } else { + at_str_len = dom_str_len = 0; + at_str = ""; + dom_str[0] = '\0'; + } } +gen_result: gid_str_len = gr_str_len + at_str_len + dom_str_len; - if ((resp = alloca(MAPID_RES_LEN(UID_MAX_STR_LEN))) == NULL) { + if ((resp = alloca(MAPID_RES_LEN(gid_str_len))) == NULL) { resp = &result; resp->status = NFSMAPID_INTERNAL; resp->u_res.len = 0; @@ -470,7 +566,10 @@ nfsmapid_gid_str(struct mapid_arg *argp, size_t arg_size) /* LINTED format argument to sprintf */ (void) sprintf(resp->str, "%s%s%s", gr_str, at_str, dom_str); resp->u_res.len = gid_str_len; - free(grp_buf); + if (grp_buf) + free(grp_buf); + if (idmap_buf) + idmap_free(idmap_buf); resp->status = NFSMAPID_OK; done: @@ -483,7 +582,7 @@ done: resp->status = NFSMAPID_INTERNAL; resp->u_res.len = 0; (void) door_return((char *)&result, sizeof (struct mapid_res), - NULL, 0); + NULL, 0); } } @@ -502,7 +601,7 @@ nfsmapid_func(void *cookie, char *argp, size_t arg_size, mapres.status = NFSMAPID_INVALID; mapres.u_res.len = 0; (void) door_return((char *)&mapres, sizeof (struct mapid_res), - NULL, 0); + NULL, 0); return; } @@ -566,7 +665,7 @@ valid_domain(const char *dom) if (!mapid_stdchk_domain(dom)) { syslog(LOG_ERR, gettext("%s: Invalid inbound domain name %s."), - whoami, dom); + whoami, dom); return (0); } @@ -655,7 +754,7 @@ open_diag_file() return; syslog(LOG_ERR, "Failed to create %s. Enable syslog " - "daemon.debug for more info", DIAG_FILE); + "daemon.debug for more info", DIAG_FILE); msg_done = 1; } @@ -678,7 +777,7 @@ update_diag_file(char *new) n = write(n4_fd, buf, len); if (n < 0 || n < len) syslog(LOG_DEBUG, "Could not write %s to diag file", new); - fsync(n4_fd); + (void) fsync(n4_fd); syslog(LOG_DEBUG, "nfsmapid domain = %s", new); } diff --git a/usr/src/cmd/fs.d/nfs/nfsmapid/nfsmapid_test.c b/usr/src/cmd/fs.d/nfs/nfsmapid/nfsmapid_test.c index a915500df0..2406b7cb0b 100644 --- a/usr/src/cmd/fs.d/nfs/nfsmapid/nfsmapid_test.c +++ b/usr/src/cmd/fs.d/nfs/nfsmapid/nfsmapid_test.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -60,12 +59,12 @@ static void usage() { fprintf(stderr, gettext( - "\nUsage:\tstr2uid string\n" - "\tstr2gid string\n" - "\tuid2str uid\n" - "\tgid2str gid\n" - "\techo string\n" - "\texit|quit\n")); + "\nUsage:\tstr2uid string\n" + "\tstr2gid string\n" + "\tuid2str uid\n" + "\tgid2str gid\n" + "\techo string\n" + "\texit|quit\n")); } static int read_line(char *buf, int size) @@ -205,7 +204,7 @@ do_test(char *input_buf) str.utf8string_val = argv[1]; str.utf8string_len = strlen(argv[1]); stat = nfs_idmap_str_uid(&str, &uid); - printf(gettext("%d stat=%s \n"), uid, mapstat(stat)); + printf(gettext("%u stat=%s \n"), uid, mapstat(stat)); } else if (strcmp(cmd, "str2gid") == 0) { if (argc < 2) { @@ -216,7 +215,7 @@ do_test(char *input_buf) str.utf8string_val = argv[1]; str.utf8string_len = strlen(argv[1]); stat = nfs_idmap_str_gid(&str, &gid); - printf(gettext("%d stat=%s \n"), gid, mapstat(stat)); + printf(gettext("%u stat=%s \n"), gid, mapstat(stat)); } else if (strcmp(cmd, "uid2str") == 0) { if (argc < 2) { @@ -229,7 +228,7 @@ do_test(char *input_buf) str.utf8string_val = str_buf; stat = nfs_idmap_uid_str(uid, &str); printf(gettext("%s stat=%s\n"), str.utf8string_val, - mapstat(stat)); + mapstat(stat)); } else if (strcmp(cmd, "gid2str") == 0) { if (argc < 2) { @@ -242,14 +241,14 @@ do_test(char *input_buf) str.utf8string_val = str_buf; stat = nfs_idmap_gid_str(gid, &str); printf(gettext("%s stat=%s\n"), str.utf8string_val, - mapstat(stat)); + mapstat(stat)); } else if (strcmp(cmd, "echo") == 0) { for (i = 1; i < argc; i++) printf("%s ", argv[i]); printf("\n"); } else if (strcmp(cmd, "exit") == 0 || - strcmp(cmd, "quit") == 0) { + strcmp(cmd, "quit") == 0) { printf(gettext("\n")); free(argv_array); return (1); @@ -329,7 +328,7 @@ nfs_idmap_str_uid(utf8string *u8s, uid_t *uid) static int msg_done = 0; if (!u8s || !u8s->utf8string_val || !u8s->utf8string_len || - (u8s->utf8string_val[0] == '\0')) { + (u8s->utf8string_val[0] == '\0')) { error = EINVAL; goto s2u_done; } @@ -345,7 +344,7 @@ nfs_idmap_str_uid(utf8string *u8s, uid_t *uid) if ((mapargp = malloc(MAPID_ARG_LEN(u8s->utf8string_len))) == NULL) { (void) fprintf(stderr, "Unable to malloc %d bytes\n", - MAPID_ARG_LEN(u8s->utf8string_len)); + MAPID_ARG_LEN(u8s->utf8string_len)); error = ENOMEM; goto s2u_done; } @@ -367,7 +366,7 @@ nfs_idmap_str_uid(utf8string *u8s, uid_t *uid) if ((doorfd = nfs_idmap_doorget()) == -1) { if (!msg_done) { fprintf(stderr, "nfs_idmap_str_uid: Can't communicate" - " with mapping daemon nfsmapid\n"); + " with mapping daemon nfsmapid\n"); msg_done = 1; } error = ECOMM; @@ -453,7 +452,7 @@ nfs_idmap_uid_str(uid_t uid, /* uid to map */ if ((doorfd = nfs_idmap_doorget()) == -1) { if (!msg_done) { fprintf(stderr, "nfs_idmap_uid_str: Can't " - "communicate with mapping daemon nfsmapid\n"); + "communicate with mapping daemon nfsmapid\n"); msg_done = 1; } error = ECOMM; @@ -474,7 +473,7 @@ nfs_idmap_uid_str(uid_t uid, /* uid to map */ if (resp->u_res.len != strlen(resp->str)) { (void) fprintf(stderr, "Incorrect length %d expected %d\n", - resp->u_res.len, strlen(resp->str)); + resp->u_res.len, strlen(resp->str)); error = NFSMAPID_INVALID; goto u2s_done; } @@ -503,7 +502,7 @@ nfs_idmap_str_gid(utf8string *u8s, gid_t *gid) static int msg_done = 0; if (!u8s || !u8s->utf8string_val || !u8s->utf8string_len || - (u8s->utf8string_val[0] == '\0')) { + (u8s->utf8string_val[0] == '\0')) { error = EINVAL; goto s2g_done; } @@ -519,7 +518,7 @@ nfs_idmap_str_gid(utf8string *u8s, gid_t *gid) if ((mapargp = malloc(MAPID_ARG_LEN(u8s->utf8string_len))) == NULL) { (void) fprintf(stderr, "Unable to malloc %d bytes\n", - MAPID_ARG_LEN(u8s->utf8string_len)); + MAPID_ARG_LEN(u8s->utf8string_len)); error = ENOMEM; goto s2g_done; } @@ -541,7 +540,7 @@ nfs_idmap_str_gid(utf8string *u8s, gid_t *gid) if ((doorfd = nfs_idmap_doorget()) == -1) { if (!msg_done) { fprintf(stderr, "nfs_idmap_str_uid: Can't communicate" - " with mapping daemon nfsmapid\n"); + " with mapping daemon nfsmapid\n"); msg_done = 1; } error = ECOMM; @@ -628,7 +627,7 @@ nfs_idmap_gid_str(gid_t gid, /* gid to map */ if ((doorfd = nfs_idmap_doorget()) == -1) { if (!msg_done) { fprintf(stderr, "nfs_idmap_uid_str: Can't " - "communicate with mapping daemon nfsmapid\n"); + "communicate with mapping daemon nfsmapid\n"); msg_done = 1; } error = ECOMM; @@ -649,7 +648,7 @@ nfs_idmap_gid_str(gid_t gid, /* gid to map */ if (resp->u_res.len != strlen(resp->str)) { (void) fprintf(stderr, "Incorrect length %d expected %d\n", - resp->u_res.len, strlen(resp->str)); + resp->u_res.len, strlen(resp->str)); error = NFSMAPID_INVALID; goto g2s_done; } diff --git a/usr/src/cmd/fs.d/nfs/svc/mapid.xml b/usr/src/cmd/fs.d/nfs/svc/mapid.xml index a3b151a2c5..f9174b7973 100644 --- a/usr/src/cmd/fs.d/nfs/svc/mapid.xml +++ b/usr/src/cmd/fs.d/nfs/svc/mapid.xml @@ -1,15 +1,14 @@ <?xml version="1.0"?> <!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1"> <!-- - Copyright 2005 Sun Microsystems, Inc. All rights reserved. + Copyright 2007 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms. CDDL HEADER START The contents of this file are subject to the terms of the - Common Development and Distribution License, Version 1.0 only - (the "License"). You may not use this file except in compliance - with the License. + Common Development and Distribution License (the "License"). + You may not use this file except in compliance with the License. You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. @@ -68,6 +67,13 @@ <service_fmri value='svc:/milestone/name-services' /> </dependency> + <dependency name='idmap' + grouping='optional_all' + restart_on='none' + type='service'> + <service_fmri value='svc:/system/idmap' /> + </dependency> + <dependency name='filesystem-minimal' grouping='require_all' restart_on='error' diff --git a/usr/src/cmd/idmap/idmapd/dbutils.c b/usr/src/cmd/idmap/idmapd/dbutils.c index 88db3c7b86..82c6df10a8 100644 --- a/usr/src/cmd/idmap/idmapd/dbutils.c +++ b/usr/src/cmd/idmap/idmapd/dbutils.c @@ -2786,6 +2786,7 @@ get_w2u_mapping(sqlite *cache, sqlite *db, idmap_mapping *request, idmap_id_res idres; lookup_state_t state; idmap_utf8str *str; + char *cp; int is_user; idmap_retcode retcode; const char *winname, *windomain; @@ -2820,18 +2821,28 @@ get_w2u_mapping(sqlite *cache, sqlite *db, idmap_mapping *request, if (winname != NULL && windomain == NULL) { str = &mapping->id1domain; - RDLOCK_CONFIG(); - if (_idmapdstate.cfg->pgcfg.mapping_domain != NULL) { + + if ((cp = strchr(winname, '@')) != NULL) { + /* + * if winname is qualified with a domain, use it. + */ + *cp = '\0'; + retcode = idmap_str2utf8(&str, cp + 1, 0); + } else if (_idmapdstate.cfg->pgcfg.mapping_domain != NULL) { + /* + * otherwise use the mapping domain + */ + RDLOCK_CONFIG(); retcode = idmap_str2utf8(&str, _idmapdstate.cfg->pgcfg.mapping_domain, 0); - if (retcode != IDMAP_SUCCESS) { - UNLOCK_CONFIG(); - idmapdlog(LOG_ERR, "Out of memory"); - retcode = IDMAP_ERR_MEMORY; - goto out; - } + UNLOCK_CONFIG(); + } else + retcode = IDMAP_SUCCESS; + + if (retcode != IDMAP_SUCCESS) { + idmapdlog(LOG_ERR, "Out of memory"); + goto out; } - UNLOCK_CONFIG(); windomain = mapping->id1domain.idmap_utf8str_val; } diff --git a/usr/src/lib/libidmap/common/idmap.h b/usr/src/lib/libidmap/common/idmap.h index d9d58cd794..7c1507fe49 100644 --- a/usr/src/lib/libidmap/common/idmap.h +++ b/usr/src/lib/libidmap/common/idmap.h @@ -103,6 +103,23 @@ extern idmap_stat idmap_get_mappings(idmap_get_handle_t *); /* Destroy the handle */ extern void idmap_get_destroy(idmap_get_handle_t *); + +/* + * API to get Windows name by UID/GID and vice-versa + */ +/* Given UID, get Windows name */ +extern idmap_stat idmap_getwinnamebyuid(uid_t, char **, char **); + +/* Given GID, get Windows name */ +extern idmap_stat idmap_getwinnamebygid(gid_t, char **, char **); + +/* Given Windows name, get UID */ +extern idmap_stat idmap_getuidbywinname(const char *, const char *, uid_t *); + +/* Given Windows name, get GID */ +extern idmap_stat idmap_getgidbywinname(const char *, const char *, gid_t *); + + #ifdef __cplusplus } #endif diff --git a/usr/src/lib/libidmap/common/idmap_api.c b/usr/src/lib/libidmap/common/idmap_api.c index 2c6c7edd03..3a90685268 100644 --- a/usr/src/lib/libidmap/common/idmap_api.c +++ b/usr/src/lib/libidmap/common/idmap_api.c @@ -1639,3 +1639,131 @@ idmap_stat4prot(idmap_stat status) { } return (status); } + + +/* + * Get uid given Windows name + */ +idmap_stat +idmap_getuidbywinname(const char *name, const char *domain, uid_t *uid) { + idmap_handle_t *ih; + idmap_retcode rc; + int is_user; + + if (uid == NULL) + return (IDMAP_ERR_ARG); + + /* Get mapping */ + if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS) + return (rc); + rc = idmap_get_w2u_mapping(ih, NULL, NULL, name, domain, 0, + &is_user, uid, NULL, NULL); + (void) idmap_fini(ih); + + /* + * XXX Until we have diagonal mapping support, check if + * the given name belongs to a user + */ + if (rc == IDMAP_SUCCESS && !is_user) + return (IDMAP_ERR_NOTUSER); + return (rc); +} + + +/* + * Get gid given Windows name + */ +idmap_stat +idmap_getgidbywinname(const char *name, const char *domain, gid_t *gid) { + idmap_handle_t *ih; + idmap_retcode rc; + int is_user; + + if (gid == NULL) + return (IDMAP_ERR_ARG); + + /* Get mapping */ + if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS) + return (rc); + rc = idmap_get_w2u_mapping(ih, NULL, NULL, name, domain, 0, + &is_user, gid, NULL, NULL); + (void) idmap_fini(ih); + + /* + * XXX Until we have diagonal mapping support, check if + * the given name belongs to a group + */ + if (rc == IDMAP_SUCCESS && is_user) + return (IDMAP_ERR_NOTGROUP); + return (rc); +} + + +/* + * Get winname given pid + */ +static idmap_retcode +idmap_getwinnamebypid(uid_t pid, int is_user, char **name, char **domain) { + idmap_handle_t *ih; + idmap_retcode rc; + int len; + char *winname, *windomain; + + if (name == NULL) + return (IDMAP_ERR_ARG); + + /* Get mapping */ + if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS) + return (rc); + rc = idmap_get_u2w_mapping(ih, &pid, NULL, 0, is_user, NULL, + NULL, &winname, &windomain, NULL); + (void) idmap_fini(ih); + + /* Return on error */ + if (rc != IDMAP_SUCCESS) + return (rc); + + /* + * The given PID may have been mapped to a locally + * generated SID in which case there isn't any + * Windows name + */ + if (winname == NULL || windomain == NULL) { + idmap_free(winname); + idmap_free(windomain); + return (IDMAP_ERR_NORESULT); + } + + if (domain != NULL) { + *name = winname; + *domain = windomain; + } else { + len = strlen(winname) + strlen(windomain) + 2; + if ((*name = malloc(len)) != NULL) + (void) snprintf(*name, len, "%s@%s", winname, + windomain); + else + rc = IDMAP_ERR_MEMORY; + idmap_free(winname); + idmap_free(windomain); + } + return (rc); +} + + +/* + * Get winname given uid + */ +idmap_stat +idmap_getwinnamebyuid(uid_t uid, char **name, char **domain) { + return (idmap_getwinnamebypid(uid, 1, name, domain)); +} + + +/* + * Get winname given gid + */ +idmap_stat +idmap_getwinnamebygid(gid_t gid, char **name, char **domain) { + return (idmap_getwinnamebypid(gid, 0, name, domain)); +} diff --git a/usr/src/lib/libidmap/common/mapfile-vers b/usr/src/lib/libidmap/common/mapfile-vers index 00c7647e10..1fe09cf777 100644 --- a/usr/src/lib/libidmap/common/mapfile-vers +++ b/usr/src/lib/libidmap/common/mapfile-vers @@ -68,6 +68,10 @@ SUNWprivate { idmap_udt_commit; idmap_udt_create; idmap_udt_flush_namerules; + idmap_getwinnamebyuid; + idmap_getwinnamebygid; + idmap_getuidbywinname; + idmap_getgidbywinname; local: *; }; |