diff options
-rw-r--r-- | source3/sam/idmap_rid.c | 305 |
1 files changed, 150 insertions, 155 deletions
diff --git a/source3/sam/idmap_rid.c b/source3/sam/idmap_rid.c index 0a81475378..222d5e0963 100644 --- a/source3/sam/idmap_rid.c +++ b/source3/sam/idmap_rid.c @@ -7,14 +7,6 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * - * TODO: - * - use str_list_copy to work on a either space or comma-separated list - * - assure somehow that we cannot swap uids/gids (difficult without any - * knowledge about the sid-type) - * - fix memory allocation - * - further cleanup - * - add spnego-login */ #include "includes.h" @@ -22,13 +14,15 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_IDMAP +#define IDMAP_RID_SUPPORT_TRUSTED_DOMAINS 0 + NTSTATUS init_module(void); struct dom_entry { - char *name; - char *sid; - int min_id; - int max_id; + fstring name; + fstring sid; + uint32 min_id; + uint32 max_id; }; typedef struct trust_dom_array { @@ -38,139 +32,111 @@ typedef struct trust_dom_array { static trust_dom_array trust; -static NTSTATUS rid_idmap_parse(char *init_param, +static NTSTATUS rid_idmap_parse(const char *init_param, uint32 num_domains, - char **domain_names, + fstring *domain_names, DOM_SID *domain_sids, uid_t u_low, uid_t u_high) { - char *p, *e; + const char *p; int i; trust.number = 0; - trust.dom = NULL; fstring sid_str; BOOL known_domain = False; p = init_param; - - /* init sizes */ - trust.dom = (struct dom_entry *) malloc(sizeof(struct dom_entry)); - if (trust.dom == NULL) - return NT_STATUS_NO_MEMORY; - - trust.dom[0].sid = (char *) malloc(strlen(sid_str)); - if (trust.dom[0].sid == NULL) - return NT_STATUS_NO_MEMORY; - - trust.dom[0].name = (char *) malloc(strlen(p)); - if (trust.dom[0].name == NULL) - return NT_STATUS_NO_MEMORY; + fstring tok; /* falling back to automatic mapping when there were no options given */ - if (!*init_param) { + if (!*init_param || !lp_allow_trusted_domains()) { + + DEBUG(3,("rid_idmap_parse: no domain list given or trusted domain-support deactivated, falling back to automatic mapping for own domain:\n")); - DEBUG(3,("rid_idmap_parse: no domain list given, falling back to automatic mapping for own domain:\n")); + sid_to_string(sid_str, &domain_sids[0]); - sid_to_string(sid_str, &domain_sids[num_domains-1]); - trust.dom[0].name = domain_names[num_domains-1]; - trust.dom[0].sid = strdup(sid_str); + fstrcpy(trust.dom[0].name, domain_names[0]); + fstrcpy(trust.dom[0].sid, sid_str); trust.dom[0].min_id = u_low; trust.dom[0].max_id = u_high; trust.number = 1; + DEBUGADD(3,("rid_idmap_parse:\tdomain: [%s], sid: [%s], range=[%d-%d]\n", trust.dom[0].name, trust.dom[0].sid, trust.dom[0].min_id, trust.dom[0].max_id)); return NT_STATUS_OK; } /* scan through the init_param-list */ - for(;;) { + while (next_token(&init_param, tok, LIST_SEP, sizeof(tok))) { + p = tok; DEBUG(3,("rid_idmap_parse: parsing entry: %d\n", trust.number)); /* reinit sizes */ - trust.dom = (struct dom_entry *) realloc(trust.dom,sizeof(struct dom_entry)*(trust.number+1)); - if ( trust.dom == NULL ) + trust.dom = (struct dom_entry *) realloc(trust.dom, sizeof(struct dom_entry)*(trust.number+1)); + + if ( trust.dom == NULL ) { return NT_STATUS_NO_MEMORY; + } - trust.dom[trust.number].sid = (char *) malloc(strlen(p)); - trust.dom[trust.number].name = (char *) malloc(strlen(p)); - if (trust.dom[trust.number].sid == NULL || trust.dom[trust.number].name == NULL) - return NT_STATUS_NO_MEMORY; - - - if ( (e = strchr(p,'=')) == NULL ) { + if (!next_token(&p, tok, "=", sizeof(tok))) { DEBUG(0, ("rid_idmap_parse: no '=' sign found in domain list [%s]\n", init_param)); - return NT_STATUS_INVALID_PARAMETER; + return NT_STATUS_UNSUCCESSFUL; } - *e = '\0'; - - /* add the name */ - i=0; - do { - if ( *p != ' ' && *p != '\t' ) { - trust.dom[trust.number].name[i++] = *p; - } - p++; - } while(*p); - trust.dom[trust.number].name[i++] = '\0'; + /* add the name */ + fstrcpy(trust.dom[trust.number].name, tok); DEBUGADD(3,("rid_idmap_parse:\tentry %d has name: [%s]\n", trust.number, trust.dom[trust.number].name)); /* add the domain-sid */ for (i=0; i<num_domains; i++) { + known_domain = False; - if (strequal(domain_names[i],trust.dom[trust.number].name)) { + + if (strequal(domain_names[i], trust.dom[trust.number].name)) { + sid_to_string(sid_str, &domain_sids[i]); - trust.dom[trust.number].sid = strdup(sid_str); + fstrcpy(trust.dom[trust.number].sid, sid_str); + DEBUGADD(3,("rid_idmap_parse:\tentry %d has sid: [%s]\n", trust.number, trust.dom[trust.number].sid)); known_domain = True; + break; } } if (!known_domain) { - DEBUG(0,("rid_idmap_parse: your DC does not know anything about: [%s]\n", trust.dom[trust.number].name)); + DEBUG(0,("rid_idmap_parse: your DC does not know anything about domain: [%s]\n", trust.dom[trust.number].name)); return NT_STATUS_INVALID_PARAMETER; } - - p = e + 1; - if ( (e = strchr(p,'-')) == NULL ) + + if (!next_token(&p, tok, "-", sizeof(tok))) { + DEBUG(0,("rid_idmap_parse: no mapping-range defined\n")); return NT_STATUS_INVALID_PARAMETER; - - *e = '\0'; + } /* add min_id */ - trust.dom[trust.number].min_id = atoi(p); + trust.dom[trust.number].min_id = atoi(tok); DEBUGADD(3,("rid_idmap_parse:\tentry %d has min_id: [%d]\n", trust.number, trust.dom[trust.number].min_id)); - p = e + 1; /* add max_id */ trust.dom[trust.number].max_id = atoi(p); DEBUGADD(3,("rid_idmap_parse:\tentry %d has max_id: [%d]\n", trust.number, trust.dom[trust.number].max_id)); - trust.number++; - - if ( (e = strchr(p,',')) == NULL ) { - break; - } else { - *e = '\0'; - p = e + 1; - } + trust.number++; } + return NT_STATUS_OK; } -static NTSTATUS rid_idmap_get_domains(uint32 *num_domains, char ***domain_names, DOM_SID **domain_sids) +static NTSTATUS rid_idmap_get_domains(uint32 *num_domains, fstring **domain_names, DOM_SID **domain_sids) { NTSTATUS status = NT_STATUS_UNSUCCESSFUL; struct cli_state *cli; TALLOC_CTX *mem_ctx; POLICY_HND pol; uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; - uint32 enum_ctx = 0; fstring dc_name; struct in_addr dc_ip; - char *password = NULL; char *username = NULL; char *domain = NULL; @@ -212,12 +178,13 @@ static NTSTATUS rid_idmap_get_domains(uint32 *num_domains, char ***domain_names, } else { DEBUG(3, ("rid_idmap_get_domains: IPC$ connections done anonymously\n")); - username = smb_xstrdup(""); - domain = smb_xstrdup(""); - password = smb_xstrdup(""); + username = ""; + domain = ""; + password = ""; } DEBUG(10, ("rid_idmap_get_domains: opening connection to [%s]\n", dc_name)); + status = cli_full_connection(&cli, global_myname(), dc_name, NULL, 0, "IPC$", "IPC", @@ -225,6 +192,7 @@ static NTSTATUS rid_idmap_get_domains(uint32 *num_domains, char ***domain_names, lp_workgroup(), password, CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK, True, NULL); + if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("rid_idmap_get_domains: could not setup connection to dc\n")); return status; @@ -241,6 +209,7 @@ static NTSTATUS rid_idmap_get_domains(uint32 *num_domains, char ***domain_names, if (!NT_STATUS_IS_OK(status)) { goto out; } + status = cli_lsa_query_info_policy(cli, mem_ctx, &pol, info_class, &domain_name, &domain_sid); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("rid_idmap_get_domains: cannot retrieve domain-info\n")); @@ -250,46 +219,51 @@ static NTSTATUS rid_idmap_get_domains(uint32 *num_domains, char ***domain_names, sid_to_string(sid_str, domain_sid); DEBUG(10,("rid_idmap_get_domains: my domain: [%s], sid: [%s]\n", domain_name, sid_str)); - /* scan trusted domains */ - DEBUG(10, ("rid_idmap_get_domains: enumerating trusted domains\n")); - status = cli_lsa_enum_trust_dom(cli, mem_ctx, &pol, &enum_ctx, - &trusted_num_domains, - &trusted_domain_names, - &trusted_domain_sids); - - if (!NT_STATUS_IS_OK(status) && - !NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_ENTRIES) && - !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) { - DEBUG(1, ("rid_idmap_get_domains: could not enumerate trusted domains\n")); - goto out; - } + if (lp_allow_trusted_domains()) { + + uint32 enum_ctx = 0; - /* show trusted domains */ - DEBUG(10,("rid_idmap_get_domains: scan for domains gave %d results:\n", trusted_num_domains)); - for (i=0;i<trusted_num_domains;i++) { - sid_to_string(sid_str, &trusted_domain_sids[i]); - DEBUGADD(10,("rid_idmap_get_domains:\t#%d\tDOMAIN: [%s], SID: [%s]\n", - i, trusted_domain_names[i], sid_str)); + /* scan trusted domains */ + DEBUG(10, ("rid_idmap_get_domains: enumerating trusted domains\n")); + status = cli_lsa_enum_trust_dom(cli, mem_ctx, &pol, &enum_ctx, + &trusted_num_domains, + &trusted_domain_names, + &trusted_domain_sids); + + if (!NT_STATUS_IS_OK(status) && + !NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_ENTRIES) && + !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) { + DEBUG(1, ("rid_idmap_get_domains: could not enumerate trusted domains\n")); + goto out; + } + + /* show trusted domains */ + DEBUG(10,("rid_idmap_get_domains: scan for trusted domains gave %d results:\n", trusted_num_domains)); + for (i=0; i<trusted_num_domains; i++) { + sid_to_string(sid_str, &trusted_domain_sids[i]); + DEBUGADD(10,("rid_idmap_get_domains:\t#%d\tDOMAIN: [%s], SID: [%s]\n", + i, trusted_domain_names[i], sid_str)); + } } /* put the results together */ *num_domains = trusted_num_domains + 1; - *domain_names = (char **) malloc(sizeof(char *) * *num_domains); + *domain_names = (fstring *) malloc(sizeof(fstring) * *num_domains); *domain_sids = (DOM_SID *) malloc(sizeof(DOM_SID) * *num_domains); /* first add myself at the end*/ - (*domain_names)[*num_domains-1] = strdup(domain_name); - sid_copy(&(*domain_sids)[*num_domains-1], domain_sid); + fstrcpy((*domain_names)[0], domain_name); + sid_copy(&(*domain_sids)[0], domain_sid); /* add trusted domains */ - for (i=0;i<trusted_num_domains;i++) { - (*domain_names)[i] = strdup(trusted_domain_names[i]); - sid_copy(&((*domain_sids)[i]), &(trusted_domain_sids[i])); + for (i=0; i<trusted_num_domains; i++) { + fstrcpy((*domain_names)[i+1], trusted_domain_names[i]); + sid_copy(&((*domain_sids)[i+1]), &(trusted_domain_sids[i])); } /* show complete domain list */ DEBUG(5,("rid_idmap_get_domains: complete domain-list has %d entries:\n", *num_domains)); - for (i=0;i<*num_domains;i++) { + for (i=0; i<*num_domains; i++) { sid_to_string(sid_str, &((*domain_sids)[i])); DEBUGADD(5,("rid_idmap_get_domains:\t#%d\tdomain: [%s], sid: [%s]\n", i, (*domain_names)[i], sid_str )); @@ -302,6 +276,7 @@ out: cli_nt_session_close(cli); talloc_destroy(mem_ctx); cli_shutdown(cli); + return status; } @@ -311,19 +286,36 @@ static NTSTATUS rid_idmap_init(char *init_param) uid_t u_low, u_high; gid_t g_low, g_high; uint32 num_domains = 0; - char **domain_names; + fstring *domain_names; DOM_SID *domain_sids; - NTSTATUS nt_status; + NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER; + trust.dom = NULL; /* basic sanity checks */ if (!lp_idmap_uid(&u_low, &u_high) || !lp_idmap_gid(&g_low, &g_high)) { - DEBUG(0, ("rid_idmap_init: cannot get global idmap-ranges.\n")); - return NT_STATUS_INVALID_PARAMETER; + DEBUG(0, ("rid_idmap_init: cannot get required global idmap-ranges.\n")); + return nt_status; } if (u_low != g_low || u_high != g_high) { DEBUG(0, ("rid_idmap_init: range defined in \"idmap uid\" must match range of \"idmap gid\".\n")); - return NT_STATUS_INVALID_PARAMETER; + return nt_status; + } + + if (lp_allow_trusted_domains()) { +#if IDMAP_RID_SUPPORT_TRUSTED_DOMAINS + DEBUG(3,("rid_idmap_init: enabling trusted-domain-mapping\n")); +#else + DEBUG(0,("rid_idmap_init: idmap_rid does not work with trusted domains\n")); + DEBUGADD(0,("rid_idmap_init: please set \"allow trusted domains\" to \"no\" when using idmap_rid\n")); + return nt_status; +#endif + } + + /* init sizes */ + trust.dom = (struct dom_entry *) malloc(sizeof(struct dom_entry)); + if (trust.dom == NULL) { + return NT_STATUS_NO_MEMORY; } /* retrieve full domain list */ @@ -332,48 +324,58 @@ static NTSTATUS rid_idmap_init(char *init_param) !NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_MORE_ENTRIES) && !NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES)) { DEBUG(0, ("rid_idmap_init: cannot fetch sids for domain and/or trusted-domains from domain-controller.\n")); - return NT_STATUS_INVALID_PARAMETER; + return nt_status; } /* parse the init string */ nt_status = rid_idmap_parse(init_param, num_domains, domain_names, domain_sids, u_low, u_high); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0, ("rid_idmap_init: cannot parse module-configuration\n")); - return NT_STATUS_INVALID_PARAMETER; + goto out; } + nt_status = NT_STATUS_INVALID_PARAMETER; + /* some basic sanity checks */ - for(i=0;i<trust.number;i++) { - DEBUG(10,("rid_idmap_init: sanity checks on mapping of domain: [%s]\n", trust.dom[i].name)); + for (i=0; i<trust.number; i++) { + if (trust.dom[i].min_id > trust.dom[i].max_id) { - DEBUG(0, ("rid_idmap_init: min_id has to be smaller than max_id for %s\n",trust.dom[i].name)); - return NT_STATUS_INVALID_PARAMETER; + DEBUG(0, ("rid_idmap_init: min_id (%d) has to be smaller than max_id (%d) for domain [%s]\n", + trust.dom[i].min_id, trust.dom[i].max_id, trust.dom[i].name)); + goto out; } + if (trust.dom[i].min_id < u_low || trust.dom[i].max_id > u_high) { - DEBUG(0, ("rid_idmap_init: mapping of domain %s (%d-%d) has to fit into global idmap range (%d-%d).\n", + DEBUG(0, ("rid_idmap_init: mapping of domain [%s] (%d-%d) has to fit into global idmap range (%d-%d).\n", trust.dom[i].name, trust.dom[i].min_id, trust.dom[i].max_id, u_low, u_high)); - return NT_STATUS_INVALID_PARAMETER; + goto out; } } /* check for overlaps */ - for(i=0;i<trust.number-1;i++) { - for(j=i+1;j<trust.number;j++) { + for (i=0; i<trust.number-1; i++) { + for (j=i+1; j<trust.number; j++) { if (trust.dom[i].min_id <= trust.dom[j].max_id && trust.dom[j].min_id <= trust.dom[i].max_id) { - DEBUG(0, ("rid_idmap_init: the ranges of %s and %s overlap\n", + DEBUG(0, ("rid_idmap_init: the ranges of domain [%s] and [%s] overlap\n", trust.dom[i+1].name, trust.dom[i].name)); - return NT_STATUS_INVALID_PARAMETER; + goto out; } } } - DEBUG(3, ("rid_idmap_init: using the %d following mappings:\n", trust.number)); - for(i=0;i<trust.number;i++) { + DEBUG(3, ("rid_idmap_init: using %d mappings:\n", trust.number)); + for (i=0; i<trust.number; i++) { DEBUGADD(3, ("rid_idmap_init:\tdomain: [%s], sid: [%s], min_id: [%d], max_id: [%d]\n", trust.dom[i].name, trust.dom[i].sid, trust.dom[i].min_id, trust.dom[i].max_id)); } - - return NT_STATUS_OK; + + nt_status = NT_STATUS_OK; + +out: + SAFE_FREE(domain_names); + SAFE_FREE(domain_sids); + + return nt_status; } static NTSTATUS rid_idmap_get_sid_from_id(DOM_SID *sid, unid_t unid, int id_type) @@ -382,25 +384,24 @@ static NTSTATUS rid_idmap_get_sid_from_id(DOM_SID *sid, unid_t unid, int id_type int i; DOM_SID sidstr; - if (sid == NULL) { - return NT_STATUS_INVALID_PARAMETER; - } - /* find range */ - for(i=0;i<trust.number;i++) { + for (i=0; i<trust.number; i++) { if (trust.dom[i].min_id <= unid.uid && trust.dom[i].max_id >= unid.uid ) break; } - + if (i == trust.number) { - DEBUG(0,("no range found for uid: %d\n",unid.uid)); - return NT_STATUS_NOT_IMPLEMENTED; + DEBUG(0,("rid_idmap_get_sid_from_id: no suitable range available for id: %d\n", unid.uid)); + return NT_STATUS_INVALID_PARAMETER; } /* use lower-end of idmap-range as offset for users and groups*/ - (unsigned long)unid.uid -= trust.dom[i].min_id; + unid.uid -= trust.dom[i].min_id; - string_to_sid(&sidstr,trust.dom[i].sid); + if (!trust.dom[i].sid) + return NT_STATUS_INVALID_PARAMETER; + + string_to_sid(&sidstr, trust.dom[i].sid); sid_copy(sid, &sidstr); if (!sid_append_rid( sid, (unsigned long)unid.uid )) { DEBUG(0,("rid_idmap_get_sid_from_id: could not append rid to domain sid\n")); @@ -421,30 +422,29 @@ static NTSTATUS rid_idmap_get_id_from_sid(unid_t *unid, int *id_type, const DOM_ uint32 rid; DOM_SID sidstr; - if (unid == NULL) { - return NT_STATUS_INVALID_PARAMETER; - } - - /* check if we have a mapping for the sid*/ - for(i=0;i<trust.number;i++) { - string_to_sid(&sidstr,trust.dom[i].sid); + /* check if we have a mapping for the sid */ + for (i=0; i<trust.number; i++) { + if (!trust.dom[i].sid) { + return NT_STATUS_INVALID_PARAMETER; + } + string_to_sid(&sidstr, trust.dom[i].sid); if ( sid_compare_domain(sid, &sidstr) == 0 ) break; } if (i == trust.number) { - DEBUG(0,("rid_idmap_get_id_from_sid: we have no mapping for sid: [%s] in domain: [%s]\n", - sid_to_string(sid_string, sid), trust.dom[i].name)); - return NT_STATUS_NOT_IMPLEMENTED; + DEBUG(0,("rid_idmap_get_id_from_sid: no suitable range available for sid: %s\n", + sid_string_static(sid))); + return NT_STATUS_INVALID_PARAMETER; } if (!sid_peek_rid(sid, &rid)) { DEBUG(0,("rid_idmap_get_id_from_sid: could not peek rid\n")); - return NT_STATUS_NOT_IMPLEMENTED; + return NT_STATUS_INVALID_PARAMETER; } /* use lower-end of idmap-range as offset for users and groups */ - (unsigned long)unid->uid = rid + trust.dom[i].min_id; + unid->uid = rid + trust.dom[i].min_id; if (unid->uid > trust.dom[i].max_id) { DEBUG(0,("rid_idmap_get_id_from_sid: rid: %d too high for mapping of domain: %s\n", rid, trust.dom[i].name)); @@ -470,12 +470,7 @@ static NTSTATUS rid_idmap_set_mapping(const DOM_SID *sid, unid_t id, int id_type static NTSTATUS rid_idmap_close(void) { - int i; - for(i=0;i<trust.number;i++) { - free(trust.dom[i].sid); - free(trust.dom[i].name); - } - free(trust.dom); + SAFE_FREE(trust.dom); return NT_STATUS_OK; } |