summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr/src/cmd/fs.d/nfs/nfsmapid/Makefile2
-rw-r--r--usr/src/cmd/fs.d/nfs/nfsmapid/nfsmapid_server.c245
-rw-r--r--usr/src/cmd/fs.d/nfs/nfsmapid/nfsmapid_test.c49
-rw-r--r--usr/src/cmd/fs.d/nfs/svc/mapid.xml14
-rw-r--r--usr/src/cmd/idmap/idmapd/dbutils.c29
-rw-r--r--usr/src/lib/libidmap/common/idmap.h17
-rw-r--r--usr/src/lib/libidmap/common/idmap_api.c128
-rw-r--r--usr/src/lib/libidmap/common/mapfile-vers4
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:
*;
};