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

Reply via email to