Author: vlendec Date: 2005-12-29 13:18:28 +0000 (Thu, 29 Dec 2005) New Revision: 12566
WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=12566 Log: Move adding RIDs to pdb_ldap. Now I need to look at creating aliases, and I can (should I?) remove allocating RIDs from winbind. Nobody will be using that anymore... Volker Modified: trunk/source/include/smbldap.h trunk/source/lib/smbldap.c trunk/source/passdb/pdb_ldap.c Changeset: Modified: trunk/source/include/smbldap.h =================================================================== --- trunk/source/include/smbldap.h 2005-12-29 13:10:36 UTC (rev 12565) +++ trunk/source/include/smbldap.h 2005-12-29 13:18:28 UTC (rev 12566) @@ -209,6 +209,15 @@ const char *location); const char** get_userattr_list( int schema_ver ); +char * smbldap_talloc_single_attribute(LDAP *ldap_struct, LDAPMessage *entry, + const char *attribute, + TALLOC_CTX *mem_ctx); +void talloc_autodestroy_ldapmsg(TALLOC_CTX *mem_ctx, LDAPMessage *result); +const char *smbldap_talloc_dn(TALLOC_CTX *mem_ctx, LDAP *ld, + LDAPMessage *entry); + + + #endif /* HAVE_LDAP */ #define LDAP_CONNECT_DEFAULT_TIMEOUT 15 Modified: trunk/source/lib/smbldap.c =================================================================== --- trunk/source/lib/smbldap.c 2005-12-29 13:10:36 UTC (rev 12565) +++ trunk/source/lib/smbldap.c 2005-12-29 13:18:28 UTC (rev 12566) @@ -321,6 +321,63 @@ sizeof(pstring)); } + char * smbldap_talloc_single_attribute(LDAP *ldap_struct, LDAPMessage *entry, + const char *attribute, + TALLOC_CTX *mem_ctx) +{ + char **values; + char *result; + + if (attribute == NULL) { + return NULL; + } + + values = ldap_get_values(ldap_struct, entry, attribute); + + if (values == NULL) { + DEBUG(10, ("attribute %s does not exist\n", attribute)); + return NULL; + } + + if (ldap_count_values(values) != 1) { + DEBUG(10, ("attribute %s has %d values, expected only one\n", + attribute, ldap_count_values(values))); + ldap_value_free(values); + return NULL; + } + + if (pull_utf8_talloc(mem_ctx, &result, values[0]) < 0) { + DEBUG(10, ("pull_utf8_talloc failed\n")); + ldap_value_free(values); + return NULL; + } + + ldap_value_free(values); + +#ifdef DEBUG_PASSWORDS + DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n", + attribute, result)); +#endif + return result; +} + + static int ldapmsg_destructor(void *p) { + LDAPMessage **result = talloc_get_type_abort(p, LDAPMessage *); + ldap_msgfree(*result); + return 0; +} + + void talloc_autodestroy_ldapmsg(TALLOC_CTX *mem_ctx, LDAPMessage *result) +{ + LDAPMessage **handle; + + handle = TALLOC_P(mem_ctx, LDAPMessage *); + SMB_ASSERT(handle != NULL); + + *handle = result; + talloc_set_destructor(handle, ldapmsg_destructor); +} + /************************************************************************ Routine to manage the LDAPMod structure array manage memory used by the array, by each struct, and values @@ -1442,6 +1499,25 @@ return unix_dn; } + const char *smbldap_talloc_dn(TALLOC_CTX *mem_ctx, LDAP *ld, + LDAPMessage *entry) +{ + char *utf8_dn, *unix_dn; + + utf8_dn = ldap_get_dn(ld, entry); + if (!utf8_dn) { + DEBUG (5, ("smbldap_get_dn: ldap_get_dn failed\n")); + return NULL; + } + if (pull_utf8_talloc(mem_ctx, &unix_dn, utf8_dn) == (size_t)-1) { + DEBUG (0, ("smbldap_get_dn: String conversion failure utf8 " + "[%s]\n", utf8_dn)); + return NULL; + } + ldap_memfree(utf8_dn); + return unix_dn; +} + /******************************************************************* Check if root-dse has a certain Control or Extension ********************************************************************/ Modified: trunk/source/passdb/pdb_ldap.c =================================================================== --- trunk/source/passdb/pdb_ldap.c 2005-12-29 13:10:36 UTC (rev 12565) +++ trunk/source/passdb/pdb_ldap.c 2005-12-29 13:18:28 UTC (rev 12566) @@ -4258,9 +4258,120 @@ return False; } +static NTSTATUS ldapsam_get_new_rid(struct ldapsam_privates *ldap_state, + uint32 *rid) +{ + struct smbldap_state *smbldap_state = ldap_state->smbldap_state; + LDAP *ldap_struct = smbldap_state->ldap_struct; + + LDAPMessage *result = NULL; + LDAPMessage *entry = NULL; + LDAPMod **mods = NULL; + NTSTATUS status; + char *value; + int rc; + uint32 nextRid = 0; + + TALLOC_CTX *mem_ctx; + + mem_ctx = talloc_new(NULL); + if (mem_ctx == NULL) { + DEBUG(0, ("talloc_new failed\n")); + return NT_STATUS_NO_MEMORY; + } + + status = smbldap_search_domain_info(smbldap_state, &result, + get_global_sam_name(), False); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("Could not get domain info: %s\n", + nt_errstr(status))); + goto done; + } + + talloc_autodestroy_ldapmsg(mem_ctx, result); + + entry = ldap_first_entry(ldap_struct, result); + if (entry == NULL) { + DEBUG(0, ("Could not get domain info entry\n")); + status = NT_STATUS_INTERNAL_DB_CORRUPTION; + goto done; + } + + /* Find the largest of the three attributes "sambaNextRid", + "sambaNextGroupRid" and "sambaNextUserRid". I gave up on the + concept of differentiating between user and group rids, and will + use only "sambaNextRid" in the future. But for compatibility + reasons I look if others have chosen different strategies -- VL */ + + value = smbldap_talloc_single_attribute(ldap_struct, entry, + "sambaNextRid", mem_ctx); + if (value != NULL) { + uint32 tmp = (uint32)strtoul(value, NULL, 10); + nextRid = MAX(nextRid, tmp); + } + + value = smbldap_talloc_single_attribute(ldap_struct, entry, + "sambaNextUserRid", mem_ctx); + if (value != NULL) { + uint32 tmp = (uint32)strtoul(value, NULL, 10); + nextRid = MAX(nextRid, tmp); + } + + value = smbldap_talloc_single_attribute(ldap_struct, entry, + "sambaNextGroupRid", mem_ctx); + if (value != NULL) { + uint32 tmp = (uint32)strtoul(value, NULL, 10); + nextRid = MAX(nextRid, tmp); + } + + if (nextRid == 0) { + nextRid = BASE_RID-1; + } + + nextRid += 1; + + smbldap_make_mod(ldap_struct, entry, &mods, "sambaNextRid", + talloc_asprintf(mem_ctx, "%d", nextRid)); + + rc = smbldap_modify(smbldap_state, + smbldap_talloc_dn(mem_ctx, ldap_struct, entry), + mods); + + /* ACCESS_DENIED is used as a placeholder for "the modify failed, + * please retry" */ + + status = (rc == LDAP_SUCCESS) ? NT_STATUS_OK : NT_STATUS_ACCESS_DENIED; + + done: + if (NT_STATUS_IS_OK(status)) { + *rid = nextRid; + } + + ldap_mods_free(mods, True); + talloc_free(mem_ctx); + return status; +} + static BOOL ldapsam_new_rid(struct pdb_methods *methods, uint32 *rid) { - return winbind_allocate_rid(rid); + int i; + + for (i=0; i<10; i++) { + NTSTATUS result = ldapsam_get_new_rid(methods->private_data, + rid); + if (NT_STATUS_IS_OK(result)) { + return True; + } + + if (!NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) { + return False; + } + + /* The ldap update failed (maybe a race condition), retry */ + } + + /* Tried 10 times, fail. */ + return False; } /**********************************************************************