summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/nsswitch/winbindd_group.c5
-rw-r--r--source3/nsswitch/winbindd_idmap.c202
-rw-r--r--source3/nsswitch/winbindd_proto.h15
-rw-r--r--source3/nsswitch/winbindd_sid.c66
-rw-r--r--source3/nsswitch/winbindd_util.c2
-rw-r--r--source3/smbd/uid.c15
6 files changed, 186 insertions, 119 deletions
diff --git a/source3/nsswitch/winbindd_group.c b/source3/nsswitch/winbindd_group.c
index 1818d992b7..c62ce54b59 100644
--- a/source3/nsswitch/winbindd_group.c
+++ b/source3/nsswitch/winbindd_group.c
@@ -228,10 +228,9 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state)
}
/* Fill in group structure */
+ sid_peek_rid(&group_sid, &group_rid);
- sid_split_rid(&group_sid, &group_rid);
-
- if (!winbindd_idmap_get_gid_from_rid(domain->name, group_rid, &gid)) {
+ if (!winbindd_idmap_get_gid_from_sid(&group_sid, &gid)) {
DEBUG(1, ("error converting unix gid to sid\n"));
return WINBINDD_ERROR;
}
diff --git a/source3/nsswitch/winbindd_idmap.c b/source3/nsswitch/winbindd_idmap.c
index 3a8269f853..977148ad6a 100644
--- a/source3/nsswitch/winbindd_idmap.c
+++ b/source3/nsswitch/winbindd_idmap.c
@@ -27,6 +27,9 @@
#define HWM_GROUP "GROUP HWM"
#define HWM_USER "USER HWM"
+/* idmap version determines auto-conversion */
+#define IDMAP_VERSION 2
+
/* Globals */
static TDB_CONTEXT *idmap_tdb;
@@ -66,17 +69,14 @@ static BOOL allocate_id(uid_t *id, BOOL isgroup)
}
/* Get an id from a rid */
-
-static BOOL get_id_from_rid(char *domain_name, uint32 rid, uid_t *id,
- BOOL isgroup)
+static BOOL get_id_from_sid(DOM_SID *sid, uid_t *id, BOOL isgroup)
{
TDB_DATA data, key;
fstring keystr;
BOOL result = False;
- /* Check if rid is present in database */
-
- slprintf(keystr, sizeof(keystr), "%s/%d", domain_name, rid);
+ /* Check if sid is present in database */
+ sid_to_string(keystr, sid);
key.dptr = keystr;
key.dsize = strlen(keystr) + 1;
@@ -88,34 +88,29 @@ static BOOL get_id_from_rid(char *domain_name, uint32 rid, uid_t *id,
int the_id;
/* Parse and return existing uid */
-
fstrcpy(scanstr, isgroup ? "GID" : "UID");
fstrcat(scanstr, " %d");
if (sscanf(data.dptr, scanstr, &the_id) == 1) {
-
/* Store uid */
-
if (id) {
- *id = the_id;
+ *id = the_id;
}
result = True;
}
SAFE_FREE(data.dptr);
-
} else {
- /* Allocate a new id for this rid */
+ /* Allocate a new id for this sid */
if (id && allocate_id(id, isgroup)) {
fstring keystr2;
/* Store new id */
- slprintf(keystr2, sizeof(keystr2), "%s %d", isgroup ? "GID" :
- "UID", *id);
+ slprintf(keystr2, sizeof(keystr2), "%s %d", isgroup ? "GID" : "UID", *id);
data.dptr = keystr2;
data.dsize = strlen(keystr2) + 1;
@@ -130,24 +125,52 @@ static BOOL get_id_from_rid(char *domain_name, uint32 rid, uid_t *id,
return result;
}
-/* Get a uid from a user rid */
+/* Get a uid from a user sid */
+BOOL winbindd_idmap_get_uid_from_sid(DOM_SID *sid, uid_t *uid)
+{
+ return get_id_from_sid(sid, uid, False);
+}
-BOOL winbindd_idmap_get_uid_from_rid(char *domain_name, uint32 user_rid,
- uid_t *uid)
+/* Get a gid from a group sid */
+BOOL winbindd_idmap_get_gid_from_sid(DOM_SID *sid, gid_t *gid)
{
- return get_id_from_rid(domain_name, user_rid, uid, False);
+ return get_id_from_sid(sid, gid, True);
}
-/* Get a gid from a group rid */
+/* Get a uid from a user rid */
+BOOL winbindd_idmap_get_uid_from_rid(const char *dom_name, uint32 rid, uid_t *uid)
+{
+ struct winbindd_domain *domain;
+ DOM_SID sid;
+
+ if (!(domain = find_domain_from_name(dom_name))) {
+ return False;
+ }
-BOOL winbindd_idmap_get_gid_from_rid(char *domain_name, uint32 group_rid,
- gid_t *gid)
+ sid_copy(&sid, &domain->sid);
+ sid_append_rid(&sid, rid);
+
+ return get_id_from_sid(&sid, uid, False);
+}
+
+/* Get a gid from a group rid */
+BOOL winbindd_idmap_get_gid_from_rid(const char *dom_name, uint32 rid, gid_t *gid)
{
- return get_id_from_rid(domain_name, group_rid, gid, True);
+ struct winbindd_domain *domain;
+ DOM_SID sid;
+
+ if (!(domain = find_domain_from_name(dom_name))) {
+ return False;
+ }
+
+ sid_copy(&sid, &domain->sid);
+ sid_append_rid(&sid, rid);
+
+ return get_id_from_sid(&sid, gid, True);
}
-BOOL get_rid_from_id(int id, uint32 *rid, struct winbindd_domain **domain,
- BOOL isgroup)
+
+BOOL get_sid_from_id(int id, DOM_SID *sid, BOOL isgroup)
{
TDB_DATA key, data;
fstring keystr;
@@ -161,43 +184,41 @@ BOOL get_rid_from_id(int id, uint32 *rid, struct winbindd_domain **domain,
data = tdb_fetch(idmap_tdb, key);
if (data.dptr) {
- char *p = data.dptr;
- fstring domain_name;
- uint32 the_rid;
-
- if (next_token(&p, domain_name, "/", sizeof(fstring))) {
-
- the_rid = atoi(p);
-
- if (rid) {
- *rid = the_rid;
- }
-
- if (domain) {
- *domain = find_domain_from_name(domain_name);
- if (*domain == NULL) {
- DEBUG(1, ("unknown domain %s for rid %d\n",
- domain_name, the_rid));
- result = False;
- goto done;
- }
- }
-
- result = True;
- }
- done:
- SAFE_FREE(data.dptr);
+ result = string_to_sid(sid, data.dptr);
+ SAFE_FREE(data.dptr);
}
return result;
}
-/* Get a user rid from a uid */
+/* Get a sid from a uid */
+BOOL winbindd_idmap_get_sid_from_uid(uid_t uid, DOM_SID *sid)
+{
+ return get_sid_from_id((int)uid, sid, False);
+}
+/* Get a sid from a gid */
+BOOL winbindd_idmap_get_sid_from_gid(gid_t gid, DOM_SID *sid)
+{
+ return get_sid_from_id((int)gid, sid, True);
+}
+
+/* Get a user rid from a uid */
BOOL winbindd_idmap_get_rid_from_uid(uid_t uid, uint32 *user_rid,
struct winbindd_domain **domain)
{
- return get_rid_from_id((int)uid, user_rid, domain, False);
+ DOM_SID sid;
+
+ if (!get_sid_from_id((int)uid, &sid, False)) {
+ return False;
+ }
+
+ *domain = find_domain_from_sid(&sid);
+ if (! *domain) return False;
+
+ sid_split_rid(&sid, user_rid);
+
+ return True;
}
/* Get a group rid from a gid */
@@ -205,9 +226,79 @@ BOOL winbindd_idmap_get_rid_from_uid(uid_t uid, uint32 *user_rid,
BOOL winbindd_idmap_get_rid_from_gid(gid_t gid, uint32 *group_rid,
struct winbindd_domain **domain)
{
- return get_rid_from_id((int)gid, group_rid, domain, True);
+ DOM_SID sid;
+
+ if (!get_sid_from_id((int)gid, &sid, True)) {
+ return False;
+ }
+
+ *domain = find_domain_from_sid(&sid);
+ if (! *domain) return False;
+
+ sid_split_rid(&sid, group_rid);
+
+ return True;
}
+/* convert one record to the new format */
+static int convert_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA data, void *ignored)
+{
+ struct winbindd_domain *domain;
+ char *p, *dom_name;
+ DOM_SID sid;
+ uint32 rid;
+ fstring keystr;
+ TDB_DATA key2;
+
+ p = strchr(key.dptr, '/');
+ if (!p) return 0;
+
+ *p++ = 0;
+ dom_name = key.dptr;
+
+ domain = find_domain_from_name(dom_name);
+ if (!domain) {
+ /* what do we do about this?? */
+ return 0;
+ }
+
+ rid = atoi(p);
+
+ sid_copy(&sid, &domain->sid);
+ sid_append_rid(&sid, rid);
+
+ sid_to_string(keystr, &sid);
+ key2.dptr = keystr;
+ key2.dsize = strlen(keystr) + 1;
+
+ if (tdb_store(idmap_tdb, key2, data, TDB_INSERT) != 0) {
+ /* not good! */
+ return 0;
+ }
+
+ tdb_delete(idmap_tdb, key);
+
+ return 0;
+}
+
+/* convert the idmap database from an older version */
+static BOOL idmap_convert(void)
+{
+ if (tdb_fetch_int(idmap_tdb, "IDMAP_VERSION") == IDMAP_VERSION) {
+ return True;
+ }
+
+ /* the old format stored as DOMAIN/rid - now we store the SID direct */
+ tdb_traverse(idmap_tdb, convert_fn, NULL);
+
+ if (tdb_store_int(idmap_tdb, "IDMAP_VERSION", IDMAP_VERSION) == -1) {
+ return False;
+ }
+
+ return True;
+}
+
+
/* Initialise idmap database */
BOOL winbindd_idmap_init(void)
@@ -220,6 +311,11 @@ BOOL winbindd_idmap_init(void)
return False;
}
+ /* possibly convert from an earlier version */
+ if (!idmap_convert()) {
+ return False;
+ }
+
/* Create high water marks for group and user id */
if (tdb_fetch_int(idmap_tdb, HWM_USER) == -1) {
diff --git a/source3/nsswitch/winbindd_proto.h b/source3/nsswitch/winbindd_proto.h
index 5d1081c719..14edbfdd44 100644
--- a/source3/nsswitch/winbindd_proto.h
+++ b/source3/nsswitch/winbindd_proto.h
@@ -49,12 +49,13 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state);
/* The following definitions come from nsswitch/winbindd_idmap.c */
-BOOL winbindd_idmap_get_uid_from_rid(char *domain_name, uint32 user_rid,
- uid_t *uid);
-BOOL winbindd_idmap_get_gid_from_rid(char *domain_name, uint32 group_rid,
- gid_t *gid);
-BOOL get_rid_from_id(int id, uint32 *rid, struct winbindd_domain **domain,
- BOOL isgroup);
+BOOL winbindd_idmap_get_uid_from_sid(DOM_SID *sid, uid_t *uid);
+BOOL winbindd_idmap_get_gid_from_sid(DOM_SID *sid, gid_t *gid);
+BOOL winbindd_idmap_get_uid_from_rid(const char *dom_name, uint32 rid, uid_t *uid);
+BOOL winbindd_idmap_get_gid_from_rid(const char *dom_name, uint32 rid, gid_t *gid);
+BOOL get_sid_from_id(int id, DOM_SID *sid, BOOL isgroup);
+BOOL winbindd_idmap_get_sid_from_uid(uid_t uid, DOM_SID *sid);
+BOOL winbindd_idmap_get_sid_from_gid(gid_t gid, DOM_SID *sid);
BOOL winbindd_idmap_get_rid_from_uid(uid_t uid, uint32 *user_rid,
struct winbindd_domain **domain);
BOOL winbindd_idmap_get_rid_from_gid(gid_t gid, uint32 *group_rid,
@@ -107,7 +108,7 @@ enum winbindd_result winbindd_list_users(struct winbindd_cli_state *state);
struct winbindd_domain *domain_list(void);
void free_domain_list(void);
BOOL init_domain_list(void);
-struct winbindd_domain *find_domain_from_name(char *domain_name);
+struct winbindd_domain *find_domain_from_name(const char *domain_name);
struct winbindd_domain *find_domain_from_sid(DOM_SID *sid);
BOOL winbindd_lookup_sid_by_name(struct winbindd_domain *domain,
const char *name, DOM_SID *sid,
diff --git a/source3/nsswitch/winbindd_sid.c b/source3/nsswitch/winbindd_sid.c
index 8153b3a3a5..227ce439d5 100644
--- a/source3/nsswitch/winbindd_sid.c
+++ b/source3/nsswitch/winbindd_sid.c
@@ -103,31 +103,19 @@ enum winbindd_result winbindd_lookupname(struct winbindd_cli_state *state)
enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state)
{
DOM_SID sid;
- uint32 user_rid;
- struct winbindd_domain *domain;
DEBUG(3, ("[%5d]: sid to uid %s\n", state->pid,
state->request.data.sid));
/* Split sid into domain sid and user rid */
-
- string_to_sid(&sid, state->request.data.sid);
- sid_split_rid(&sid, &user_rid);
-
- /* Find domain this sid belongs to */
-
- if ((domain = find_domain_from_sid(&sid)) == NULL) {
- fstring sid_str;
-
- sid_to_string(sid_str, &sid);
- DEBUG(1, ("Could not find domain for sid %s\n", sid_str));
+ if (!string_to_sid(&sid, state->request.data.sid)) {
+ DEBUG(1, ("Could not get convert sid %s from string\n",
+ state->request.data.sid));
return WINBINDD_ERROR;
}
/* Find uid for this sid and return it */
-
- if (!winbindd_idmap_get_uid_from_rid(domain->name, user_rid,
- &state->response.data.uid)) {
+ if (!winbindd_idmap_get_uid_from_sid(&sid, &state->response.data.uid)) {
DEBUG(1, ("Could not get uid for sid %s\n",
state->request.data.sid));
return WINBINDD_ERROR;
@@ -142,31 +130,18 @@ enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state)
enum winbindd_result winbindd_sid_to_gid(struct winbindd_cli_state *state)
{
DOM_SID sid;
- uint32 group_rid;
- struct winbindd_domain *domain;
DEBUG(3, ("[%5d]: sid to gid %s\n", state->pid,
state->request.data.sid));
- /* Split sid into domain sid and user rid */
-
- string_to_sid(&sid, state->request.data.sid);
- sid_split_rid(&sid, &group_rid);
-
- /* Find domain this sid belongs to */
-
- if ((domain = find_domain_from_sid(&sid)) == NULL) {
- fstring sid_str;
-
- sid_to_string(sid_str, &sid);
- DEBUG(1, ("Could not find domain for sid %s\n", sid_str));
+ if (!string_to_sid(&sid, state->request.data.sid)) {
+ DEBUG(1, ("Could not cvt string to sid %s\n",
+ state->request.data.sid));
return WINBINDD_ERROR;
}
- /* Find uid for this sid and return it */
-
- if (!winbindd_idmap_get_gid_from_rid(domain->name, group_rid,
- &state->response.data.gid)) {
+ /* Find gid for this sid and return it */
+ if (!winbindd_idmap_get_gid_from_sid(&sid, &state->response.data.gid)) {
DEBUG(1, ("Could not get gid for sid %s\n",
state->request.data.sid));
return WINBINDD_ERROR;
@@ -179,8 +154,6 @@ enum winbindd_result winbindd_sid_to_gid(struct winbindd_cli_state *state)
enum winbindd_result winbindd_uid_to_sid(struct winbindd_cli_state *state)
{
- struct winbindd_domain *domain;
- uint32 user_rid;
DOM_SID sid;
/* Bug out if the uid isn't in the winbind range */
@@ -194,18 +167,12 @@ enum winbindd_result winbindd_uid_to_sid(struct winbindd_cli_state *state)
state->request.data.uid));
/* Lookup rid for this uid */
-
- if (!winbindd_idmap_get_rid_from_uid(state->request.data.uid,
- &user_rid, &domain)) {
+ if (!winbindd_idmap_get_sid_from_uid(state->request.data.uid, &sid)) {
DEBUG(1, ("Could not convert uid %d to rid\n",
state->request.data.uid));
return WINBINDD_ERROR;
}
- /* Construct sid and return it */
-
- sid_copy(&sid, &domain->sid);
- sid_append_rid(&sid, user_rid);
sid_to_string(state->response.data.sid.sid, &sid);
state->response.data.sid.type = SID_NAME_USER;
@@ -216,8 +183,6 @@ enum winbindd_result winbindd_uid_to_sid(struct winbindd_cli_state *state)
enum winbindd_result winbindd_gid_to_sid(struct winbindd_cli_state *state)
{
- struct winbindd_domain *domain;
- uint32 group_rid;
DOM_SID sid;
/* Bug out if the gid isn't in the winbind range */
@@ -230,19 +195,14 @@ enum winbindd_result winbindd_gid_to_sid(struct winbindd_cli_state *state)
DEBUG(3, ("[%5d]: gid to sid %d\n", state->pid,
state->request.data.gid));
- /* Lookup rid for this uid */
-
- if (!winbindd_idmap_get_rid_from_gid(state->request.data.gid,
- &group_rid, &domain)) {
- DEBUG(1, ("Could not convert gid %d to rid\n",
+ /* Lookup sid for this uid */
+ if (!winbindd_idmap_get_sid_from_gid(state->request.data.gid, &sid)) {
+ DEBUG(1, ("Could not convert gid %d to sid\n",
state->request.data.gid));
return WINBINDD_ERROR;
}
/* Construct sid and return it */
-
- sid_copy(&sid, &domain->sid);
- sid_append_rid(&sid, group_rid);
sid_to_string(state->response.data.sid.sid, &sid);
state->response.data.sid.type = SID_NAME_DOM_GRP;
diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c
index 48c756712d..e274c78220 100644
--- a/source3/nsswitch/winbindd_util.c
+++ b/source3/nsswitch/winbindd_util.c
@@ -178,7 +178,7 @@ BOOL init_domain_list(void)
/* Given a domain name, return the struct winbindd domain info for it
if it is actually working. */
-struct winbindd_domain *find_domain_from_name(char *domain_name)
+struct winbindd_domain *find_domain_from_name(const char *domain_name)
{
struct winbindd_domain *domain;
diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c
index 3a939e4fce..f2b3bdbe6c 100644
--- a/source3/smbd/uid.c
+++ b/source3/smbd/uid.c
@@ -596,6 +596,11 @@ BOOL sid_to_uid(DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype)
*sidtype = SID_NAME_UNKNOWN;
+
+/* (tridge) I commented out the slab of code below in order to support foreign SIDs
+ Do we really need to validate the type of SID we have in this case?
+*/
+#if 0
/*
* First we must look up the name and decide if this is a user sid.
*/
@@ -616,7 +621,7 @@ BOOL sid_to_uid(DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype)
(unsigned int)name_type ));
return False;
}
-
+#endif
*sidtype = SID_NAME_USER;
/*
@@ -658,7 +663,13 @@ BOOL sid_to_gid(DOM_SID *psid, gid_t *pgid, enum SID_NAME_USE *sidtype)
DEBUG(10,("sid_to_gid: winbind lookup for sid %s failed - trying local.\n",
sid_to_string(sid_str, psid) ));
- return local_sid_to_gid(pgid, psid, sidtype);
+ if (!local_sid_to_gid(pgid, psid, sidtype)) {
+ /* this was probably a foreign sid - assume its a group rid
+ and continue */
+ name_type = SID_NAME_DOM_GRP;
+ } else {
+ return True;
+ }
}
/*