s3-talloc Change TALLOC_P() to talloc()
[nivanova/samba-autobuild/.git] / source3 / libads / ldap_schema.c
index 13a8ab0cb0b448c08d9e3f9f695e8a58abe6eff2..7368be830fb24e55bfd5dd72a9075812706f79d9 100644 (file)
@@ -1,12 +1,12 @@
 /* 
    Unix SMB/CIFS implementation.
    ads (active directory) utility library
-   Copyright (C) Guenther Deschner 2005-2006
+   Copyright (C) Guenther Deschner 2005-2007
    Copyright (C) Gerald (Jerry) Carter 2006
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
+#include "ads.h"
+#include "libads/ldap_schema.h"
+#include "../libcli/ldap/ldap_ndr.h"
 
 #ifdef HAVE_LDAP
 
-ADS_STATUS ads_get_attrnames_by_oids(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
-                                    const char *schema_path,
-                                    const char **OIDs, size_t num_OIDs, 
-                                    char ***OIDs_out, char ***names, size_t *count)
+static ADS_STATUS ads_get_attrnames_by_oids(ADS_STRUCT *ads,
+                                           TALLOC_CTX *mem_ctx,
+                                           const char *schema_path,
+                                           const char **OIDs,
+                                           size_t num_OIDs,
+                                           char ***OIDs_out, char ***names,
+                                           size_t *count)
 {
        ADS_STATUS status;
-       void *res = NULL;
+       LDAPMessage *res = NULL;
        LDAPMessage *msg;
        char *expr = NULL;
        const char *attrs[] = { "lDAPDisplayName", "attributeId", NULL };
@@ -49,13 +54,13 @@ ADS_STATUS ads_get_attrnames_by_oids(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
 
        for (i=0; i<num_OIDs; i++) {
 
-               if ((expr = talloc_asprintf_append(expr, "(attributeId=%s)", 
+               if ((expr = talloc_asprintf_append_buffer(expr, "(attributeId=%s)", 
                                                   OIDs[i])) == NULL) {
                        return ADS_ERROR(LDAP_NO_MEMORY);
                }
        }
 
-       if ((expr = talloc_asprintf_append(expr, ")")) == NULL) {
+       if ((expr = talloc_asprintf_append_buffer(expr, ")")) == NULL) {
                return ADS_ERROR(LDAP_NO_MEMORY);
        }
 
@@ -71,11 +76,11 @@ ADS_STATUS ads_get_attrnames_by_oids(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
                goto out;
        }
 
-       if (((*names) = TALLOC_ARRAY(mem_ctx, char *, *count)) == NULL) {
+       if (((*names) = talloc_array(mem_ctx, char *, *count)) == NULL) {
                status = ADS_ERROR(LDAP_NO_MEMORY);
                goto out;
        }
-       if (((*OIDs_out) = TALLOC_ARRAY(mem_ctx, char *, *count)) == NULL) {
+       if (((*OIDs_out) = talloc_array(mem_ctx, char *, *count)) == NULL) {
                status = ADS_ERROR(LDAP_NO_MEMORY);
                goto out;
        }
@@ -107,55 +112,58 @@ out:
        return status;
 }
 
-const char *ads_get_attrname_by_oid(ADS_STRUCT *ads, const char *schema_path, TALLOC_CTX *mem_ctx, const char * OID)
+const char *ads_get_attrname_by_guid(ADS_STRUCT *ads, 
+                                    const char *schema_path, 
+                                    TALLOC_CTX *mem_ctx, 
+                                    const struct GUID *schema_guid)
 {
        ADS_STATUS rc;
-       int count = 0;
-       void *res = NULL;
+       LDAPMessage *res = NULL;
        char *expr = NULL;
        const char *attrs[] = { "lDAPDisplayName", NULL };
-       char *result;
+       const char *result = NULL;
+       char *guid_bin = NULL;
 
-       if (ads == NULL || mem_ctx == NULL || OID == NULL) {
-               goto failed;
+       if (!ads || !mem_ctx || !schema_guid) {
+               goto done;
        }
 
-       expr = talloc_asprintf(mem_ctx, "(attributeId=%s)", OID);
-       if (expr == NULL) {
-               goto failed;
+       guid_bin = ldap_encode_ndr_GUID(mem_ctx, schema_guid);
+       if (!guid_bin) {
+               goto done;
+       }
+
+       expr = talloc_asprintf(mem_ctx, "(schemaIDGUID=%s)", guid_bin);
+       if (!expr) {
+               goto done;
        }
 
        rc = ads_do_search_retry(ads, schema_path, LDAP_SCOPE_SUBTREE, 
-               expr, attrs, &res);
+                                expr, attrs, &res);
        if (!ADS_ERR_OK(rc)) {
-               goto failed;
+               goto done;
        }
 
-       count = ads_count_replies(ads, res);
-       if (count == 0 || !res) {
-               goto failed;
+       if (ads_count_replies(ads, res) != 1) {
+               goto done;
        }
 
        result = ads_pull_string(ads, mem_ctx, res, "lDAPDisplayName");
-       ads_msgfree(ads, res);
 
+ done:
+       TALLOC_FREE(guid_bin);
+       ads_msgfree(ads, res);
        return result;
        
-failed:
-       DEBUG(0,("ads_get_attrname_by_oid: failed to retrieve name for oid: %s\n", 
-               OID));
-       
-       ads_msgfree(ads, res);
-       return NULL;
 }
 
 /*********************************************************************
 *********************************************************************/
 
-static ADS_STATUS ads_schema_path(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char **schema_path)
+ADS_STATUS ads_schema_path(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char **schema_path)
 {
        ADS_STATUS status;
-       void *res;
+       LDAPMessage *res;
        const char *schema;
        const char *attrs[] = { "schemaNamingContext", NULL };
 
@@ -165,10 +173,12 @@ static ADS_STATUS ads_schema_path(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char **s
        }
 
        if ( (schema = ads_pull_string(ads, mem_ctx, res, "schemaNamingContext")) == NULL ) {
+               ads_msgfree(ads, res);
                return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
        }
 
        if ( (*schema_path = talloc_strdup(mem_ctx, schema)) == NULL ) {
+               ads_msgfree(ads, res);
                return ADS_ERROR(LDAP_NO_MEMORY);
        }
 
@@ -181,32 +191,44 @@ static ADS_STATUS ads_schema_path(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char **s
  * Check for "Services for Unix" or rfc2307 Schema and load some attributes into the ADS_STRUCT
  * @param ads connection to ads server
  * @param enum mapping type
- * @return BOOL status of search (False if one or more attributes couldn't be
+ * @return ADS_STATUS status of search (False if one or more attributes couldn't be
  * found in Active Directory)
  **/ 
-ADS_STATUS ads_check_posix_schema_mapping(ADS_STRUCT *ads, enum wb_posix_mapping map_type) 
+ADS_STATUS ads_check_posix_schema_mapping(TALLOC_CTX *mem_ctx,
+                                         ADS_STRUCT *ads,
+                                         enum wb_posix_mapping map_type,
+                                         struct posix_schema **s ) 
 {
        TALLOC_CTX *ctx = NULL; 
        ADS_STATUS status;
        char **oids_out, **names_out;
        size_t num_names;
        char *schema_path = NULL;
-       ADS_STRUCT *ads_s = ads;
        int i;
+       struct posix_schema *schema = NULL;
 
        const char *oids_sfu[] = {      ADS_ATTR_SFU_UIDNUMBER_OID,
                                        ADS_ATTR_SFU_GIDNUMBER_OID,
                                        ADS_ATTR_SFU_HOMEDIR_OID,
                                        ADS_ATTR_SFU_SHELL_OID,
-                                       ADS_ATTR_SFU_GECOS_OID};
+                                       ADS_ATTR_SFU_GECOS_OID,
+                                       ADS_ATTR_SFU_UID_OID };
+
+       const char *oids_sfu20[] = {    ADS_ATTR_SFU20_UIDNUMBER_OID,
+                                       ADS_ATTR_SFU20_GIDNUMBER_OID,
+                                       ADS_ATTR_SFU20_HOMEDIR_OID,
+                                       ADS_ATTR_SFU20_SHELL_OID,
+                                       ADS_ATTR_SFU20_GECOS_OID,
+                                       ADS_ATTR_SFU20_UID_OID };
 
        const char *oids_rfc2307[] = {  ADS_ATTR_RFC2307_UIDNUMBER_OID,
                                        ADS_ATTR_RFC2307_GIDNUMBER_OID,
                                        ADS_ATTR_RFC2307_HOMEDIR_OID,
                                        ADS_ATTR_RFC2307_SHELL_OID,
-                                       ADS_ATTR_RFC2307_GECOS_OID };
+                                       ADS_ATTR_RFC2307_GECOS_OID,
+                                       ADS_ATTR_RFC2307_UID_OID };
 
-       DEBUG(10,("ads_check_posix_schema_mapping\n"));
+       DEBUG(10,("ads_check_posix_schema_mapping for schema mode: %d\n", map_type));
 
        switch (map_type) {
        
@@ -216,6 +238,7 @@ ADS_STATUS ads_check_posix_schema_mapping(ADS_STRUCT *ads, enum wb_posix_mapping
                        return ADS_ERROR(LDAP_SUCCESS);
 
                case WB_POSIX_MAP_SFU:
+               case WB_POSIX_MAP_SFU20:
                case WB_POSIX_MAP_RFC2307:
                        break;
 
@@ -225,104 +248,109 @@ ADS_STATUS ads_check_posix_schema_mapping(ADS_STRUCT *ads, enum wb_posix_mapping
                        return ADS_ERROR(LDAP_PARAM_ERROR);
        }
 
-       ads->schema.posix_uidnumber_attr = NULL;
-       ads->schema.posix_gidnumber_attr = NULL;
-       ads->schema.posix_homedir_attr = NULL;
-       ads->schema.posix_shell_attr = NULL;
-       ads->schema.posix_gecos_attr = NULL;
-
-       ctx = talloc_init("ads_check_posix_schema_mapping");
-       if (ctx == NULL) {
+       if ( (ctx = talloc_init("ads_check_posix_schema_mapping")) == NULL ) {
                return ADS_ERROR(LDAP_NO_MEMORY);
        }
 
-       /* establish a new ldap tcp session if necessary */
-
-       if (!ads->ld) {
-               if ((ads_s = ads_init(ads->server.realm, ads->server.workgroup, 
-                                     ads->server.ldap_server)) == NULL) {
-                       status = ADS_ERROR(LDAP_SERVER_DOWN);
-                       goto done;
-               }
-
-               ads_s->auth.flags = ADS_AUTH_ANON_BIND;
-               status = ads_connect(ads_s);
-               if (!ADS_ERR_OK(status)) {
-                       goto done;
-               }
+       if ( (schema = talloc(mem_ctx, struct posix_schema)) == NULL ) {
+               TALLOC_FREE( ctx );
+               return ADS_ERROR(LDAP_NO_MEMORY);
        }
-
+       
        status = ads_schema_path(ads, ctx, &schema_path);
        if (!ADS_ERR_OK(status)) {
                DEBUG(3,("ads_check_posix_mapping: Unable to retrieve schema DN!\n"));
                goto done;
        }
 
-       if (map_type == WB_POSIX_MAP_SFU) {
-               status = ads_get_attrnames_by_oids(ads, ctx, schema_path, oids_sfu, 
-                                                  ARRAY_SIZE(oids_sfu), 
-                                                  &oids_out, &names_out, &num_names);
-       } else { 
-               status = ads_get_attrnames_by_oids(ads, ctx, schema_path, oids_rfc2307, 
-                                                  ARRAY_SIZE(oids_rfc2307), 
-                                                  &oids_out, &names_out, &num_names);
+       switch (map_type) {
+               case WB_POSIX_MAP_SFU:
+                       status = ads_get_attrnames_by_oids(ads, ctx, schema_path, oids_sfu, 
+                                                          ARRAY_SIZE(oids_sfu), 
+                                                          &oids_out, &names_out, &num_names);
+                       break;
+               case WB_POSIX_MAP_SFU20:
+                       status = ads_get_attrnames_by_oids(ads, ctx, schema_path, oids_sfu20, 
+                                                          ARRAY_SIZE(oids_sfu20), 
+                                                          &oids_out, &names_out, &num_names);
+                       break;
+               case WB_POSIX_MAP_RFC2307:
+                       status = ads_get_attrnames_by_oids(ads, ctx, schema_path, oids_rfc2307, 
+                                                          ARRAY_SIZE(oids_rfc2307), 
+                                                          &oids_out, &names_out, &num_names);
+                       break;
+               default:
+                       status = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+                       break;
        }
 
        if (!ADS_ERR_OK(status)) {
                DEBUG(3,("ads_check_posix_schema_mapping: failed %s\n", 
                        ads_errstr(status)));
                goto done;
-       } 
-       
-       DEBUG(10,("ads_check_posix_schema_mapping: query succeeded, identified: %s\n",
-               wb_posix_map_str(map_type)));
+       }
 
        for (i=0; i<num_names; i++) {
 
                DEBUGADD(10,("\tOID %s has name: %s\n", oids_out[i], names_out[i]));
 
                if (strequal(ADS_ATTR_RFC2307_UIDNUMBER_OID, oids_out[i]) ||
-                   strequal(ADS_ATTR_SFU_UIDNUMBER_OID, oids_out[i])) {
-                       ads->schema.posix_uidnumber_attr = SMB_STRDUP(names_out[i]);
+                   strequal(ADS_ATTR_SFU_UIDNUMBER_OID, oids_out[i]) ||
+                   strequal(ADS_ATTR_SFU20_UIDNUMBER_OID, oids_out[i])) {
+                       schema->posix_uidnumber_attr = talloc_strdup(schema, names_out[i]);
+                       continue;                      
                }
+
                if (strequal(ADS_ATTR_RFC2307_GIDNUMBER_OID, oids_out[i]) ||
-                   strequal(ADS_ATTR_SFU_GIDNUMBER_OID, oids_out[i])) {
-                       ads->schema.posix_gidnumber_attr = SMB_STRDUP(names_out[i]);
+                   strequal(ADS_ATTR_SFU_GIDNUMBER_OID, oids_out[i]) ||
+                   strequal(ADS_ATTR_SFU20_GIDNUMBER_OID, oids_out[i])) {
+                       schema->posix_gidnumber_attr = talloc_strdup(schema, names_out[i]);
+                       continue;               
                }
+
                if (strequal(ADS_ATTR_RFC2307_HOMEDIR_OID, oids_out[i]) ||
-                   strequal(ADS_ATTR_SFU_HOMEDIR_OID, oids_out[i])) {
-                       ads->schema.posix_homedir_attr = SMB_STRDUP(names_out[i]);
+                   strequal(ADS_ATTR_SFU_HOMEDIR_OID, oids_out[i]) ||
+                   strequal(ADS_ATTR_SFU20_HOMEDIR_OID, oids_out[i])) {
+                       schema->posix_homedir_attr = talloc_strdup(schema, names_out[i]);
+                       continue;                       
                }
+
                if (strequal(ADS_ATTR_RFC2307_SHELL_OID, oids_out[i]) ||
-                   strequal(ADS_ATTR_SFU_SHELL_OID, oids_out[i])) {
-                       ads->schema.posix_shell_attr = SMB_STRDUP(names_out[i]);
+                   strequal(ADS_ATTR_SFU_SHELL_OID, oids_out[i]) ||
+                   strequal(ADS_ATTR_SFU20_SHELL_OID, oids_out[i])) {
+                       schema->posix_shell_attr = talloc_strdup(schema, names_out[i]);
+                       continue;                       
                }
+
                if (strequal(ADS_ATTR_RFC2307_GECOS_OID, oids_out[i]) ||
-                   strequal(ADS_ATTR_SFU_GECOS_OID, oids_out[i])) {
-                       ads->schema.posix_gecos_attr = SMB_STRDUP(names_out[i]);
+                   strequal(ADS_ATTR_SFU_GECOS_OID, oids_out[i]) ||
+                   strequal(ADS_ATTR_SFU20_GECOS_OID, oids_out[i])) {
+                       schema->posix_gecos_attr = talloc_strdup(schema, names_out[i]);
+               }
+
+               if (strequal(ADS_ATTR_RFC2307_UID_OID, oids_out[i]) ||
+                   strequal(ADS_ATTR_SFU_UID_OID, oids_out[i]) ||
+                   strequal(ADS_ATTR_SFU20_UID_OID, oids_out[i])) {
+                       schema->posix_uid_attr = talloc_strdup(schema, names_out[i]);
                }
        }
 
-       if (!ads->schema.posix_uidnumber_attr ||
-           !ads->schema.posix_gidnumber_attr ||
-           !ads->schema.posix_homedir_attr ||
-           !ads->schema.posix_shell_attr ||
-           !ads->schema.posix_gecos_attr) {
+       if (!schema->posix_uidnumber_attr ||
+           !schema->posix_gidnumber_attr ||
+           !schema->posix_homedir_attr ||
+           !schema->posix_shell_attr ||
+           !schema->posix_gecos_attr) {
                status = ADS_ERROR(LDAP_NO_MEMORY);
+               TALLOC_FREE( schema );          
                goto done;
        }
+
+       *s = schema;
        
        status = ADS_ERROR(LDAP_SUCCESS);
        
-       ads->schema.map_type = map_type;
 done:
-       /* free any temporary ads connections */
-       if (ads_s != ads) {
-               ads_destroy(&ads_s);
-       }
-       if (ctx) {
-               talloc_destroy(ctx);
-       }
+       TALLOC_FREE(ctx);
 
        return status;
 }