1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-13 13:18:06 +03:00

this allows us to support foreign SIDs in winbindd and smbd

this means "xcopy /o" has a chance of working with ACLs that contain
ACEs that use SIDs that the Samba server has no knowledge of.

It's a bit hackish, Tim, can you look at my uid.c changes?
(This used to be commit fe2db31485)
This commit is contained in:
Andrew Tridgell 2002-02-27 23:51:25 +00:00
parent 9d975fa6bc
commit 276ff4df82
6 changed files with 187 additions and 120 deletions

View File

@ -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;
}

View File

@ -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 */
BOOL winbindd_idmap_get_uid_from_rid(char *domain_name, uint32 user_rid,
uid_t *uid)
/* Get a uid from a user sid */
BOOL winbindd_idmap_get_uid_from_sid(DOM_SID *sid, uid_t *uid)
{
return get_id_from_rid(domain_name, user_rid, uid, False);
return get_id_from_sid(sid, uid, False);
}
/* Get a gid from a group sid */
BOOL winbindd_idmap_get_gid_from_sid(DOM_SID *sid, gid_t *gid)
{
return get_id_from_sid(sid, gid, True);
}
/* 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;
}
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(char *domain_name, uint32 group_rid,
gid_t *gid)
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) {

View File

@ -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,

View File

@ -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;

View File

@ -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;

View File

@ -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;
}
}
/*