NTSTATUS sec_ace_del_sid(TALLOC_CTX *ctx, SEC_ACE **pp_new, SEC_ACE *old, uint32 *num, DOM_SID *sid) { unsigned int i = 0; unsigned int n_del = 0; if (!ctx || !pp_new || !old || !sid || !num) return NT_STATUS_INVALID_PARAMETER; if (*num) { if((pp_new[0] = TALLOC_ZERO_ARRAY(ctx, SEC_ACE, *num )) == 0) return NT_STATUS_NO_MEMORY; } else { pp_new[0] = NULL; } for (i = 0; i < *num; i ++) { if (sid_compare(&old[i].trustee, sid) != 0) sec_ace_copy(&(*pp_new)[i], &old[i]); else n_del ++; } if (n_del == 0) return NT_STATUS_NOT_FOUND; else { *num -= n_del; return NT_STATUS_OK; } }
void init_unistr2_w(TALLOC_CTX *ctx, UNISTR2 *str, const smb_ucs2_t *buf) { uint32 len = buf ? strlen_w(buf) : 0; ZERO_STRUCTP(str); /* set up string lengths. */ str->uni_max_len = len; str->offset = 0; str->uni_str_len = len; str->buffer = TALLOC_ZERO_ARRAY(ctx, uint16, len + 1); if (str->buffer == NULL) { smb_panic("init_unistr2_w: talloc fail\n"); return; } /* * don't move this test above ! The UNISTR2 must be initialized !!! * jfm, 7/7/2001. */ if (buf==NULL) return; /* Yes, this is a strncpy( foo, bar, strlen(bar)) - but as long as the buffer above is talloc()ed correctly then this is the correct thing to do */ strncpy_w(str->buffer, buf, len + 1); }
void init_unistr2_from_unistr(UNISTR2 *to, const UNISTR *from) { uint32 i; /* the destination UNISTR2 should never be NULL. if it is it is a programming error */ /* if the source UNISTR is NULL, then zero out the destination string and return */ ZERO_STRUCTP (to); if ((from == NULL) || (from->buffer == NULL)) return; /* get the length; UNISTR must be NULL terminated */ i = 0; while ((from->buffer)[i]!='\0') i++; i++; /* one more to catch the terminating NULL */ /* is this necessary -- jerry? I need to think */ /* set up string lengths; uni_max_len is set to i+1 because we need to account for the final NULL termination */ to->uni_max_len = i; to->offset = 0; to->uni_str_len = i; /* allocate the space and copy the string buffer */ to->buffer = TALLOC_ZERO_ARRAY(get_talloc_ctx(), uint16, i); if (to->buffer == NULL) smb_panic("init_unistr2_from_unistr: malloc fail\n"); memcpy(to->buffer, from->buffer, i*sizeof(uint16)); return; }
void copy_unistr2(UNISTR2 *str, const UNISTR2 *from) { if (from->buffer == NULL) { ZERO_STRUCTP(str); return; } SMB_ASSERT(from->uni_max_len >= from->uni_str_len); str->uni_max_len = from->uni_max_len; str->offset = from->offset; str->uni_str_len = from->uni_str_len; /* the string buffer is allocated to the maximum size (the the length of the source string) to prevent reallocation of memory. */ if (str->buffer == NULL) { str->buffer = (uint16 *)TALLOC_ZERO_ARRAY(get_talloc_ctx(), uint16, str->uni_max_len); if ((str->buffer == NULL)) { smb_panic("copy_unistr2: talloc fail\n"); return; } } /* copy the string */ memcpy(str->buffer, from->buffer, str->uni_max_len*sizeof(uint16)); }
BOOL prs_unistr4_array(const char *desc, prs_struct *ps, int depth, UNISTR4_ARRAY *array ) { unsigned int i; prs_debug(ps, depth, desc, "prs_unistr4_array"); depth++; if(!prs_uint32("count", ps, depth, &array->count)) return False; if ( array->count == 0 ) return True; if (UNMARSHALLING(ps)) { if ( !(array->strings = TALLOC_ZERO_ARRAY( get_talloc_ctx(), UNISTR4, array->count)) ) return False; } /* write the headers and then the actual string buffer */ for ( i=0; i<array->count; i++ ) { if ( !prs_unistr4_hdr( "string", ps, depth, &array->strings[i]) ) return False; } for (i=0;i<array->count;i++) { if ( !prs_unistr4_str("string", ps, depth, &array->strings[i]) ) return False; } return True; }
void init_unistr2(UNISTR2 *str, const char *buf, enum unistr2_term_codes flags) { size_t len = 0; uint32 num_chars = 0; if (buf) { /* We always null terminate the copy. */ len = strlen(buf) + 1; if ( flags == UNI_STR_DBLTERMINATE ) len++; } else { /* no buffer -- nothing to do */ str->uni_max_len = 0; str->offset = 0; str->uni_str_len = 0; return; } str->buffer = TALLOC_ZERO_ARRAY(get_talloc_ctx(), uint16, len); if (str->buffer == NULL) { smb_panic("init_unistr2: malloc fail\n"); return; } /* Ensure len is the length in *bytes* */ len *= sizeof(uint16); /* * The UNISTR2 must be initialized !!! * jfm, 7/7/2001. */ if (buf) { rpcstr_push((char *)str->buffer, buf, len, STR_TERMINATE); num_chars = strlen_w(str->buffer); if (flags == UNI_STR_TERMINATE || flags == UNI_MAXLEN_TERMINATE) { num_chars++; } if ( flags == UNI_STR_DBLTERMINATE ) num_chars += 2; } str->uni_max_len = num_chars; str->offset = 0; str->uni_str_len = num_chars; if ( num_chars && ((flags == UNI_MAXLEN_TERMINATE) || (flags == UNI_BROKEN_NON_NULL)) ) str->uni_max_len++; }
void init_unistr3(UNISTR3 *str, const char *buf) { if (buf == NULL) { str->uni_str_len=0; str->str.buffer = NULL; return; } str->uni_str_len = strlen(buf) + 1; str->str.buffer = TALLOC_ZERO_ARRAY(get_talloc_ctx(), uint16, str->uni_str_len); if (str->str.buffer == NULL) smb_panic("init_unistr3: malloc fail\n"); rpcstr_push((char *)str->str.buffer, buf, str->uni_str_len * sizeof(uint16), STR_TERMINATE); }
void init_unistr(UNISTR *str, const char *buf) { size_t len; if (buf == NULL) { str->buffer = NULL; return; } len = strlen(buf) + 1; str->buffer = TALLOC_ZERO_ARRAY(get_talloc_ctx(), uint16, len); if (str->buffer == NULL) smb_panic("init_unistr: malloc fail\n"); rpcstr_push(str->buffer, buf, len*sizeof(uint16), STR_TERMINATE); }
BOOL init_unistr4_array( UNISTR4_ARRAY *array, uint32 count, const char **strings ) { unsigned int i; array->count = count; if ( array->count == 0 ) return True; /* allocate memory for the array of UNISTR4 objects */ if ( !(array->strings = TALLOC_ZERO_ARRAY(get_talloc_ctx(), UNISTR4, count )) ) return False; for ( i=0; i<count; i++ ) init_unistr4( &array->strings[i], strings[i], UNI_STR_TERMINATE ); return True; }
NTSTATUS sec_ace_add_sid(TALLOC_CTX *ctx, SEC_ACE **pp_new, SEC_ACE *old, unsigned *num, DOM_SID *sid, uint32 mask) { unsigned int i = 0; if (!ctx || !pp_new || !old || !sid || !num) return NT_STATUS_INVALID_PARAMETER; *num += 1; if((pp_new[0] = TALLOC_ZERO_ARRAY(ctx, SEC_ACE, *num )) == 0) return NT_STATUS_NO_MEMORY; for (i = 0; i < *num - 1; i ++) sec_ace_copy(&(*pp_new)[i], &old[i]); (*pp_new)[i].type = 0; (*pp_new)[i].flags = 0; (*pp_new)[i].size = SEC_ACE_HEADER_SIZE + sid_size(sid); (*pp_new)[i].access_mask = mask; sid_copy(&(*pp_new)[i].trustee, sid); return NT_STATUS_OK; }
static SEC_DESC* parse_acl_string(TALLOC_CTX *mem_ctx, const char *szACL, size_t *sd_size ) { SEC_DESC *sd = NULL; SEC_ACE *ace; SEC_ACL *acl; int num_ace; const char *pacl; int i; if ( !szACL ) return NULL; pacl = szACL; num_ace = count_chars( pacl, ',' ) + 1; if ( !(ace = TALLOC_ZERO_ARRAY( mem_ctx, SEC_ACE, num_ace )) ) return NULL; for ( i=0; i<num_ace; i++ ) { char *end_acl = strchr_m( pacl, ',' ); fstring acl_string; strncpy( acl_string, pacl, MIN( PTR_DIFF( end_acl, pacl ), sizeof(fstring)-1) ); acl_string[MIN( PTR_DIFF( end_acl, pacl ), sizeof(fstring)-1)] = '\0'; if ( !parse_ace( &ace[i], acl_string ) ) return NULL; pacl = end_acl; pacl++; } if ( !(acl = make_sec_acl( mem_ctx, NT4_ACL_REVISION, num_ace, ace )) ) return NULL; sd = make_sec_desc( mem_ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, acl, sd_size); return sd; }
RPC_DATA_BLOB *cac_MakeRpcDataBlob( TALLOC_CTX * mem_ctx, uint32 data_type, REG_VALUE_DATA data ) { RPC_DATA_BLOB *blob = NULL; int i; uint32 size = 0; uint8 *multi = NULL; uint32 multi_idx = 0; blob = talloc( mem_ctx, RPC_DATA_BLOB ); if ( !blob ) { errno = ENOMEM; return NULL; } switch ( data_type ) { case REG_SZ: init_rpc_blob_str( blob, data.reg_sz, strlen( data.reg_sz ) + 1 ); break; case REG_EXPAND_SZ: init_rpc_blob_str( blob, data.reg_expand_sz, strlen( data.reg_sz ) + 1 ); break; case REG_BINARY: init_rpc_blob_bytes( blob, data.reg_binary.data, data.reg_binary.data_length ); break; case REG_DWORD: init_rpc_blob_uint32( blob, data.reg_dword ); break; case REG_DWORD_BE: init_rpc_blob_uint32( blob, data.reg_dword_be ); break; case REG_MULTI_SZ: /*need to find the size */ for ( i = 0; i < data.reg_multi_sz.num_strings; i++ ) { size += strlen( data.reg_multi_sz.strings[i] ) + 1; } /**need a whole bunch of unicode strings in a row (seperated by null characters), with an extra null-character on the end*/ multi = TALLOC_ZERO_ARRAY( mem_ctx, uint8, ( size + 1 ) * 2 ); /*size +1 for the extra null character */ if ( !multi ) { errno = ENOMEM; break; } /*do it using rpcstr_push() */ multi_idx = 0; for ( i = 0; i < data.reg_multi_sz.num_strings; i++ ) { size_t len = strlen( data.reg_multi_sz.strings[i] ) + 1; rpcstr_push( ( multi + multi_idx ), data.reg_multi_sz.strings[i], len * 2, STR_TERMINATE ); /* x2 becuase it is a uint8 buffer */ multi_idx += len * 2; } /*now initialize the buffer as binary data */ init_rpc_blob_bytes( blob, multi, ( size + 1 ) * 2 ); break; default: TALLOC_FREE( blob ); blob = NULL; return NULL; } if ( !( blob->buffer ) ) { TALLOC_FREE( blob ); return NULL; } return blob; }
static NTSTATUS ldif_init_context(TALLOC_CTX *mem_ctx, enum netr_SamDatabaseID database_id, const char *ldif_filename, const char *domain_sid_str, struct samsync_ldif_context **ctx) { NTSTATUS status = NT_STATUS_UNSUCCESSFUL; struct samsync_ldif_context *r; const char *add_template = "/tmp/add.ldif.XXXXXX"; const char *mod_template = "/tmp/mod.ldif.XXXXXX"; const char *builtin_sid = "S-1-5-32"; /* Get other smb.conf data */ if (!(lp_workgroup()) || !*(lp_workgroup())) { DEBUG(0,("workgroup missing from smb.conf--exiting\n")); exit(1); } /* Get the ldap suffix */ if (!(lp_ldap_suffix()) || !*(lp_ldap_suffix())) { DEBUG(0,("ldap suffix missing from smb.conf--exiting\n")); exit(1); } if (*ctx && (*ctx)->initialized) { return NT_STATUS_OK; } r = TALLOC_ZERO_P(mem_ctx, struct samsync_ldif_context); NT_STATUS_HAVE_NO_MEMORY(r); /* Get the ldap suffix */ r->suffix = lp_ldap_suffix(); /* Ensure we have an output file */ if (ldif_filename) { r->ldif_file = fopen(ldif_filename, "a"); } else { r->ldif_file = stdout; } if (!r->ldif_file) { fprintf(stderr, "Could not open %s\n", ldif_filename); DEBUG(1, ("Could not open %s\n", ldif_filename)); status = NT_STATUS_UNSUCCESSFUL; goto done; } r->add_template = talloc_strdup(mem_ctx, add_template); r->mod_template = talloc_strdup(mem_ctx, mod_template); if (!r->add_template || !r->mod_template) { status = NT_STATUS_NO_MEMORY; goto done; } r->add_name = talloc_strdup(mem_ctx, add_template); r->mod_name = talloc_strdup(mem_ctx, mod_template); if (!r->add_name || !r->mod_name) { status = NT_STATUS_NO_MEMORY; goto done; } /* Open the add and mod ldif files */ if (!(r->add_file = fdopen(smb_mkstemp(r->add_name),"w"))) { DEBUG(1, ("Could not open %s\n", r->add_name)); status = NT_STATUS_UNSUCCESSFUL; goto done; } if (!(r->mod_file = fdopen(smb_mkstemp(r->mod_name),"w"))) { DEBUG(1, ("Could not open %s\n", r->mod_name)); status = NT_STATUS_UNSUCCESSFUL; goto done; } /* Allocate initial memory for groupmap and accountmap arrays */ r->groupmap = TALLOC_ZERO_ARRAY(mem_ctx, GROUPMAP, 8); r->accountmap = TALLOC_ZERO_ARRAY(mem_ctx, ACCOUNTMAP, 8); if (r->groupmap == NULL || r->accountmap == NULL) { DEBUG(1,("GROUPMAP talloc failed\n")); status = NT_STATUS_NO_MEMORY; goto done; } /* Remember how many we malloced */ r->num_alloced = 8; /* Initial database population */ if (database_id == SAM_DATABASE_DOMAIN) { status = populate_ldap_for_ldif(domain_sid_str, r->suffix, builtin_sid, r->add_file); if (!NT_STATUS_IS_OK(status)) { goto done; } status = map_populate_groups(mem_ctx, r->groupmap, r->accountmap, domain_sid_str, r->suffix, builtin_sid); if (!NT_STATUS_IS_OK(status)) { goto done; } } r->initialized = true; *ctx = r; return NT_STATUS_OK; done: TALLOC_FREE(r); return status; }
/* find the members of a group, given a group rid and domain */ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const DOM_SID *group_sid, enum lsa_SidType type, uint32 *num_names, DOM_SID **sid_mem, char ***names, uint32 **name_types) { ADS_STATUS rc; ADS_STRUCT *ads = NULL; char *ldap_exp; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; char *sidbinstr; char **members = NULL; int i; size_t num_members = 0; ads_control args; DOM_SID *sid_mem_nocache = NULL; char **names_nocache = NULL; enum lsa_SidType *name_types_nocache = NULL; char **domains_nocache = NULL; /* only needed for rpccli_lsa_lookup_sids */ uint32 num_nocache = 0; TALLOC_CTX *tmp_ctx = NULL; DEBUG(10,("ads: lookup_groupmem %s sid=%s\n", domain->name, sid_string_dbg(group_sid))); *num_names = 0; tmp_ctx = talloc_new(mem_ctx); if (!tmp_ctx) { DEBUG(1, ("ads: lookup_groupmem: talloc failed\n")); status = NT_STATUS_NO_MEMORY; goto done; } if ( !winbindd_can_contact_domain( domain ) ) { DEBUG(10,("lookup_groupmem: No incoming trust for domain %s\n", domain->name)); return NT_STATUS_OK; } ads = ads_cached_connection(domain); if (!ads) { domain->last_status = NT_STATUS_SERVER_DISABLED; goto done; } if ((sidbinstr = sid_binstring(talloc_tos(), group_sid)) == NULL) { status = NT_STATUS_NO_MEMORY; goto done; } /* search for all members of the group */ ldap_exp = talloc_asprintf(tmp_ctx, "(objectSid=%s)", sidbinstr); TALLOC_FREE(sidbinstr); if (ldap_exp == NULL) { DEBUG(1, ("ads: lookup_groupmem: talloc_asprintf for ldap_exp failed!\n")); status = NT_STATUS_NO_MEMORY; goto done; } args.control = ADS_EXTENDED_DN_OID; args.val = ADS_EXTENDED_DN_HEX_STRING; args.critical = True; rc = ads_ranged_search(ads, tmp_ctx, LDAP_SCOPE_SUBTREE, ads->config.bind_path, ldap_exp, &args, "member", &members, &num_members); if (!ADS_ERR_OK(rc)) { DEBUG(0,("ads_ranged_search failed with: %s\n", ads_errstr(rc))); status = NT_STATUS_UNSUCCESSFUL; goto done; } DEBUG(10, ("ads lookup_groupmem: got %d sids via extended dn call\n", (int)num_members)); /* Now that we have a list of sids, we need to get the * lists of names and name_types belonging to these sids. * even though conceptually not quite clean, we use the * RPC call lsa_lookup_sids for this since it can handle a * list of sids. ldap calls can just resolve one sid at a time. * * At this stage, the sids are still hidden in the exetended dn * member output format. We actually do a little better than * stated above: In extracting the sids from the member strings, * we try to resolve as many sids as possible from the * cache. Only the rest is passed to the lsa_lookup_sids call. */ if (num_members) { (*sid_mem) = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, num_members); (*names) = TALLOC_ZERO_ARRAY(mem_ctx, char *, num_members); (*name_types) = TALLOC_ZERO_ARRAY(mem_ctx, uint32, num_members); (sid_mem_nocache) = TALLOC_ZERO_ARRAY(tmp_ctx, DOM_SID, num_members); if ((members == NULL) || (*sid_mem == NULL) || (*names == NULL) || (*name_types == NULL) || (sid_mem_nocache == NULL)) { DEBUG(1, ("ads: lookup_groupmem: talloc failed\n")); status = NT_STATUS_NO_MEMORY; goto done; } } else {
/* Lookup groups a user is a member of - alternate method, for when tokenGroups are not available. */ static NTSTATUS lookup_usergroups_memberof(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const char *user_dn, DOM_SID *primary_group, size_t *p_num_groups, DOM_SID **user_sids) { ADS_STATUS rc; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; ADS_STRUCT *ads; const char *attrs[] = {"memberOf", NULL}; size_t num_groups = 0; DOM_SID *group_sids = NULL; int i; char **strings = NULL; size_t num_strings = 0, num_sids = 0; DEBUG(3,("ads: lookup_usergroups_memberof\n")); if ( !winbindd_can_contact_domain( domain ) ) { DEBUG(10,("lookup_usergroups_memberof: No incoming trust for " "domain %s\n", domain->name)); return NT_STATUS_OK; } ads = ads_cached_connection(domain); if (!ads) { domain->last_status = NT_STATUS_SERVER_DISABLED; return NT_STATUS_UNSUCCESSFUL; } rc = ads_search_retry_extended_dn_ranged(ads, mem_ctx, user_dn, attrs, ADS_EXTENDED_DN_HEX_STRING, &strings, &num_strings); if (!ADS_ERR_OK(rc)) { DEBUG(1,("lookup_usergroups_memberof ads_search " "member=%s: %s\n", user_dn, ads_errstr(rc))); return ads_ntstatus(rc); } *user_sids = NULL; num_groups = 0; /* always add the primary group to the sid array */ status = add_sid_to_array(mem_ctx, primary_group, user_sids, &num_groups); if (!NT_STATUS_IS_OK(status)) { goto done; } group_sids = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, num_strings + 1); if (!group_sids) { status = NT_STATUS_NO_MEMORY; goto done; } for (i=0; i<num_strings; i++) { rc = ads_get_sid_from_extended_dn(mem_ctx, strings[i], ADS_EXTENDED_DN_HEX_STRING, &(group_sids)[i]); if (!ADS_ERR_OK(rc)) { /* ignore members without SIDs */ if (NT_STATUS_EQUAL(ads_ntstatus(rc), NT_STATUS_NOT_FOUND)) { continue; } else { status = ads_ntstatus(rc); goto done; } } num_sids++; } if (i == 0) { DEBUG(1,("No memberOf for this user?!?\n")); status = NT_STATUS_NO_MEMORY; goto done; } for (i=0; i<num_sids; i++) { /* ignore Builtin groups from ADS - Guenther */ if (sid_check_is_in_builtin(&group_sids[i])) { continue; } status = add_sid_to_array(mem_ctx, &group_sids[i], user_sids, &num_groups); if (!NT_STATUS_IS_OK(status)) { goto done; } } *p_num_groups = num_groups; status = (*user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY; DEBUG(3,("ads lookup_usergroups (memberof) succeeded for dn=%s\n", user_dn)); done: TALLOC_FREE(strings); TALLOC_FREE(group_sids); return status; }