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:
parent
9d975fa6bc
commit
276ff4df82
@ -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;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user