Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into pac-verify
authorAndrew Bartlett <abartlet@samba.org>
Tue, 26 Aug 2008 06:26:08 +0000 (16:26 +1000)
committerAndrew Bartlett <abartlet@samba.org>
Tue, 26 Aug 2008 06:26:08 +0000 (16:26 +1000)
(This used to be commit b706708210a05d6f10474a3cd2bbc550704d4356)

138 files changed:
.gitignore
source4/auth/gensec/gensec.h
source4/auth/gensec/gensec_gssapi.c
source4/auth/gensec/spnego.c
source4/auth/gensec/spnego_parse.c
source4/build/m4/check_path.m4
source4/cldap_server/netlogon.c
source4/dsdb/common/flags.h
source4/dsdb/config.mk
source4/dsdb/repl/drepl_out_helpers.c
source4/dsdb/samdb/ldb_modules/anr.c
source4/dsdb/samdb/ldb_modules/linked_attributes.c
source4/dsdb/samdb/ldb_modules/normalise.c
source4/dsdb/samdb/ldb_modules/partition.c
source4/dsdb/samdb/ldb_modules/samldb.c
source4/dsdb/samdb/ldb_modules/schema_fsmo.c
source4/dsdb/samdb/ldb_modules/schema_syntax.c
source4/dsdb/samdb/ldb_modules/simple_ldap_map.c
source4/dsdb/samdb/ldb_modules/tests/samba3sam.py
source4/dsdb/samdb/samdb.h
source4/dsdb/schema/schema.h
source4/dsdb/schema/schema_constructed.c [deleted file]
source4/dsdb/schema/schema_description.c [new file with mode: 0644]
source4/dsdb/schema/schema_init.c
source4/dsdb/schema/schema_query.c [new file with mode: 0644]
source4/dsdb/schema/schema_set.c [new file with mode: 0644]
source4/dsdb/schema/schema_syntax.c
source4/heimdal/lib/gssapi/krb5/accept_sec_context.c
source4/heimdal/lib/gssapi/krb5/cfx.c
source4/heimdal/lib/gssapi/krb5/gsskrb5-private.h
source4/heimdal/lib/gssapi/krb5/unwrap.c
source4/heimdal/lib/gssapi/krb5/wrap.c
source4/kdc/hdb-ldb.c
source4/kdc/pac-glue.c
source4/lib/basic.mk
source4/lib/charset/charset.h
source4/lib/charset/iconv.c
source4/lib/charset/util_unistr.c
source4/lib/compression/lzxpress.c [new file with mode: 0644]
source4/lib/compression/lzxpress.h [new file with mode: 0644]
source4/lib/ldb-samba/config.mk
source4/lib/ldb-samba/ldif_handlers.c
source4/lib/ldb-samba/ldif_handlers.h [new file with mode: 0644]
source4/lib/ldb/common/attrib_handlers.c
source4/lib/ldb/common/ldb_attributes.c
source4/lib/ldb/common/ldb_dn.c
source4/lib/ldb/common/ldb_msg.c
source4/lib/ldb/common/ldb_utf8.c
source4/lib/ldb/include/ldb.h
source4/lib/ldb/include/ldb_private.h
source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c
source4/lib/ldb/ldb_sqlite3/schema
source4/lib/ldb/ldb_tdb/ldb_index.c
source4/lib/ldb/modules/operational.c
source4/lib/ldb/tests/python/ldap.py
source4/lib/ldb/tests/test-attribs.ldif
source4/lib/ldb/tests/test-index.ldif
source4/lib/ldb/tools/ldbtest.c
source4/lib/ldb_wrap.c
source4/lib/ldb_wrap.h
source4/lib/util/data_blob.c
source4/lib/util/util_ldb.c
source4/lib/util/util_ldb.h
source4/lib/zlib/adler32.c
source4/lib/zlib/compress.c
source4/lib/zlib/crc32.c
source4/lib/zlib/deflate.c
source4/lib/zlib/gzio.c
source4/lib/zlib/infback.c
source4/lib/zlib/inffast.c
source4/lib/zlib/inflate.c
source4/lib/zlib/trees.c
source4/lib/zlib/uncompr.c
source4/lib/zlib/zlib.h
source4/lib/zlib/zutil.h
source4/libcli/config.mk
source4/libcli/drsblobs.c [new file with mode: 0644]
source4/libcli/drsblobs.h [new file with mode: 0644]
source4/libcli/raw/smb.h
source4/libcli/security/dom_sid.c
source4/libcli/smb2/connect.c
source4/libcli/smb2/signing.c
source4/libcli/smb2/smb2.h
source4/libcli/smb2/transport.c
source4/libnet/libnet_become_dc.c
source4/librpc/config.mk
source4/librpc/idl/dcerpc.idl
source4/librpc/idl/drsblobs.idl
source4/librpc/idl/drsuapi.idl
source4/librpc/idl/krb5pac.idl
source4/librpc/idl/lsa.idl
source4/librpc/idl/nbt.idl
source4/librpc/idl/security.idl
source4/librpc/ndr/ndr.c
source4/librpc/ndr/ndr_compression.c
source4/librpc/ndr/ndr_drsuapi.c
source4/librpc/rpc/dcerpc.c
source4/ntp_signd/ntp_signd.c
source4/ntvfs/ntvfs_generic.c
source4/ntvfs/posix/pvfs_open.c
source4/pidl/lib/Parse/Pidl/NDR.pm
source4/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm
source4/pidl/tests/samba-ndr.pl
source4/pidl/tests/samba3-cli.pl
source4/rpc_server/dcerpc_server.c
source4/rpc_server/dcesrv_auth.c
source4/rpc_server/lsa/dcesrv_lsa.c
source4/scripting/python/samba/provision.py
source4/setup/mmr_serverids.conf [new file with mode: 0644]
source4/setup/mmr_syncrepl.conf [new file with mode: 0644]
source4/setup/provision-backend
source4/setup/provision_index.ldif [deleted file]
source4/setup/provision_init.ldif
source4/setup/provision_templates.ldif
source4/setup/provision_templates_init.ldif [new file with mode: 0644]
source4/setup/provision_users.ldif
source4/setup/schema-map-openldap-2.3
source4/setup/schema.ldif
source4/setup/slapd.conf
source4/setup/tests/blackbox_provision-backend.sh
source4/smb_server/smb2/receive.c
source4/smb_server/smb2/smb2_server.h
source4/torture/auth/pac.c
source4/torture/ldap/cldap.c
source4/torture/nbt/dgram.c
source4/torture/nbt/winsreplication.c
source4/torture/raw/offline.c
source4/torture/raw/open.c
source4/torture/rpc/atsvc.c
source4/torture/rpc/dssync.c
source4/torture/rpc/lsa.c
source4/torture/smb2/create.c
source4/utils/ad2oLschema.c
source4/utils/config.mk
source4/utils/oLschema2ldif.c
source4/utils/schema_convert.c [deleted file]
source4/utils/schema_convert.h [deleted file]
testprogs/ejs/minschema.js

index 1e574f00597ccd17a924c4ad28e0de31da73fc14..a216677f4a5df1f64866944b1915b9d440a54b92 100644 (file)
@@ -55,7 +55,7 @@ source/ldap_server/proto.h
 source/lib/db_wrap_proto.h
 source/lib/charset/charset_proto.h
 source/lib/cmdline/credentials.h
-source/lib/ldb/samba/ldif_handlers.h
+source/lib/ldb/samba/ldif_handlers_proto.h
 source/lib/registry/regf.h
 source/lib/registry/tdr_regf.c
 source/lib/registry/tdr_regf.h
index 2a89e67ed2ae46a3b7125b901049ebe4c162d13a..2830297ffe4043fc31ae661aac1f5d90b27279c0 100644 (file)
@@ -53,6 +53,7 @@ struct gensec_target {
 #define GENSEC_FEATURE_ASYNC_REPLIES   0x00000010
 #define GENSEC_FEATURE_DATAGRAM_MODE   0x00000020
 #define GENSEC_FEATURE_SIGN_PKT_HEADER 0x00000040
+#define GENSEC_FEATURE_NEW_SPNEGO      0x00000080
 
 /* GENSEC mode */
 enum gensec_role
index 1541c88e0784714741e6bf97b12511f0860a1f6d..20d08078be401620c509fcdce294954b87dd1636 100644 (file)
@@ -65,6 +65,7 @@ struct gensec_gssapi_state {
        struct smb_krb5_context *smb_krb5_context;
        struct gssapi_creds_container *client_cred;
        struct gssapi_creds_container *server_cred;
+       gss_krb5_lucid_context_v1_t *lucid;
 
        gss_cred_id_t delegated_cred_handle;
 
@@ -143,9 +144,45 @@ static int gensec_gssapi_destructor(struct gensec_gssapi_state *gensec_gssapi_st
        if (gensec_gssapi_state->client_name != GSS_C_NO_NAME) {
                maj_stat = gss_release_name(&min_stat, &gensec_gssapi_state->client_name);
        }
+
+       if (gensec_gssapi_state->lucid) {
+               gss_krb5_free_lucid_sec_context(&min_stat, gensec_gssapi_state->lucid);
+       }
+
        return 0;
 }
 
+static NTSTATUS gensec_gssapi_init_lucid(struct gensec_gssapi_state *gensec_gssapi_state)
+{
+       OM_uint32 maj_stat, min_stat;
+
+       if (gensec_gssapi_state->lucid) {
+               return NT_STATUS_OK;
+       }
+
+       maj_stat = gss_krb5_export_lucid_sec_context(&min_stat,
+                                                    &gensec_gssapi_state->gssapi_context,
+                                                    1,
+                                                    (void **)&gensec_gssapi_state->lucid);
+       if (maj_stat != GSS_S_COMPLETE) {
+               DEBUG(0,("gensec_gssapi_init_lucid: %s\n",
+                       gssapi_error_string(gensec_gssapi_state,
+                                           maj_stat, min_stat,
+                                           gensec_gssapi_state->gss_oid)));
+               return NT_STATUS_INTERNAL_ERROR;
+       }
+
+       if (gensec_gssapi_state->lucid->version != 1) {
+               DEBUG(0,("gensec_gssapi_init_lucid: lucid version[%d] != 1\n",
+                       gensec_gssapi_state->lucid->version));
+               gss_krb5_free_lucid_sec_context(&min_stat, gensec_gssapi_state->lucid);
+               gensec_gssapi_state->lucid = NULL;
+               return NT_STATUS_INTERNAL_ERROR;
+       }
+
+       return NT_STATUS_OK;
+}
+
 static NTSTATUS gensec_gssapi_start(struct gensec_security *gensec_security)
 {
        struct gensec_gssapi_state *gensec_gssapi_state;
@@ -169,6 +206,7 @@ static NTSTATUS gensec_gssapi_start(struct gensec_security *gensec_security)
        gensec_gssapi_state->gssapi_context = GSS_C_NO_CONTEXT;
        gensec_gssapi_state->server_name = GSS_C_NO_NAME;
        gensec_gssapi_state->client_name = GSS_C_NO_NAME;
+       gensec_gssapi_state->lucid = NULL;
 
        /* TODO: Fill in channel bindings */
        gensec_gssapi_state->input_chan_bindings = GSS_C_NO_CHANNEL_BINDINGS;
@@ -1083,10 +1121,10 @@ static NTSTATUS gensec_gssapi_check_packet(struct gensec_security *gensec_securi
 
        if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
                input_message.length = pdu_length;
-               input_message.value = whole_pdu;
+               input_message.value = discard_const(whole_pdu);
        } else {
                input_message.length = length;
-               input_message.value = data;
+               input_message.value = discard_const(data);
        }
 
        input_token.length = sig->length;
@@ -1139,6 +1177,31 @@ static bool gensec_gssapi_have_feature(struct gensec_security *gensec_security,
        if (feature & GENSEC_FEATURE_DCE_STYLE) {
                return gensec_gssapi_state->got_flags & GSS_C_DCE_STYLE;
        }
+       if (feature & GENSEC_FEATURE_NEW_SPNEGO) {
+               NTSTATUS status;
+
+               if (!(gensec_gssapi_state->got_flags & GSS_C_INTEG_FLAG)) {
+                       return false;
+               }
+
+               if (lp_parm_bool(gensec_security->lp_ctx, NULL, "gensec_gssapi", "force_new_spnego", false)) {
+                       return true;
+               }
+               if (lp_parm_bool(gensec_security->lp_ctx, NULL, "gensec_gssapi", "disable_new_spnego", false)) {
+                       return false;
+               }
+
+               status = gensec_gssapi_init_lucid(gensec_gssapi_state);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return false;
+               }
+
+               if (gensec_gssapi_state->lucid->protocol == 1) {
+                       return true;
+               }
+
+               return false;
+       }
        /* We can always do async (rather than strict request/reply) packets.  */
        if (feature & GENSEC_FEATURE_ASYNC_REPLIES) {
                return true;
@@ -1165,20 +1228,24 @@ static NTSTATUS gensec_gssapi_session_key(struct gensec_security *gensec_securit
                return NT_STATUS_OK;
        }
 
-       maj_stat = gsskrb5_get_initiator_subkey(&min_stat, 
-                                               gensec_gssapi_state->gssapi_context,
-                                               &subkey);
+       maj_stat = gsskrb5_get_subkey(&min_stat,
+                                     gensec_gssapi_state->gssapi_context,
+                                     &subkey);
        if (maj_stat != 0) {
                DEBUG(1, ("NO session key for this mech\n"));
                return NT_STATUS_NO_USER_SESSION_KEY;
        }
        
-       DEBUG(10, ("Got KRB5 session key of length %d\n",  
-                  (int)KRB5_KEY_LENGTH(subkey)));
-       gensec_gssapi_state->session_key = data_blob_talloc(gensec_gssapi_state, 
-                                                           KRB5_KEY_DATA(subkey), KRB5_KEY_LENGTH(subkey));
+       DEBUG(10, ("Got KRB5 session key of length %d%s\n",
+                  (int)KRB5_KEY_LENGTH(subkey),
+                  (gensec_gssapi_state->sasl_state == STAGE_DONE)?" (done)":""));
+       *session_key = data_blob_talloc(gensec_gssapi_state,
+                                       KRB5_KEY_DATA(subkey), KRB5_KEY_LENGTH(subkey));
        krb5_free_keyblock(gensec_gssapi_state->smb_krb5_context->krb5_context, subkey);
-       *session_key = gensec_gssapi_state->session_key;
+       if (gensec_gssapi_state->sasl_state == STAGE_DONE) {
+               /* only cache in the done stage */
+               gensec_gssapi_state->session_key = *session_key;
+       }
        dump_data_pw("KRB5 Session Key:\n", session_key->data, session_key->length);
 
        return NT_STATUS_OK;
@@ -1386,8 +1453,7 @@ size_t gensec_gssapi_sig_size(struct gensec_security *gensec_security, size_t da
 {
        struct gensec_gssapi_state *gensec_gssapi_state
                = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
-       OM_uint32 maj_stat, min_stat;
-       gss_krb5_lucid_context_v1_t *lucid = NULL;
+       NTSTATUS status;
 
        if (gensec_gssapi_state->sig_size) {
                return gensec_gssapi_state->sig_size;
@@ -1399,29 +1465,23 @@ size_t gensec_gssapi_sig_size(struct gensec_security *gensec_security, size_t da
                gensec_gssapi_state->sig_size = 37;
        }
 
-       maj_stat = gss_krb5_export_lucid_sec_context(&min_stat,
-                                                    &gensec_gssapi_state->gssapi_context,
-                                                    1, (void **)&lucid);
-       if (maj_stat != GSS_S_COMPLETE) {
-               return gensec_gssapi_state->sig_size;
-       }
-
-       if (lucid->version != 1) {
+       status = gensec_gssapi_init_lucid(gensec_gssapi_state);
+       if (!NT_STATUS_IS_OK(status)) {
                return gensec_gssapi_state->sig_size;
        }
 
-       if (lucid->protocol == 1) {
+       if (gensec_gssapi_state->lucid->protocol == 1) {
                if (gensec_gssapi_state->got_flags & GSS_C_CONF_FLAG) {
                        /*
                         * TODO: windows uses 76 here, but we don't know
                         *       gss_wrap works with aes keys yet
                         */
-                       gensec_gssapi_state->sig_size = 60;
+                       gensec_gssapi_state->sig_size = 76;
                } else {
                        gensec_gssapi_state->sig_size = 28;
                }
-       } else if (lucid->protocol == 0) {
-               switch (lucid->rfc1964_kd.ctx_key.type) {
+       } else if (gensec_gssapi_state->lucid->protocol == 0) {
+               switch (gensec_gssapi_state->lucid->rfc1964_kd.ctx_key.type) {
                case KEYTYPE_DES:
                case KEYTYPE_ARCFOUR:
                case KEYTYPE_ARCFOUR_56:
@@ -1441,8 +1501,6 @@ size_t gensec_gssapi_sig_size(struct gensec_security *gensec_security, size_t da
                }
        }
 
-       gss_krb5_free_lucid_sec_context(&min_stat, lucid);
-
        return gensec_gssapi_state->sig_size;
 }
 
index 1544326bb1c06c45f0a105dcf5d40cda440d1c61..1855e0583d71af366fadd22b4f150ff15fc42076 100644 (file)
@@ -5,6 +5,7 @@
    
    Copyright (C) Jim McDonough <jmcd@us.ibm.com>      2003
    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
+   Copyright (C) Stefan Metzmacher <metze@samba.org>  2004-2008
 
    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
@@ -44,6 +45,8 @@ struct spnego_state {
        bool no_response_expected;
 
        const char *neg_oid;
+
+       DATA_BLOB mech_types;
 };
 
 
@@ -60,6 +63,7 @@ static NTSTATUS gensec_spnego_client_start(struct gensec_security *gensec_securi
        spnego_state->state_position = SPNEGO_CLIENT_START;
        spnego_state->sub_sec_security = NULL;
        spnego_state->no_response_expected = false;
+       spnego_state->mech_types = data_blob(NULL, 0);
 
        gensec_security->private_data = spnego_state;
        return NT_STATUS_OK;
@@ -78,6 +82,7 @@ static NTSTATUS gensec_spnego_server_start(struct gensec_security *gensec_securi
        spnego_state->state_position = SPNEGO_SERVER_START;
        spnego_state->sub_sec_security = NULL;
        spnego_state->no_response_expected = false;
+       spnego_state->mech_types = data_blob(NULL, 0);
 
        gensec_security->private_data = spnego_state;
        return NT_STATUS_OK;
@@ -392,12 +397,22 @@ static NTSTATUS gensec_spnego_parse_negTokenInit(struct gensec_security *gensec_
        int i;
        NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
        DATA_BLOB null_data_blob = data_blob(NULL,0);
+       bool ok;
 
        const struct gensec_security_ops_wrapper *all_sec
                = gensec_security_by_oid_list(gensec_security, 
                                              out_mem_ctx, 
                                              mechType,
                                              GENSEC_OID_SPNEGO);
+
+       ok = spnego_write_mech_types(spnego_state,
+                                    mechType,
+                                    &spnego_state->mech_types);
+       if (!ok) {
+               DEBUG(1, ("SPNEGO: Failed to write mechTypes\n"));
+               return NT_STATUS_NO_MEMORY;
+       }
+
        if (spnego_state->state_position == SPNEGO_SERVER_START) {
                for (i=0; all_sec && all_sec[i].op; i++) {
                        /* optomisitic token */
@@ -556,6 +571,9 @@ static NTSTATUS gensec_spnego_create_negTokenInit(struct gensec_security *gensec
                                              GENSEC_OID_SPNEGO);
        for (i=0; all_sec && all_sec[i].op; i++) {
                struct spnego_data spnego_out;
+               const char **send_mech_types;
+               bool ok;
+
                nt_status = gensec_subcontext_start(spnego_state,
                                                    gensec_security,
                                                    &spnego_state->sub_sec_security);
@@ -591,10 +609,20 @@ static NTSTATUS gensec_spnego_create_negTokenInit(struct gensec_security *gensec
                }
 
                spnego_out.type = SPNEGO_NEG_TOKEN_INIT;
-               
+
+               send_mech_types = gensec_security_oids_from_ops_wrapped(out_mem_ctx,
+                                                                       &all_sec[i]);
+
+               ok = spnego_write_mech_types(spnego_state,
+                                            send_mech_types,
+                                            &spnego_state->mech_types);
+               if (!ok) {
+                       DEBUG(1, ("SPNEGO: Failed to write mechTypes\n"));
+                       return NT_STATUS_NO_MEMORY;
+               }
+
                /* List the remaining mechs as options */
-               spnego_out.negTokenInit.mechTypes = gensec_security_oids_from_ops_wrapped(out_mem_ctx, 
-                                                                                         &all_sec[i]);
+               spnego_out.negTokenInit.mechTypes = send_mech_types;
                spnego_out.negTokenInit.reqFlags = 0;
                
                if (spnego_state->state_position == SPNEGO_SERVER_START) {
@@ -644,7 +672,9 @@ static NTSTATUS gensec_spnego_server_negTokenTarg(struct gensec_security *gensec
                                                  struct spnego_state *spnego_state,
                                                  TALLOC_CTX *out_mem_ctx, 
                                                  NTSTATUS nt_status,
-                                                 const DATA_BLOB unwrapped_out, DATA_BLOB *out) 
+                                                 const DATA_BLOB unwrapped_out,
+                                                 DATA_BLOB mech_list_mic,
+                                                 DATA_BLOB *out)
 {
        struct spnego_data spnego_out;
        DATA_BLOB null_data_blob = data_blob(NULL, 0);
@@ -664,6 +694,7 @@ static NTSTATUS gensec_spnego_server_negTokenTarg(struct gensec_security *gensec
                        spnego_out.negTokenTarg.supportedMech = spnego_state->neg_oid;
                }
                spnego_out.negTokenTarg.negResult = SPNEGO_ACCEPT_COMPLETED;
+               spnego_out.negTokenTarg.mechListMIC = mech_list_mic;
                spnego_state->state_position = SPNEGO_DONE;
        } else {
                spnego_out.negTokenTarg.negResult = SPNEGO_REJECT;
@@ -687,6 +718,7 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA
 {
        struct spnego_state *spnego_state = (struct spnego_state *)gensec_security->private_data;
        DATA_BLOB null_data_blob = data_blob(NULL, 0);
+       DATA_BLOB mech_list_mic = data_blob(NULL, 0);
        DATA_BLOB unwrapped_out = data_blob(NULL, 0);
        struct spnego_data spnego_out;
        struct spnego_data spnego;
@@ -737,7 +769,8 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA
                                                                      spnego_state,
                                                                      out_mem_ctx,
                                                                      nt_status,
-                                                                     unwrapped_out, 
+                                                                     unwrapped_out,
+                                                                     null_data_blob,
                                                                      out);
                        
                        spnego_free_data(&spnego);
@@ -829,6 +862,8 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA
        case SPNEGO_SERVER_TARG:
        {
                NTSTATUS nt_status;
+               bool new_spnego = false;
+
                if (!in.length) {
                        return NT_STATUS_INVALID_PARAMETER;
                }
@@ -860,12 +895,40 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA
                                          out_mem_ctx, 
                                          spnego.negTokenTarg.responseToken,
                                          &unwrapped_out);
+               if (NT_STATUS_IS_OK(nt_status) && spnego.negTokenTarg.mechListMIC.length > 0) {
+                       new_spnego = true;
+                       nt_status = gensec_check_packet(spnego_state->sub_sec_security,
+                                                       out_mem_ctx,
+                                                       spnego_state->mech_types.data,
+                                                       spnego_state->mech_types.length,
+                                                       spnego_state->mech_types.data,
+                                                       spnego_state->mech_types.length,
+                                                       &spnego.negTokenTarg.mechListMIC);
+                       if (!NT_STATUS_IS_OK(nt_status)) {
+                               DEBUG(2,("GENSEC SPNEGO: failed to verify mechListMIC: %s\n",
+                                       nt_errstr(nt_status)));
+                       }
+               }
+               if (NT_STATUS_IS_OK(nt_status) && new_spnego) {
+                       nt_status = gensec_sign_packet(spnego_state->sub_sec_security,
+                                                      out_mem_ctx,
+                                                      spnego_state->mech_types.data,
+                                                      spnego_state->mech_types.length,
+                                                      spnego_state->mech_types.data,
+                                                      spnego_state->mech_types.length,
+                                                      &mech_list_mic);
+                       if (!NT_STATUS_IS_OK(nt_status)) {
+                               DEBUG(2,("GENSEC SPNEGO: failed to sign mechListMIC: %s\n",
+                                       nt_errstr(nt_status)));
+                       }
+               }
 
                nt_status = gensec_spnego_server_negTokenTarg(gensec_security,
                                                              spnego_state,
                                                              out_mem_ctx, 
                                                              nt_status,
-                                                             unwrapped_out, 
+                                                             unwrapped_out,
+                                                             mech_list_mic,
                                                              out);
                
                spnego_free_data(&spnego);
@@ -940,12 +1003,44 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA
                        } else {
                                nt_status = NT_STATUS_OK;
                        }
+                       if (NT_STATUS_IS_OK(nt_status) && spnego.negTokenTarg.mechListMIC.length > 0) {
+                               nt_status = gensec_check_packet(spnego_state->sub_sec_security,
+                                                               out_mem_ctx,
+                                                               spnego_state->mech_types.data,
+                                                               spnego_state->mech_types.length,
+                                                               spnego_state->mech_types.data,
+                                                               spnego_state->mech_types.length,
+                                                               &spnego.negTokenTarg.mechListMIC);
+                               if (!NT_STATUS_IS_OK(nt_status)) {
+                                       DEBUG(2,("GENSEC SPNEGO: failed to verify mechListMIC: %s\n",
+                                               nt_errstr(nt_status)));
+                               }
+                       }
                } else {
+                       bool new_spnego = false;
+
                        nt_status = gensec_update(spnego_state->sub_sec_security,
                                                  out_mem_ctx, 
                                                  spnego.negTokenTarg.responseToken, 
                                                  &unwrapped_out);
 
+                       if (NT_STATUS_IS_OK(nt_status)) {
+                               new_spnego = gensec_have_feature(spnego_state->sub_sec_security,
+                                                                GENSEC_FEATURE_NEW_SPNEGO);
+                       }
+                       if (NT_STATUS_IS_OK(nt_status) && new_spnego) {
+                               nt_status = gensec_sign_packet(spnego_state->sub_sec_security,
+                                                              out_mem_ctx,
+                                                              spnego_state->mech_types.data,
+                                                              spnego_state->mech_types.length,
+                                                              spnego_state->mech_types.data,
+                                                              spnego_state->mech_types.length,
+                                                              &mech_list_mic);
+                               if (!NT_STATUS_IS_OK(nt_status)) {
+                                       DEBUG(2,("GENSEC SPNEGO: failed to sign mechListMIC: %s\n",
+                                               nt_errstr(nt_status)));
+                               }
+                       }
                        if (NT_STATUS_IS_OK(nt_status)) {
                                spnego_state->no_response_expected = true;
                        }
@@ -967,7 +1062,7 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA
                        spnego_out.negTokenTarg.negResult = SPNEGO_NONE_RESULT;
                        spnego_out.negTokenTarg.supportedMech = NULL;
                        spnego_out.negTokenTarg.responseToken = unwrapped_out;
-                       spnego_out.negTokenTarg.mechListMIC = null_data_blob;
+                       spnego_out.negTokenTarg.mechListMIC = mech_list_mic;
                        
                        if (spnego_write_data(out_mem_ctx, out, &spnego_out) == -1) {
                                DEBUG(1, ("Failed to write SPNEGO reply to NEG_TOKEN_TARG\n"));
index 8012a83ba8d59149e9d49355f90e89bb5696828a..5ea8cf71002b9d386b3909e5d8a85e3242da6062 100644 (file)
@@ -374,3 +374,35 @@ out:
        return ret;
 }
 
+bool spnego_write_mech_types(TALLOC_CTX *mem_ctx,
+                            const char **mech_types,
+                            DATA_BLOB *blob)
+{
+       struct asn1_data *asn1 = asn1_init(mem_ctx);
+
+       /* Write mechTypes */
+       if (mech_types && *mech_types) {
+               int i;
+
+               asn1_push_tag(asn1, ASN1_SEQUENCE(0));
+               for (i = 0; mech_types[i]; i++) {
+                       asn1_write_OID(asn1, mech_types[i]);
+               }
+               asn1_pop_tag(asn1);
+       }
+
+       if (asn1->has_error) {
+               asn1_free(asn1);
+               return false;
+       }
+
+       *blob = data_blob_talloc(mem_ctx, asn1->data, asn1->length);
+       if (blob->length != asn1->length) {
+               asn1_free(asn1);
+               return false;
+       }
+
+       asn1_free(asn1);
+
+       return true;
+}
index a209a4b85a858c1c59c460bb7a7ce9cd40da147d..c45a80363375335eb63bb891d1981a31cf7fd4dd 100644 (file)
@@ -24,7 +24,7 @@ winbindd_privileged_socket_dir="${localstatedir}/lib/winbindd_privileged"
 ntp_signd_socket_dir="${localstatedir}/run/ntp_signd"
 
 AC_ARG_WITH(fhs, 
-[  --with-fhs              Use FHS-compliant paths (default=no)],
+[AS_HELP_STRING([--with-fhs],[Use FHS-compliant paths (default=no)])],
     lockdir="${localstatedir}/lib/samba"
     piddir="${localstatedir}/run/samba"
     logfilebase="${localstatedir}/log/samba"
@@ -41,7 +41,7 @@ AC_ARG_WITH(fhs,
 #################################################
 # set private directory location
 AC_ARG_WITH(privatedir,
-[  --with-privatedir=DIR   Where to put sam.ldb and other private files containing key material ($ac_default_prefix/private)],
+[AS_HELP_STRING([--with-privatedir=DIR],[Where to put sam.ldb and other private files containing key material ($ac_default_prefix/private)])],
 [ case "$withval" in
   yes|no)
   #
@@ -57,7 +57,7 @@ AC_ARG_WITH(privatedir,
 #################################################
 # set where the winbindd socket should be put
 AC_ARG_WITH(winbindd-socket-dir,
-[  --with-winbindd-socket-dir=DIR   Where to put the winbindd socket ($winbindd_socket_dir)],
+[AS_HELP_STRING([--with-winbindd-socket-dir=DIR],[Where to put the winbindd socket ($winbindd_socket_dir)])],
 [ case "$withval" in
   yes|no)
   #
@@ -73,7 +73,7 @@ AC_ARG_WITH(winbindd-socket-dir,
 #################################################
 # set where the winbindd privilaged socket should be put
 AC_ARG_WITH(winbindd-privileged-socket-dir,
-[  --with-winbindd-privileged-socket-dir=DIR   Where to put the winbindd socket ($winbindd_privileged_socket_dir)],
+[AS_HELP_STRING([--with-winbindd-privileged-socket-dir=DIR],[Where to put the winbindd socket ($winbindd_privileged_socket_dir)])],
 [ case "$withval" in
   yes|no)
   #
@@ -86,26 +86,10 @@ AC_ARG_WITH(winbindd-privileged-socket-dir,
     ;;
   esac])
 
-#################################################
-# set where the winbindd privilaged socket should be put
-AC_ARG_WITH(winbindd-socket-dir,
-[  --with-winbindd-socket-dir=DIR   Where to put the winbindd socket ($ac_default_prefix/run/winbind_pipe)],
-[ case "$withval" in
-  yes|no)
-  #
-  # Just in case anybody calls it without argument
-  #
-    AC_MSG_WARN([--with-winbind-socketdir called without argument - will use default])
-  ;;
-  * )
-    winbindd_socket_dir="$withval"
-    ;;
-  esac])
-
 #################################################
 # set where the NTP signing deamon socket should be put
 AC_ARG_WITH(ntp-signd-socket-dir,
-[  --with-ntp-signd-socket-dir=DIR   Where to put the NTP signing deamon socket ($ac_default_prefix/run/ntp_signd)],
+[AS_HELP_STRING([--with-ntp-signd-socket-dir=DIR],[Where to put the NTP signing deamon socket ($ac_default_prefix/run/ntp_signd)])],
 [ case "$withval" in
   yes|no)
   #
@@ -121,7 +105,7 @@ AC_ARG_WITH(ntp-signd-socket-dir,
 #################################################
 # set lock directory location
 AC_ARG_WITH(lockdir,
-[  --with-lockdir=DIR      Where to put lock files ($ac_default_prefix/var/locks)],
+[AS_HELP_STRING([--with-lockdir=DIR],[Where to put lock files ($ac_default_prefix/var/locks)])],
 [ case "$withval" in
   yes|no)
   #
@@ -137,7 +121,7 @@ AC_ARG_WITH(lockdir,
 #################################################
 # set pid directory location
 AC_ARG_WITH(piddir,
-[  --with-piddir=DIR       Where to put pid files ($ac_default_prefix/var/locks)],
+[AS_HELP_STRING([--with-piddir=DIR],[Where to put pid files ($ac_default_prefix/var/locks)])],
 [ case "$withval" in
   yes|no)
   #
@@ -153,7 +137,7 @@ AC_ARG_WITH(piddir,
 #################################################
 # set log directory location
 AC_ARG_WITH(logfilebase,
-[  --with-logfilebase=DIR  Where to put log files (\$(VARDIR))],
+[AS_HELP_STRING([--with-logfilebase=DIR],[Where to put log files (\$(VARDIR))])],
 [ case "$withval" in
   yes|no)
   #
@@ -186,7 +170,7 @@ AC_SUBST(modulesdir)
 selftest_prefix="./st"
 AC_SUBST(selftest_prefix)
 AC_ARG_WITH(selftest-prefix,
-[  --with-selftest-prefix=DIR    The prefix where make test will be run ($selftest_prefix)],
+[AS_HELP_STRING([--with-selftest-prefix=DIR],[The prefix where make test will be run ($selftest_prefix)])],
 [ case "$withval" in
   yes|no)
     AC_MSG_WARN([--with-selftest-prefix called without argument - will use default])
@@ -198,7 +182,7 @@ AC_ARG_WITH(selftest-prefix,
 
 debug=no
 AC_ARG_ENABLE(debug,
-[  --enable-debug          Turn on compiler debugging information (default=no)],
+[AS_HELP_STRING([--enable-debug],[Turn on compiler debugging information (default=no)])],
     [if test x$enable_debug = xyes; then
         debug=yes
     fi])
@@ -206,7 +190,7 @@ AC_ARG_ENABLE(debug,
 developer=no
 AC_SUBST(developer)
 AC_ARG_ENABLE(developer,
-[  --enable-developer      Turn on developer warnings and debugging (default=no)],
+[AS_HELP_STRING([--enable-developer],[Turn on developer warnings and debugging (default=no)])],
     [if test x$enable_developer = xyes; then
        debug=yes
         developer=yes
@@ -214,7 +198,7 @@ AC_ARG_ENABLE(developer,
 
 dnl disable these external libs 
 AC_ARG_WITH(disable-ext-lib,
-[  --with-disable-ext-lib=LIB Comma-seperated list of external libraries],
+[AS_HELP_STRING([--with-disable-ext-lib=LIB],[Comma-seperated list of external libraries])],
 [ if test $withval; then
        for i in `echo $withval | sed -e's/,/ /g'`
        do
index f263f33d48889ac89d5154c0be3a875b24a03064..0b146b3c7d82afbc9ea4537fc277e7df4f4d4c91 100644 (file)
@@ -71,6 +71,7 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx,
        struct ldb_dn *partitions_basedn;
        struct interface *ifaces;
        bool user_known;
+       NTSTATUS status;
 
        partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx);
 
@@ -87,7 +88,7 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx,
                                         partitions_basedn, LDB_SCOPE_ONELEVEL, 
                                         ref_attrs, 
                                         "(&(&(objectClass=crossRef)(dnsRoot=%s))(nETBIOSName=*))",
-                                        domain);
+                                        ldb_binary_encode_string(mem_ctx, domain));
        
                if (ret != LDB_SUCCESS) {
                        DEBUG(2,("Unable to find referece to '%s' in sam: %s\n",
@@ -126,7 +127,7 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx,
                                         partitions_basedn, LDB_SCOPE_ONELEVEL, 
                                         ref_attrs, 
                                         "(&(objectClass=crossRef)(ncName=*)(nETBIOSName=%s))",
-                                        netbios_domain);
+                                        ldb_binary_encode_string(mem_ctx, netbios_domain));
        
                if (ret != LDB_SUCCESS) {
                        DEBUG(2,("Unable to find referece to '%s' in sam: %s\n",
@@ -161,17 +162,45 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx,
                ref_res = NULL;
 
                if (domain_guid) {
+                       struct GUID binary_guid;
+                       struct ldb_val guid_val;
+                       enum ndr_err_code ndr_err;
+
+                       /* By this means, we ensure we don't have funny stuff in the GUID */
+
+                       status = GUID_from_string(domain_guid, &binary_guid);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return status;
+                       }
+
+                       /* And this gets the result into the binary format we want anyway */
+                       ndr_err = ndr_push_struct_blob(&guid_val, mem_ctx, NULL, &binary_guid,
+                                                      (ndr_push_flags_fn_t)ndr_push_GUID);
+                       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+                               return NT_STATUS_INVALID_PARAMETER;
+                       }
                        ret = ldb_search_exp_fmt(sam_ctx, mem_ctx, &dom_res,
                                                 NULL, LDB_SCOPE_SUBTREE, 
                                                 dom_attrs, 
-                                                "(&(objectClass=domainDNS)(objectGUID=%s))", 
-                                                domain_guid);
+                                                "(&(objectCategory=DomainDNS)(objectGUID=%s))", 
+                                                ldb_binary_encode(mem_ctx, guid_val));
                } else { /* domain_sid case */
+                       struct dom_sid *sid;
+                       struct ldb_val sid_val;
+                       enum ndr_err_code ndr_err;
+                       
+                       /* Rather than go via the string, just push into the NDR form */
+                       ndr_err = ndr_push_struct_blob(&sid_val, mem_ctx, NULL, &sid,
+                                                      (ndr_push_flags_fn_t)ndr_push_dom_sid);
+                       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+                               return NT_STATUS_INVALID_PARAMETER;
+                       }
+
                        ret = ldb_search_exp_fmt(sam_ctx, mem_ctx, &dom_res,
                                                 NULL, LDB_SCOPE_SUBTREE, 
                                                 dom_attrs, 
-                                                "(&(objectClass=domainDNS)(objectSID=%s))", 
-                                                dom_sid_string(mem_ctx, domain_sid));
+                                                "(&(objectCategory=DomainDNS)(objectSID=%s))", 
+                                                ldb_binary_encode(mem_ctx, sid_val));
                }
                
                if (ret != LDB_SUCCESS) {
@@ -237,7 +266,8 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx,
                                         "(&(objectClass=user)(samAccountName=%s)"
                                         "(!(userAccountControl:" LDB_OID_COMPARATOR_AND ":=%u))"
                                         "(userAccountControl:" LDB_OID_COMPARATOR_OR ":=%u))", 
-                                        user, UF_ACCOUNTDISABLE, samdb_acb2uf(acct_control));
+                                        ldb_binary_encode_string(mem_ctx, user),
+                                        UF_ACCOUNTDISABLE, samdb_acb2uf(acct_control));
                if (ret != LDB_SUCCESS) {
                        DEBUG(2,("Unable to find referece to user '%s' with ACB 0x%8x under %s: %s\n",
                                 user, acct_control, ldb_dn_get_linearized(dom_res->msgs[0]->dn),
@@ -256,7 +286,8 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx,
        server_type      = 
                NBT_SERVER_DS | NBT_SERVER_TIMESERV |
                NBT_SERVER_CLOSEST | NBT_SERVER_WRITABLE | 
-               NBT_SERVER_GOOD_TIMESERV;
+               NBT_SERVER_GOOD_TIMESERV | NBT_SERVER_DS_DNS_CONTR |
+               NBT_SERVER_DS_DNS_DOMAIN;
 
        if (samdb_is_pdc(sam_ctx)) {
                server_type |= NBT_SERVER_PDC;
@@ -274,6 +305,10 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx,
                server_type |= NBT_SERVER_KDC;
        }
 
+       if (!ldb_dn_compare_base(ldb_get_root_basedn(sam_ctx), ldb_get_default_basedn(sam_ctx))) {
+               server_type |= NBT_SERVER_DS_DNS_FOREST;
+       }
+
        pdc_name         = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name(lp_ctx));
        domain_uuid      = samdb_result_guid(dom_res->msgs[0], "objectGUID");
        realm            = samdb_result_string(ref_res->msgs[0], "dnsRoot", lp_realm(lp_ctx));
@@ -285,6 +320,7 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx,
 
        flatname         = samdb_result_string(ref_res->msgs[0], "nETBIOSName", 
                                               lp_workgroup(lp_ctx));
+       /* FIXME: Hardcoded site names */
        server_site      = "Default-First-Site-Name";
        client_site      = "Default-First-Site-Name";
        load_interfaces(mem_ctx, lp_interfaces(lp_ctx), &ifaces);
index e8802fdf9c1b5d0d1588976cdccdb9ee238e9a7a..bdd61a363c4545c0dde2174f1cb28367f43114dc 100644 (file)
 #define SYSTEM_FLAG_CONFIG_ALLOW_RENAME                0x40000000
 #define SYSTEM_FLAG_DISALLOW_DELTE             0x80000000
 
+#define SEARCH_FLAG_ATTINDEX            0x0000001
+#define SEARCH_FLAG_PDNTATTINDEX        0x0000002
+#define SEARCH_FLAG_ANR                 0x0000004
+#define SEARCH_FLAG_PRESERVEONDELETE    0x0000008
+#define SEARCH_FLAG_COPY                0x0000010
+#define SEARCH_FLAG_TUPLEINDEX          0x0000020
+#define SEARCH_FLAG_SUBTREEATTRINDEX    0x0000040
+#define SEARCH_FLAG_CONFIDENTIAL        0x0000080
+#define SEARCH_FLAG_NEVERVALUEAUDIT     0x0000100
+#define SEARCH_FLAG_RODC_ATTRIBUTE      0x0000200
+
 #define DS_BEHAVIOR_WIN2000            0
 #define DS_BEHAVIOR_WIN2003_INTERIM    1
 #define DS_BEHAVIOR_WIN2003            2
index 7b700fda22ffbdc8207c0164f30f0a5f20ef7c98..63e8a77ce4c96ec79b53c0ac32719098ae599986 100644 (file)
@@ -34,8 +34,10 @@ PRIVATE_DEPENDENCIES = SAMDB_COMMON NDR_DRSUAPI NDR_DRSBLOBS
 
 SAMDB_SCHEMA_OBJ_FILES = $(addprefix $(dsdbsrcdir)/schema/, \
                schema_init.o \
+               schema_set.o \
+               schema_query.o \
                schema_syntax.o \
-               schema_constructed.o)
+               schema_description.o)
 
 $(eval $(call proto_header_template,$(dsdbsrcdir)/schema/proto.h,$(SAMDB_SCHEMA_OBJ_FILES:.o=.c)))
 # PUBLIC_HEADERS += dsdb/schema/schema.h
index 3629a3b92bf3c68751ed57e60395fd1e3a262a0f..80b398ef5c93ba49d37e34b1c8efec3e94ec50f0 100644 (file)
@@ -314,27 +314,35 @@ static void dreplsrv_op_pull_source_get_changes_recv(struct rpc_request *req)
        if (*r->out.level == 1) {
                ctr_level = 1;
                ctr1 = &r->out.ctr.ctr1;
-       } else if (*r->out.level == 2) {
+       } else if (*r->out.level == 2 &&
+                  r->out.ctr.ctr2.mszip1.ts) {
                ctr_level = 1;
-               ctr1 = r->out.ctr.ctr2.mszip1.ctr1;
+               ctr1 = &r->out.ctr.ctr2.mszip1.ts->ctr1;
        } else if (*r->out.level == 6) {
                ctr_level = 6;
                ctr6 = &r->out.ctr.ctr6;
        } else if (*r->out.level == 7 &&
                   r->out.ctr.ctr7.level == 6 &&
-                  r->out.ctr.ctr7.type == DRSUAPI_COMPRESSION_TYPE_MSZIP) {
+                  r->out.ctr.ctr7.type == DRSUAPI_COMPRESSION_TYPE_MSZIP &&
+                  r->out.ctr.ctr7.ctr.mszip6.ts) {
                ctr_level = 6;
-               ctr6 = r->out.ctr.ctr7.ctr.mszip6.ctr6;
+               ctr6 = &r->out.ctr.ctr7.ctr.mszip6.ts->ctr6;
        } else if (*r->out.level == 7 &&
                   r->out.ctr.ctr7.level == 6 &&
-                  r->out.ctr.ctr7.type == DRSUAPI_COMPRESSION_TYPE_XPRESS) {
+                  r->out.ctr.ctr7.type == DRSUAPI_COMPRESSION_TYPE_XPRESS &&
+                  r->out.ctr.ctr7.ctr.xpress6.ts) {
                ctr_level = 6;
-               ctr6 = r->out.ctr.ctr7.ctr.xpress6.ctr6;
+               ctr6 = &r->out.ctr.ctr7.ctr.xpress6.ts->ctr6;
        } else {
                composite_error(c, werror_to_ntstatus(WERR_BAD_NET_RESP));
                return;
        }
 
+       if (!ctr1 && !ctr6) {
+               composite_error(c, werror_to_ntstatus(WERR_BAD_NET_RESP));
+               return;
+       }
+
        if (ctr_level == 6) {
                if (!W_ERROR_IS_OK(ctr6->drs_error)) {
                        composite_error(c, werror_to_ntstatus(ctr6->drs_error));
index 1252c9ee42f1ae2c65fbb82dd875baae34101850..4e2c527fe9c31335590511f6cd6c8a4b3b7f2198 100644 (file)
@@ -146,7 +146,7 @@ struct ldb_parse_tree *anr_replace_callback(TALLOC_CTX *mem_ctx,
                op = LDB_OP_SUBSTRING;
        }
        for (cur = schema->attributes; cur; cur = cur->next) {
-               if (!(cur->searchFlags & 0x4)) continue;
+               if (!(cur->searchFlags & SEARCH_FLAG_ANR)) continue;
                match_tree = make_match_tree(module, mem_ctx, op, cur->lDAPDisplayName, match);
 
                if (tree) {
@@ -224,30 +224,26 @@ struct ldb_parse_tree *anr_replace_subtrees(struct ldb_parse_tree *tree,
                                            void *context)
 {
        int i;
+       struct ldb_parse_tree *tmp;
+
        switch (tree->operation) {
        case LDB_OP_AND:
        case LDB_OP_OR:
                for (i=0;i<tree->u.list.num_elements;i++) {
-                       tree->u.list.elements[i] = anr_replace_subtrees(tree->u.list.elements[i],
-                                                                       attr, callback, context);
-                       if (!tree->u.list.elements[i]) {
-                               return NULL;
-                       }
+                       tmp = anr_replace_subtrees(tree->u.list.elements[i],
+                                                  attr, callback, context);
+                       if (tmp) tree->u.list.elements[i] = tmp;
                }
                break;
        case LDB_OP_NOT:
-               tree->u.isnot.child = anr_replace_subtrees(tree->u.isnot.child, attr, callback, context);
-                       if (!tree->u.isnot.child) {
-                               return NULL;
-                       }
+               tmp = anr_replace_subtrees(tree->u.isnot.child, attr, callback, context);
+               if (tmp) tree->u.isnot.child = tmp;
                break;
        case LDB_OP_EQUALITY:
                if (ldb_attr_cmp(tree->u.equality.attr, attr) == 0) {
-                       tree = callback(tree, &tree->u.equality.value, 
+                       tmp = callback(tree, &tree->u.equality.value, 
                                        context);
-                       if (!tree) {
-                               return NULL;
-                       }
+                       if (tmp) tree = tmp;
                }
                break;
        case LDB_OP_SUBSTRING:
@@ -256,10 +252,8 @@ struct ldb_parse_tree *anr_replace_subtrees(struct ldb_parse_tree *tree,
                            tree->u.substring.end_with_wildcard == 1 && 
                            tree->u.substring.chunks[0] != NULL && 
                            tree->u.substring.chunks[1] == NULL) {
-                               tree = callback(tree, tree->u.substring.chunks[0], context);
-                               if (!tree) {
-                                       return NULL;
-                               }
+                               tmp = callback(tree, tree->u.substring.chunks[0], context);
+                               if (tmp) tree = tmp;
                        }
                }
                break;
@@ -280,17 +274,29 @@ static int anr_search(struct ldb_module *module, struct ldb_request *req)
        context->module = module;
        context->found_anr = false;
 
+#if 0
+       printf("oldanr : %s\n", ldb_filter_from_tree (0, req->op.search.tree));
+#endif
+
        /* Yes, this is a problem with req->op.search.tree being const... */
        anr_tree = anr_replace_subtrees(req->op.search.tree, "anr", anr_replace_callback, context);
        if (!anr_tree) {
+               talloc_free(context);
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
        if (context->found_anr) {
                /* The above function modifies the tree if it finds "anr", so no
                 * point just setting this on the down_req */
+#if 0
+               printf("newtree: %s\n", ldb_filter_from_tree (0, anr_tree));
+#endif
                req->op.search.tree = talloc_steal(req, anr_tree);
-
+       } else {
+               if (anr_tree != req->op.search.tree) {
+                       talloc_free(anr_tree);
+               }
+               talloc_free(context);
        }
        return ldb_next_request(module, req);
 }
index 04b9987071df30aba5e783a8b34ef5c63ffee72c..e64472432d21d2293b1bfd173144a1942a16169e 100644 (file)
@@ -160,7 +160,7 @@ static int setup_modifies(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
                                ldb_oom(ldb);
                                return LDB_ERR_OPERATIONS_ERROR;
                        }
-                       new_msg->dn = ldb_dn_new(new_msg, ldb, (char *)el->values[j].data);
+                       new_msg->dn = ldb_dn_from_ldb_val(new_msg, ldb, &el->values[j]);
                        if (!new_msg->dn) {
                                ldb_asprintf_errstring(ldb, 
                                                       "attribute %s value %s was not a valid DN", msg->elements[i].name,
@@ -330,7 +330,7 @@ static int linked_attributes_mod_replace_search_callback(struct ldb_context *ldb
                        /* Add all the existing elements, marking as 'proposed for delete' by setting .add = false */
                        for (i=0; i < search_el->num_values; i++) {
                                merged_list = talloc_realloc(ares, merged_list, struct merge, size + 1);
-                               merged_list[size].dn = ldb_dn_new(merged_list, ldb, (char *)search_el->values[i].data);
+                               merged_list[size].dn = ldb_dn_from_ldb_val(merged_list, ldb, &search_el->values[i]);
                                merged_list[size].add = false;
                                merged_list[size].ignore = false;
                                size++;
@@ -339,7 +339,7 @@ static int linked_attributes_mod_replace_search_callback(struct ldb_context *ldb
                        /* Add all the new replacement elements, marking as 'proposed for add' by setting .add = true */
                        for (i=0; i < ac2->el->num_values; i++) {
                                merged_list = talloc_realloc(ares, merged_list, struct merge, size + 1);
-                               merged_list[size].dn = ldb_dn_new(merged_list, ldb, (char *)ac2->el->values[i].data);
+                               merged_list[size].dn = ldb_dn_from_ldb_val(merged_list, ldb, &ac2->el->values[i]);
                                merged_list[size].add = true;
                                merged_list[size].ignore = false;
                                size++;
@@ -610,7 +610,7 @@ static int linked_attributes_modify(struct ldb_module *module, struct ldb_reques
                                ldb_oom(module->ldb);
                                return LDB_ERR_OPERATIONS_ERROR;
                        }
-                       new_msg->dn = ldb_dn_new(new_msg, module->ldb, (char *)el->values[j].data);
+                       new_msg->dn = ldb_dn_from_ldb_val(new_msg, module->ldb, &el->values[j]);
                        if (!new_msg->dn) {
                                ldb_asprintf_errstring(module->ldb, 
                                               "attribute %s value %s was not a valid DN", req->op.mod.message->elements[i].name,
index 8de9e33002bace5f76d8173373f09f12ed3ddc3b..3306fd3c33b9f8cba6b1bd76d674465c3160d83c 100644 (file)
@@ -112,7 +112,7 @@ static int normalise_search_callback(struct ldb_context *ldb, void *context, str
                }
                for (j = 0; j < ares->message->elements[i].num_values; j++) {
                        const char *dn_str;
-                       struct ldb_dn *dn = ldb_dn_new(mem_ctx, ldb, (const char *)ares->message->elements[i].values[j].data);
+                       struct ldb_dn *dn = ldb_dn_from_ldb_val(mem_ctx, ldb, &ares->message->elements[i].values[j]);
                        if (!dn) {
                                talloc_free(mem_ctx);
                                return LDB_ERR_OPERATIONS_ERROR;
index 9285d6d0d862e6e2d73b05f5db85d412ff356fed..9cae6ab7b538e96165ec7a011655270f674f8e15 100644 (file)
@@ -925,7 +925,7 @@ static int partition_init(struct ldb_module *module)
                }
                
                for (i=0; i < replicate_attributes->num_values; i++) {
-                       data->replicate[i] = ldb_dn_new(data->replicate, module->ldb, (const char *)replicate_attributes->values[i].data);
+                       data->replicate[i] = ldb_dn_from_ldb_val(data->replicate, module->ldb, &replicate_attributes->values[i]);
                        if (!ldb_dn_validate(data->replicate[i])) {
                                ldb_asprintf_errstring(module->ldb, 
                                                        "partition_init: "
index 88590f306beddbf2a6712f5ca49202f727b2af39..bd491bd011e580f19a9b05a5a1a5f993004757ba 100644 (file)
@@ -768,6 +768,10 @@ static int samldb_modify(struct ldb_module *module, struct ldb_request *req)
        struct ldb_message_element *el, *el2;
        int ret;
        unsigned int group_type, user_account_control, account_type;
+       if (ldb_dn_is_special(req->op.mod.message->dn)) { /* do not manipulate our control entries */
+               return ldb_next_request(module, req);
+       }
+
        if (ldb_msg_find_element(req->op.mod.message, "sAMAccountType") != NULL) {
                ldb_asprintf_errstring(module->ldb, "sAMAccountType must not be specified");
                return LDB_ERR_UNWILLING_TO_PERFORM;
index 87ada855d3ff54b3c9b72c20e073a0d034c80142..968b19c038d5254054b5d32cf202836fc6dadc0a 100644 (file)
 #include "lib/util/dlinklist.h"
 #include "param/param.h"
 
+static int generate_objectClasses(struct ldb_context *ldb, struct ldb_message *msg,
+                                 const struct dsdb_schema *schema);
+static int generate_attributeTypes(struct ldb_context *ldb, struct ldb_message *msg,
+                                  const struct dsdb_schema *schema);
+static int generate_dITContentRules(struct ldb_context *ldb, struct ldb_message *msg,
+                                   const struct dsdb_schema *schema);
+
+static const struct {
+       const char *attr;
+       int (*fn)(struct ldb_context *, struct ldb_message *, const struct dsdb_schema *);
+} generated_attrs[] = {
+       {
+               .attr = "objectClasses",
+               .fn = generate_objectClasses
+       },
+       {
+               .attr = "attributeTypes",
+               .fn = generate_attributeTypes
+       },
+       {
+               .attr = "dITContentRules",
+               .fn = generate_dITContentRules
+       }
+};
+
+struct schema_fsmo_private_data {
+       struct ldb_dn *aggregate_dn;
+};
+
+struct schema_fsmo_search_data {
+       struct schema_fsmo_private_data *module_context;
+       struct ldb_request *orig_req;
+};
+
 static int schema_fsmo_init(struct ldb_module *module)
 {
        TALLOC_CTX *mem_ctx;
@@ -39,10 +73,7 @@ static int schema_fsmo_init(struct ldb_module *module)
        struct dsdb_schema *schema;
        char *error_string = NULL;
        int ret;
-
-       if (dsdb_get_schema(module->ldb)) {
-               return ldb_next_init(module);
-       }
+       struct schema_fsmo_private_data *data;
 
        schema_dn = samdb_schema_dn(module->ldb);
        if (!schema_dn) {
@@ -52,6 +83,25 @@ static int schema_fsmo_init(struct ldb_module *module)
                return ldb_next_init(module);
        }
 
+       data = talloc(module, struct schema_fsmo_private_data);
+       if (data == NULL) {
+               ldb_oom(module->ldb);
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       /* Check to see if this is a result on the CN=Aggregate schema */
+       data->aggregate_dn = ldb_dn_copy(data, schema_dn);
+       if (!ldb_dn_add_child_fmt(data->aggregate_dn, "CN=Aggregate")) {
+               ldb_oom(module->ldb);
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       module->private_data = data;
+
+       if (dsdb_get_schema(module->ldb)) {
+               return ldb_next_init(module);
+       }
+
        mem_ctx = talloc_new(module);
        if (!mem_ctx) {
                ldb_oom(module->ldb);
@@ -75,6 +125,7 @@ static int schema_fsmo_init(struct ldb_module *module)
                                       "schema_fsmo_init: dsdb_schema load failed: %s",
                                       error_string);
                talloc_free(mem_ctx);
+               return ret;
        }
 
        /* dsdb_set_schema() steal schema into the ldb_context */
@@ -208,9 +259,155 @@ static int schema_fsmo_extended(struct ldb_module *module, struct ldb_request *r
        return LDB_SUCCESS;
 }
 
+static int generate_objectClasses(struct ldb_context *ldb, struct ldb_message *msg,
+                                 const struct dsdb_schema *schema) 
+{
+       const struct dsdb_class *class;
+       int ret;
+
+       for (class = schema->classes; class; class = class->next) {
+               ret = ldb_msg_add_string(msg, "objectClasses", schema_class_to_description(msg, class));
+               if (ret != LDB_SUCCESS) {
+                       return ret;
+               }
+       }
+       return LDB_SUCCESS;
+}
+static int generate_attributeTypes(struct ldb_context *ldb, struct ldb_message *msg,
+                                 const struct dsdb_schema *schema) 
+{
+       const struct dsdb_attribute *attribute;
+       int ret;
+       
+       for (attribute = schema->attributes; attribute; attribute = attribute->next) {
+               ret = ldb_msg_add_string(msg, "attributeTypes", schema_attribute_to_description(msg, attribute));
+               if (ret != LDB_SUCCESS) {
+                       return ret;
+               }
+       }
+       return LDB_SUCCESS;
+}
+
+static int generate_dITContentRules(struct ldb_context *ldb, struct ldb_message *msg,
+                                   const struct dsdb_schema *schema) 
+{
+       const struct dsdb_class *class;
+       int ret;
+
+       for (class = schema->classes; class; class = class->next) {
+               if (class->auxiliaryClass || class->systemAuxiliaryClass) {
+                       char *ditcontentrule = schema_class_to_dITContentRule(msg, class, schema);
+                       if (!ditcontentrule) {
+                               ldb_oom(ldb);
+                               return LDB_ERR_OPERATIONS_ERROR;
+                       }
+                       ret = ldb_msg_add_steal_string(msg, "dITContentRules", ditcontentrule);
+                       if (ret != LDB_SUCCESS) {
+                               return ret;
+                       }
+               }
+       }
+       return 0;
+}
+
+
+
+/* Add objectClasses, attributeTypes and dITContentRules from the
+   schema object (they are not stored in the database)
+ */
+static int schema_fsmo_search_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares) 
+{
+       const struct dsdb_schema *schema = dsdb_get_schema(ldb);
+       struct schema_fsmo_search_data *search_data = talloc_get_type(context, struct schema_fsmo_search_data);
+       struct ldb_request *orig_req = search_data->orig_req;
+       TALLOC_CTX *mem_ctx;
+       int i, ret;
+
+       /* Only entries are interesting, and we handle the case of the parent seperatly */
+       if (ares->type != LDB_REPLY_ENTRY) {
+               return orig_req->callback(ldb, orig_req->context, ares);
+       }
+
+       if (ldb_dn_compare(ares->message->dn, search_data->module_context->aggregate_dn) != 0) {
+               talloc_free(mem_ctx);
+               return orig_req->callback(ldb, orig_req->context, ares);
+       }
+
+       mem_ctx = talloc_new(ares);
+       if (!mem_ctx) {
+               ldb_oom(ldb);
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       for (i=0; i < ARRAY_SIZE(generated_attrs); i++) {
+               if (ldb_attr_in_list(orig_req->op.search.attrs, generated_attrs[i].attr)) {
+                       ret = generated_attrs[i].fn(ldb, ares->message, schema);
+                       if (ret != LDB_SUCCESS) {
+                               return ret;
+                       }
+               }
+       }
+
+       talloc_free(mem_ctx);
+       return orig_req->callback(ldb, orig_req->context, ares);
+}
+
+/* search */
+static int schema_fsmo_search(struct ldb_module *module, struct ldb_request *req)
+{
+       int i, ret;
+       struct schema_fsmo_search_data *search_context;
+       struct ldb_request *down_req;
+       struct dsdb_schema *schema = dsdb_get_schema(module->ldb);
+
+       if (!schema || !module->private_data) {
+               /* If there is no schema, there is little we can do */
+               return ldb_next_request(module, req);
+       }
+       for (i=0; i < ARRAY_SIZE(generated_attrs); i++) {
+               if (ldb_attr_in_list(req->op.search.attrs, generated_attrs[i].attr)) {
+                       break;
+               }
+       }
+       if (i == ARRAY_SIZE(generated_attrs)) {
+               /* No request for a generated attr found, nothing to
+                * see here, move along... */
+               return ldb_next_request(module, req);
+       }
+
+       search_context = talloc(req, struct schema_fsmo_search_data);
+       if (!search_context) {
+               ldb_oom(module->ldb);
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+       down_req = talloc(req, struct ldb_request);     
+       if (!down_req) {
+               ldb_oom(module->ldb);
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+       
+       *down_req = *req;
+       search_context->orig_req = req;
+       search_context->module_context = talloc_get_type(module->private_data, struct schema_fsmo_private_data);
+       down_req->context = search_context;
+
+       down_req->callback = schema_fsmo_search_callback;
+
+       ret = ldb_next_request(module, down_req);
+
+       /* do not free down_req as the call results may be linked to it,
+        * it will be freed when the upper level request get freed */
+       if (ret == LDB_SUCCESS) {
+               req->handle = down_req->handle;
+       }
+       return ret;
+}
+
+
 _PUBLIC_ const struct ldb_module_ops ldb_schema_fsmo_module_ops = {
        .name           = "schema_fsmo",
        .init_context   = schema_fsmo_init,
        .add            = schema_fsmo_add,
-       .extended       = schema_fsmo_extended
+       .extended       = schema_fsmo_extended,
+       .search         = schema_fsmo_search
 };
index d800e4b6d242e9b24e0106d58a08582c1eed0427..ab9f32c913c7d2a928cdcfa7678a3da1cf53661d 100644 (file)
@@ -248,7 +248,7 @@ static int schema_validate_dn(struct ldb_context *ldb, struct ldb_val *val, int
        struct ldb_dn *dn;
        int ret = LDB_SUCCESS;
 
-       dn = ldb_dn_new(ldb, ldb, (const char *)val->data);
+       dn = ldb_dn_from_ldb_val(ldb, ldb, val);
        if ( ! ldb_dn_validate(dn)) {
                ret = LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
        }
index 6e967aab2f2061fac9fc9a1c2ff7cc17b735f8ac..8f9299514551a61af6eb1f4c75bbf8795729813a 100644 (file)
@@ -154,7 +154,7 @@ static struct ldb_val objectCategory_always_dn(struct ldb_module *module, TALLOC
        struct ldb_val out = data_blob(NULL, 0);
        const struct ldb_schema_attribute *a = ldb_schema_attribute_by_name(module->ldb, "objectCategory");
 
-       dn = ldb_dn_new(ctx, module->ldb, val->data);
+       dn = ldb_dn_from_ldb_val(ctx, module->ldb, val);
        if (dn && ldb_dn_validate(dn)) {
                talloc_free(dn);
                return val_copy(module, ctx, val);
index 7c408d0436c8a446e5dca80c90fd4d550ce2bf5f..428e6b4d4b93f25ab9683c2585683feb517899c8 100644 (file)
@@ -47,7 +47,7 @@ class MapBaseTestCase(TestCaseInTempDir):
 
         ldb.add({"dn": "@PARTITION",
             "partition": [s4.basedn + ":" + s4.url, s3.basedn + ":" + s3.url],
-            "replicateEntries": ["@SUBCLASSES", "@ATTRIBUTES", "@INDEXLIST"]})
+            "replicateEntries": ["@ATTRIBUTES", "@INDEXLIST"]})
 
     def setUp(self):
         super(MapBaseTestCase, self).setUp()
index 3e92671fa04690ab1b202bcdbc268e2149902f58..f24a75fd8f0c0f939669c7a17ace6491be85bd74 100644 (file)
@@ -31,6 +31,7 @@ struct event_context;
 
 #include "librpc/gen_ndr/security.h"
 #include "lib/ldb/include/ldb.h"
+#include "lib/ldb-samba/ldif_handlers.h"
 #include "librpc/gen_ndr/samr.h"
 #include "librpc/gen_ndr/drsuapi.h"
 #include "librpc/gen_ndr/drsblobs.h"
index a4e455ae33f1118aaa4c58efd54aae10015ef160..68dc8197cb14c12929a9da28d391023b23b8baea 100644 (file)
@@ -32,6 +32,10 @@ struct dsdb_syntax {
        uint32_t oMSyntax;
        struct ldb_val oMObjectClass;
        const char *attributeSyntax_oid;
+       const char *equality;
+       const char *substring;
+       const char *comment;
+       const char *ldb_syntax;
 
        WERROR (*drsuapi_to_ldb)(const struct dsdb_schema *schema,
                                 const struct dsdb_attribute *attr,
@@ -168,6 +172,12 @@ enum dsdb_attr_list_query {
        DSDB_SCHEMA_ALL
 };
 
+enum dsdb_schema_convert_target {
+       TARGET_OPENLDAP,
+       TARGET_FEDORA_DS,
+       TARGET_AD_SCHEMA_SUBENTRY
+};
+
 #include "dsdb/schema/proto.h"
 
 #endif /* _DSDB_SCHEMA_H */
diff --git a/source4/dsdb/schema/schema_constructed.c b/source4/dsdb/schema/schema_constructed.c
deleted file mode 100644 (file)
index 5134381..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-/* 
-   Unix SMB/CIFS mplementation.
-   DSDB schema constructed attributes
-   attributeTypes, objectClasses, dITContentRules...
-   
-   Copyright (C) Stefan Metzmacher 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 3 of the License, or
-   (at your option) any later version.
-   
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   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, see <http://www.gnu.org/licenses/>.
-   
-*/
-#include "includes.h"
-#include "dsdb/samdb/samdb.h"
-#include "librpc/gen_ndr/ndr_drsuapi.h"
-#include "lib/ldb/include/ldb.h"
-#include "system/time.h"
-#include "lib/charset/charset.h"
-#include "librpc/ndr/libndr.h"
-
-static char *dsdb_subSchema_list_append(char *v, const char *list_name)
-{
-       bool first = true;
-       uint32_t i;
-       const char *attrs[] = {
-               "attr1",
-               "attr2",
-               "attr3",
-               NULL
-       };
-
-       v = talloc_asprintf_append(v, "%s ( ", list_name);
-       if (!v) return NULL;
-
-       for (i=0; attrs[i]; i++) {
-               v = talloc_asprintf_append(v, "%s%s ",
-                                          (!first ? "$ " : ""),
-                                          attrs[i]);
-               if (!v) return NULL;
-               first = false;
-       }
-
-       v = talloc_asprintf_append(v, ") ");
-       if (!v) return NULL;
-
-       return v;
-}
-
-WERROR dsdb_subSchema_attributeTypes(const struct dsdb_schema *schema,
-                                    TALLOC_CTX *mem_ctx)
-{
-       struct ldb_message_element *e;
-       struct dsdb_attribute *a;
-
-       e = talloc_zero(mem_ctx, struct ldb_message_element);
-       W_ERROR_HAVE_NO_MEMORY(e);
-
-       for (a = schema->attributes; a; a = a->next) {
-               char *v;
-
-               v = talloc_asprintf(e, "( %s NAME '%s' SYNTAX '%s' ",
-                                   a->attributeID_oid, a->lDAPDisplayName,
-                                   a->syntax->ldap_oid);
-               W_ERROR_HAVE_NO_MEMORY(v);
-
-               if (a->isSingleValued) {
-                       v = talloc_asprintf_append(v, "SINGLE-VALUE ");
-                       W_ERROR_HAVE_NO_MEMORY(v);
-               }
-
-               if (a->systemOnly) {
-                       v = talloc_asprintf_append(v, "NO-USER-MODIFICATION ");
-                       W_ERROR_HAVE_NO_MEMORY(v);
-               }
-
-               v = talloc_asprintf_append(v, ")");
-               W_ERROR_HAVE_NO_MEMORY(v);
-
-               DEBUG(0,("%s\n", v));
-       }
-
-       return WERR_FOOBAR;
-}
-
-WERROR dsdb_subSchema_objectClasses(const struct dsdb_schema *schema,
-                                   TALLOC_CTX *mem_ctx)
-{
-       struct ldb_message_element *e;
-       struct dsdb_class *c;
-
-       e = talloc_zero(mem_ctx, struct ldb_message_element);
-       W_ERROR_HAVE_NO_MEMORY(e);
-
-       for (c = schema->classes; c; c = c->next) {
-               const char *class_type;
-               char *v;
-
-               switch (c->objectClassCategory) {
-               case 0:
-                       /*
-                        * NOTE: this is an type 88 class
-                        *       e.g. 2.5.6.6 NAME 'person'
-                        *       but w2k3 gives STRUCTURAL here!
-                        */
-                       class_type = "STRUCTURAL";
-                       break;
-               case 1:
-                       class_type = "STRUCTURAL";
-                       break;
-               case 2:
-                       class_type = "ABSTRACT";
-                       break;
-               case 3:
-                       class_type = "AUXILIARY";
-                       break;
-               default:
-                       class_type = "UNKNOWN";
-                       break;
-               }
-
-               v = talloc_asprintf(e, "( %s NAME '%s' SUB %s %s ",
-                                   c->governsID_oid, c->lDAPDisplayName,
-                                   c->subClassOf, class_type);
-               W_ERROR_HAVE_NO_MEMORY(v);
-
-               v = dsdb_subSchema_list_append(v, "MUST");
-               W_ERROR_HAVE_NO_MEMORY(v);
-
-               v = dsdb_subSchema_list_append(v, "MAY");
-               W_ERROR_HAVE_NO_MEMORY(v);
-
-               v = talloc_asprintf_append(v, ")");
-               W_ERROR_HAVE_NO_MEMORY(v);
-
-               DEBUG(0,("%s\n", v));
-       }
-
-       return WERR_FOOBAR;
-}
-
-WERROR dsdb_subSchema_dITContentRules(const struct dsdb_schema *schema,
-                                     TALLOC_CTX *mem_ctx)
-{
-       struct ldb_message_element *e;
-       struct dsdb_class *c;
-
-       e = talloc_zero(mem_ctx, struct ldb_message_element);
-       W_ERROR_HAVE_NO_MEMORY(e);
-
-       for (c = schema->classes; c; c = c->next) {
-               char *v;
-
-               /*
-                * TODO: filter out classes without auxiliary classes
-                */
-
-               v = talloc_asprintf(e, "( %s NAME '%s' ",
-                                   c->governsID_oid, c->lDAPDisplayName);
-               W_ERROR_HAVE_NO_MEMORY(v);
-
-               v = dsdb_subSchema_list_append(v, "AUX");
-               W_ERROR_HAVE_NO_MEMORY(v);
-
-               v = dsdb_subSchema_list_append(v, "MUST");
-               W_ERROR_HAVE_NO_MEMORY(v);
-
-               v = dsdb_subSchema_list_append(v, "MAY");
-               W_ERROR_HAVE_NO_MEMORY(v);
-
-               v = talloc_asprintf_append(v, ")");
-               W_ERROR_HAVE_NO_MEMORY(v);
-
-               DEBUG(0,("%s\n", v));
-       }
-
-       return WERR_FOOBAR;
-}
diff --git a/source4/dsdb/schema/schema_description.c b/source4/dsdb/schema/schema_description.c
new file mode 100644 (file)
index 0000000..9d93af9
--- /dev/null
@@ -0,0 +1,316 @@
+/* 
+   Unix SMB/CIFS mplementation.
+   Print schema info into string format
+   
+   Copyright (C) Andrew Bartlett 2006-2008
+    
+   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 3 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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, see <http://www.gnu.org/licenses/>.
+   
+*/
+#include "includes.h"
+#include "dsdb/samdb/samdb.h"
+
+#define IF_NULL_FAIL_RET(x) do {     \
+               if (!x) {               \
+                       return NULL;    \
+               }                       \
+       } while (0) 
+
+
+char *schema_attribute_description(TALLOC_CTX *mem_ctx, 
+                                         enum dsdb_schema_convert_target target,
+                                         const char *seperator,
+                                         const char *oid, 
+                                         const char *name,
+                                         const char *description,
+                                         const char *equality, 
+                                         const char *substring, 
+                                         const char *syntax,
+                                         bool single_value, bool operational)
+{
+       char *schema_entry = talloc_asprintf(mem_ctx, 
+                                            "(%s%s%s", seperator, oid, seperator);
+       
+       schema_entry = talloc_asprintf_append(schema_entry, 
+                                             "NAME '%s'%s", name, seperator);
+       IF_NULL_FAIL_RET(schema_entry);
+       
+       if (description) {
+#if 0          
+               /* Need a way to escape ' characters from the description */
+               schema_entry = talloc_asprintf_append(schema_entry, 
+                                                     "DESC '%s'%s", description, seperator);
+               IF_NULL_FAIL_RET(schema_entry);
+#endif
+       }
+
+       if (equality) {
+               schema_entry = talloc_asprintf_append(schema_entry, 
+                                                     "EQUALITY %s%s", equality, seperator);
+               IF_NULL_FAIL_RET(schema_entry);
+       }
+       if (substring) {
+               schema_entry = talloc_asprintf_append(schema_entry, 
+                                                     "SUBSTR %s%s", substring, seperator);
+               IF_NULL_FAIL_RET(schema_entry);
+       }
+       
+       schema_entry = talloc_asprintf_append(schema_entry, 
+                                             "SYNTAX %s%s", syntax, seperator);
+       IF_NULL_FAIL_RET(schema_entry);
+       
+       if (single_value) {
+               schema_entry = talloc_asprintf_append(schema_entry, 
+                                                     "SINGLE-VALUE%s", seperator);
+               IF_NULL_FAIL_RET(schema_entry);
+       }
+       
+       if (operational) {
+               schema_entry = talloc_asprintf_append(schema_entry, 
+                                                     "NO-USER-MODIFICATION%s", seperator);
+               IF_NULL_FAIL_RET(schema_entry);
+       }
+       
+       schema_entry = talloc_asprintf_append(schema_entry, 
+                                             ")");
+       return schema_entry;
+}
+
+char *schema_attribute_to_description(TALLOC_CTX *mem_ctx, const struct dsdb_attribute *attribute) 
+{
+       char *schema_description;
+       const struct dsdb_syntax *map = find_syntax_map_by_ad_oid(attribute->attributeSyntax_oid);
+       const char *syntax = map ? map->ldap_oid : attribute->attributeSyntax_oid;
+       TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+       if (!tmp_ctx) {
+               return NULL;
+       }
+
+       
+       schema_description 
+               = schema_attribute_description(mem_ctx, 
+                                              TARGET_AD_SCHEMA_SUBENTRY,
+                                              " ",
+                                              attribute->attributeID_oid,
+                                              attribute->lDAPDisplayName,
+                                              NULL, NULL, NULL, talloc_asprintf(tmp_ctx, "'%s'", syntax),
+                                              attribute->isSingleValued,
+                                              attribute->systemOnly);
+       talloc_free(tmp_ctx);
+       return schema_description;
+}
+
+#define APPEND_ATTRS(attributes)                               \
+       do {                                                            \
+               int k;                                                  \
+               for (k=0; attributes && attributes[k]; k++) {           \
+                       const char *attr_name = attributes[k];          \
+                                                                       \
+                       schema_entry = talloc_asprintf_append(schema_entry, \
+                                                             "%s ",    \
+                                                             attr_name); \
+                       IF_NULL_FAIL_RET(schema_entry);                 \
+                       if (attributes[k+1]) {                          \
+                               IF_NULL_FAIL_RET(schema_entry);         \
+                               if (target == TARGET_OPENLDAP && ((k+1)%5 == 0)) { \
+                                       schema_entry = talloc_asprintf_append(schema_entry, \
+                                                                             "$%s ", seperator); \
+                                       IF_NULL_FAIL_RET(schema_entry); \
+                               } else {                                \
+                                       schema_entry = talloc_asprintf_append(schema_entry, \
+                                                                             "$ "); \
+                               }                                       \
+                       }                                               \
+               }                                                       \
+       } while (0)
+       
+
+/* Print a schema class or dITContentRule as a string.  
+ *
+ * To print a scheam class, specify objectClassCategory but not auxillary_classes
+ * To print a dITContentRule, specify auxillary_classes but set objectClassCategory == -1
+ *
+ */
+
+char *schema_class_description(TALLOC_CTX *mem_ctx, 
+                              enum dsdb_schema_convert_target target,
+                              const char *seperator,
+                              const char *oid, 
+                              const char *name,
+                              const char **auxillary_classes,
+                              const char *description,
+                              const char *subClassOf,
+                              int objectClassCategory,
+                              char **must,
+                              char **may)
+{
+       char *schema_entry = talloc_asprintf(mem_ctx, 
+                                            "(%s%s%s", seperator, oid, seperator);
+       
+       IF_NULL_FAIL_RET(schema_entry);
+
+       schema_entry = talloc_asprintf_append(schema_entry, 
+                                             "NAME '%s'%s", name, seperator);
+       IF_NULL_FAIL_RET(schema_entry);
+       
+       if (description) {
+               schema_entry = talloc_asprintf_append(schema_entry, 
+                                                     "DESC '%s'%s", description, seperator);
+               IF_NULL_FAIL_RET(schema_entry);
+       }
+
+       if (auxillary_classes) {
+               schema_entry = talloc_asprintf_append(schema_entry, 
+                                                     "AUX ( ");
+               IF_NULL_FAIL_RET(schema_entry);
+               
+               APPEND_ATTRS(auxillary_classes);
+               
+               schema_entry = talloc_asprintf_append(schema_entry, 
+                                                     ")%s", seperator);
+               IF_NULL_FAIL_RET(schema_entry);
+       }
+
+       if (subClassOf) {
+               schema_entry = talloc_asprintf_append(schema_entry, 
+                                                     "SUP %s%s", subClassOf, seperator);
+               IF_NULL_FAIL_RET(schema_entry);
+       }
+       
+       switch (objectClassCategory) {
+       case -1:
+               break;
+               /* Dummy case for when used for printing ditContentRules */
+       case 0:
+               /*
+                * NOTE: this is an type 88 class
+                *       e.g. 2.5.6.6 NAME 'person'
+                *       but w2k3 gives STRUCTURAL here!
+                */
+               schema_entry = talloc_asprintf_append(schema_entry, 
+                                                     "STRUCTURAL%s", seperator);
+               IF_NULL_FAIL_RET(schema_entry);
+               break;
+       case 1:
+               schema_entry = talloc_asprintf_append(schema_entry, 
+                                                     "STRUCTURAL%s", seperator);
+               IF_NULL_FAIL_RET(schema_entry);
+               break;
+       case 2:
+               schema_entry = talloc_asprintf_append(schema_entry, 
+                                                     "ABSTRACT%s", seperator);
+               IF_NULL_FAIL_RET(schema_entry);
+               break;
+       case 3:
+               schema_entry = talloc_asprintf_append(schema_entry, 
+                                                     "AUXILIARY%s", seperator);
+               IF_NULL_FAIL_RET(schema_entry);
+               break;
+       }
+       
+       if (must) {
+               schema_entry = talloc_asprintf_append(schema_entry, 
+                                                     "MUST ( ");
+               IF_NULL_FAIL_RET(schema_entry);
+               
+               APPEND_ATTRS(must);
+               
+               schema_entry = talloc_asprintf_append(schema_entry, 
+                                                     ")%s", seperator);
+               IF_NULL_FAIL_RET(schema_entry);
+       }
+       
+       if (may) {
+               schema_entry = talloc_asprintf_append(schema_entry, 
+                                                     "MAY ( ");
+               IF_NULL_FAIL_RET(schema_entry);
+               
+               APPEND_ATTRS(may);
+               
+               schema_entry = talloc_asprintf_append(schema_entry, 
+                                                     ")%s", seperator);
+               IF_NULL_FAIL_RET(schema_entry);
+       }
+       
+       schema_entry = talloc_asprintf_append(schema_entry, 
+                                             ")");
+       return schema_entry;
+}
+
+char *schema_class_to_description(TALLOC_CTX *mem_ctx, const struct dsdb_class *class) 
+{
+       char *schema_description;
+       TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+       if (!tmp_ctx) {
+               return NULL;
+       }
+       
+       schema_description
+               = schema_class_description(mem_ctx, 
+                                          TARGET_AD_SCHEMA_SUBENTRY,
+                                          " ",
+                                          class->governsID_oid,
+                                          class->lDAPDisplayName,
+                                          NULL,
+                                          NULL, 
+                                          class->subClassOf,
+                                          class->objectClassCategory,
+                                          dsdb_attribute_list(tmp_ctx, 
+                                                              class, DSDB_SCHEMA_ALL_MUST),
+                                          dsdb_attribute_list(tmp_ctx, 
+                                                              class, DSDB_SCHEMA_ALL_MAY));
+       talloc_free(tmp_ctx);
+       return schema_description;
+}
+char *schema_class_to_dITContentRule(TALLOC_CTX *mem_ctx, const struct dsdb_class *class,
+                                    const struct dsdb_schema *schema) 
+{
+       int i;
+       char *schema_description;
+       char **aux_class_list = NULL;
+       char **attrs;
+       char **must_attr_list = NULL;
+       char **may_attr_list = NULL;
+       TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+       const struct dsdb_class *aux_class;
+       if (!tmp_ctx) {
+               return NULL;
+       }
+
+       aux_class_list = merge_attr_list(tmp_ctx, aux_class_list, class->systemAuxiliaryClass);
+       aux_class_list = merge_attr_list(tmp_ctx, aux_class_list, class->auxiliaryClass);
+
+       for (i=0; aux_class_list && aux_class_list[i]; i++) {
+               aux_class = dsdb_class_by_lDAPDisplayName(schema, aux_class_list[i]);
+               
+               attrs = dsdb_attribute_list(mem_ctx, aux_class, DSDB_SCHEMA_ALL_MUST);
+               must_attr_list = merge_attr_list(mem_ctx, must_attr_list, attrs);
+
+               attrs = dsdb_attribute_list(mem_ctx, aux_class, DSDB_SCHEMA_ALL_MAY);
+               may_attr_list = merge_attr_list(mem_ctx, may_attr_list, attrs);
+       }
+
+       schema_description
+               = schema_class_description(mem_ctx, 
+                                          TARGET_AD_SCHEMA_SUBENTRY,
+                                          " ",
+                                          class->governsID_oid,
+                                          class->lDAPDisplayName,
+                                          (const char **)aux_class_list,
+                                          NULL, 
+                                          class->subClassOf,
+                                          -1, must_attr_list, may_attr_list);
+       talloc_free(tmp_ctx);
+       return schema_description;
+}
index 85fdbe9e8731b427c78cf5526bd6c769fdb40a29..3ed7daee5953aa8a778436a01baf08ea286708dc 100644 (file)
@@ -809,7 +809,6 @@ int dsdb_schema_from_ldb_results(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
        if (!prefix_val) {
                *error_string = talloc_asprintf(mem_ctx, 
                                                "schema_fsmo_init: no prefixMap attribute found");
-               talloc_free(mem_ctx);
                return LDB_ERR_CONSTRAINT_VIOLATION;
        }
        info_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "schemaInfo");
@@ -828,7 +827,6 @@ int dsdb_schema_from_ldb_results(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
                *error_string = talloc_asprintf(mem_ctx, 
                              "schema_fsmo_init: failed to load oid mappings: %s",
                              win_errstr(status));
-               talloc_free(mem_ctx);
                return LDB_ERR_CONSTRAINT_VIOLATION;
        }
 
@@ -847,7 +845,6 @@ int dsdb_schema_from_ldb_results(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
                                      "schema_fsmo_init: failed to load attribute definition: %s:%s",
                                      ldb_dn_get_linearized(attrs_res->msgs[i]->dn),
                                      win_errstr(status));
-                       talloc_free(mem_ctx);
                        return LDB_ERR_CONSTRAINT_VIOLATION;
                }
 
@@ -869,7 +866,6 @@ int dsdb_schema_from_ldb_results(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
                                      "schema_fsmo_init: failed to load class definition: %s:%s",
                                      ldb_dn_get_linearized(objectclass_res->msgs[i]->dn),
                                      win_errstr(status));
-                       talloc_free(mem_ctx);
                        return LDB_ERR_CONSTRAINT_VIOLATION;
                }
 
@@ -914,7 +910,6 @@ static int fetch_oc_recursive(struct ldb_context *ldb, struct ldb_dn *schemadn,
                                        "(&(&(objectClass=classSchema)(subClassOf=%s))(!(lDAPDisplayName=%s)))",
                                        name, name);
                if (ret != LDB_SUCCESS) {
-                       printf("Search failed: %s\n", ldb_errstring(ldb));
                        return ret;
                }
                
@@ -940,7 +935,8 @@ static int fetch_oc_recursive(struct ldb_context *ldb, struct ldb_dn *schemadn,
 
 static int fetch_objectclass_schema(struct ldb_context *ldb, struct ldb_dn *schemadn, 
                                    TALLOC_CTX *mem_ctx, 
-                                   struct ldb_result **objectclasses_res)
+                                   struct ldb_result **objectclasses_res,
+                                   char **error_string)
 {
        TALLOC_CTX *local_ctx = talloc_new(mem_ctx);
        struct ldb_result *top_res, *ret_res;
@@ -949,19 +945,23 @@ static int fetch_objectclass_schema(struct ldb_context *ldb, struct ldb_dn *sche
                return LDB_ERR_OPERATIONS_ERROR;
        }
        
-       /* Downlaod 'top' */
+       /* Download 'top' */
        ret = ldb_search(ldb, schemadn, LDB_SCOPE_SUBTREE, 
                         "(&(objectClass=classSchema)(lDAPDisplayName=top))", 
                         NULL, &top_res);
        if (ret != LDB_SUCCESS) {
-               printf("Search failed: %s\n", ldb_errstring(ldb));
-               return LDB_ERR_OPERATIONS_ERROR;
+               *error_string = talloc_asprintf(mem_ctx, 
+                                               "dsdb_schema: failed to search for top classSchema object: %s",
+                                               ldb_errstring(ldb));
+               return ret;
        }
 
        talloc_steal(local_ctx, top_res);
 
        if (top_res->count != 1) {
-               return LDB_ERR_OPERATIONS_ERROR;
+               *error_string = talloc_asprintf(mem_ctx, 
+                                               "dsdb_schema: failed to find top classSchema object");
+               return LDB_ERR_NO_SUCH_OBJECT;
        }
 
        ret_res = talloc_zero(local_ctx, struct ldb_result);
@@ -972,8 +972,7 @@ static int fetch_objectclass_schema(struct ldb_context *ldb, struct ldb_dn *sche
        ret = fetch_oc_recursive(ldb, schemadn, local_ctx, top_res, ret_res); 
 
        if (ret != LDB_SUCCESS) {
-               printf("Search failed: %s\n", ldb_errstring(ldb));
-               return LDB_ERR_OPERATIONS_ERROR;
+               return ret;
        }
 
        *objectclasses_res = talloc_move(mem_ctx, &ret_res);
@@ -1051,10 +1050,10 @@ int dsdb_schema_from_schema_dn(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
        /*
         * load the objectClass definitions
         */
-       ret = fetch_objectclass_schema(ldb, schema_dn, tmp_ctx, &c_res);
+       ret = fetch_objectclass_schema(ldb, schema_dn, tmp_ctx, &c_res, &error_string);
        if (ret != LDB_SUCCESS) {
                *error_string_out = talloc_asprintf(mem_ctx, 
-                                      "Failed to fetch objectClass schema elements: %s\n", ldb_errstring(ldb));
+                                      "Failed to fetch objectClass schema elements: %s", error_string);
                talloc_free(tmp_ctx);
                return ret;
        }
@@ -1410,535 +1409,3 @@ WERROR dsdb_class_from_drsuapi(struct dsdb_schema *schema,
        return WERR_OK;
 }
 
-const struct dsdb_attribute *dsdb_attribute_by_attributeID_id(const struct dsdb_schema *schema,
-                                                             uint32_t id)
-{
-       struct dsdb_attribute *cur;
-
-       /*
-        * 0xFFFFFFFF is used as value when no mapping table is available,
-        * so don't try to match with it
-        */
-       if (id == 0xFFFFFFFF) return NULL;
-
-       /* TODO: add binary search */
-       for (cur = schema->attributes; cur; cur = cur->next) {
-               if (cur->attributeID_id != id) continue;
-
-               return cur;
-       }
-
-       return NULL;
-}
-
-const struct dsdb_attribute *dsdb_attribute_by_attributeID_oid(const struct dsdb_schema *schema,
-                                                              const char *oid)
-{
-       struct dsdb_attribute *cur;
-
-       if (!oid) return NULL;
-
-       /* TODO: add binary search */
-       for (cur = schema->attributes; cur; cur = cur->next) {
-               if (strcmp(cur->attributeID_oid, oid) != 0) continue;
-
-               return cur;
-       }
-
-       return NULL;
-}
-
-const struct dsdb_attribute *dsdb_attribute_by_lDAPDisplayName(const struct dsdb_schema *schema,
-                                                              const char *name)
-{
-       struct dsdb_attribute *cur;
-
-       if (!name) return NULL;
-
-       /* TODO: add binary search */
-       for (cur = schema->attributes; cur; cur = cur->next) {
-               if (strcasecmp(cur->lDAPDisplayName, name) != 0) continue;
-
-               return cur;
-       }
-
-       return NULL;
-}
-
-const struct dsdb_attribute *dsdb_attribute_by_linkID(const struct dsdb_schema *schema,
-                                                     int linkID)
-{
-       struct dsdb_attribute *cur;
-
-       /* TODO: add binary search */
-       for (cur = schema->attributes; cur; cur = cur->next) {
-               if (cur->linkID != linkID) continue;
-
-               return cur;
-       }
-
-       return NULL;
-}
-
-const struct dsdb_class *dsdb_class_by_governsID_id(const struct dsdb_schema *schema,
-                                                   uint32_t id)
-{
-       struct dsdb_class *cur;
-
-       /*
-        * 0xFFFFFFFF is used as value when no mapping table is available,
-        * so don't try to match with it
-        */
-       if (id == 0xFFFFFFFF) return NULL;
-
-       /* TODO: add binary search */
-       for (cur = schema->classes; cur; cur = cur->next) {
-               if (cur->governsID_id != id) continue;
-
-               return cur;
-       }
-
-       return NULL;
-}
-
-const struct dsdb_class *dsdb_class_by_governsID_oid(const struct dsdb_schema *schema,
-                                                    const char *oid)
-{
-       struct dsdb_class *cur;
-
-       if (!oid) return NULL;
-
-       /* TODO: add binary search */
-       for (cur = schema->classes; cur; cur = cur->next) {
-               if (strcmp(cur->governsID_oid, oid) != 0) continue;
-
-               return cur;
-       }
-
-       return NULL;
-}
-
-const struct dsdb_class *dsdb_class_by_lDAPDisplayName(const struct dsdb_schema *schema,
-                                                      const char *name)
-{
-       struct dsdb_class *cur;
-
-       if (!name) return NULL;
-
-       /* TODO: add binary search */
-       for (cur = schema->classes; cur; cur = cur->next) {
-               if (strcasecmp(cur->lDAPDisplayName, name) != 0) continue;
-
-               return cur;
-       }
-
-       return NULL;
-}
-
-const struct dsdb_class *dsdb_class_by_cn(const struct dsdb_schema *schema,
-                                         const char *cn)
-{
-       struct dsdb_class *cur;
-
-       if (!cn) return NULL;
-
-       /* TODO: add binary search */
-       for (cur = schema->classes; cur; cur = cur->next) {
-               if (strcasecmp(cur->cn, cn) != 0) continue;
-
-               return cur;
-       }
-
-       return NULL;
-}
-
-const char *dsdb_lDAPDisplayName_by_id(const struct dsdb_schema *schema,
-                                      uint32_t id)
-{
-       const struct dsdb_attribute *a;
-       const struct dsdb_class *c;
-
-       /* TODO: add binary search */
-       a = dsdb_attribute_by_attributeID_id(schema, id);
-       if (a) {
-               return a->lDAPDisplayName;
-       }
-
-       c = dsdb_class_by_governsID_id(schema, id);
-       if (c) {
-               return c->lDAPDisplayName;
-       }
-
-       return NULL;
-}
-
-/** 
-    Return a list of linked attributes, in lDAPDisplayName format.
-
-    This may be used to determine if a modification would require
-    backlinks to be updated, for example
-*/
-
-WERROR dsdb_linked_attribute_lDAPDisplayName_list(const struct dsdb_schema *schema, TALLOC_CTX *mem_ctx, const char ***attr_list_ret)
-{
-       const char **attr_list = NULL;
-       struct dsdb_attribute *cur;
-       int i = 0;
-       for (cur = schema->attributes; cur; cur = cur->next) {
-               if (cur->linkID == 0) continue;
-               
-               attr_list = talloc_realloc(mem_ctx, attr_list, const char *, i+2);
-               if (!attr_list) {
-                       return WERR_NOMEM;
-               }
-               attr_list[i] = cur->lDAPDisplayName;
-               i++;
-       }
-       attr_list[i] = NULL;
-       *attr_list_ret = attr_list;
-       return WERR_OK;
-}
-
-static char **merge_attr_list(TALLOC_CTX *mem_ctx, 
-                             char **attrs, const char **new_attrs) 
-{
-       char **ret_attrs;
-       int i;
-       size_t new_len, orig_len = str_list_length((const char **)attrs);
-       if (!new_attrs) {
-               return attrs;
-       }
-
-       ret_attrs = talloc_realloc(mem_ctx, 
-                                  attrs, char *, orig_len + str_list_length(new_attrs) + 1);
-       if (ret_attrs) {
-               for (i=0; i < str_list_length(new_attrs); i++) {
-                       ret_attrs[orig_len + i] = new_attrs[i];
-               }
-               new_len = orig_len + str_list_length(new_attrs);
-
-               ret_attrs[new_len] = NULL;
-
-       }
-
-       return ret_attrs;
-}
-
-char **dsdb_full_attribute_list_internal(TALLOC_CTX *mem_ctx, 
-                                        const struct dsdb_schema *schema, 
-                                        const char **class_list,
-                                        enum dsdb_attr_list_query query)
-{
-       int i;
-       const struct dsdb_class *class;
-       
-       char **attr_list = NULL;
-       char **recursive_list;
-
-       for (i=0; class_list && class_list[i]; i++) {
-               class = dsdb_class_by_lDAPDisplayName(schema, class_list[i]);
-               
-               switch (query) {
-               case DSDB_SCHEMA_ALL_MAY:
-                       attr_list = merge_attr_list(mem_ctx, attr_list, class->mayContain);
-                       attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMayContain);
-                       break;
-
-               case DSDB_SCHEMA_ALL_MUST:
-                       attr_list = merge_attr_list(mem_ctx, attr_list, class->mustContain);
-                       attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMustContain);
-                       break;
-
-               case DSDB_SCHEMA_SYS_MAY:
-                       attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMayContain);
-                       break;
-
-               case DSDB_SCHEMA_SYS_MUST:
-                       attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMustContain);
-                       break;
-
-               case DSDB_SCHEMA_MAY:
-                       attr_list = merge_attr_list(mem_ctx, attr_list, class->mayContain);
-                       break;
-
-               case DSDB_SCHEMA_MUST:
-                       attr_list = merge_attr_list(mem_ctx, attr_list, class->mustContain);
-                       break;
-
-               case DSDB_SCHEMA_ALL:
-                       attr_list = merge_attr_list(mem_ctx, attr_list, class->mayContain);
-                       attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMayContain);
-                       attr_list = merge_attr_list(mem_ctx, attr_list, class->mustContain);
-                       attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMustContain);
-                       break;
-               }
-
-               recursive_list = dsdb_full_attribute_list_internal(mem_ctx, schema, 
-                                                                  class->systemAuxiliaryClass, 
-                                                                  query);
-               
-               attr_list = merge_attr_list(mem_ctx, attr_list, (const char **)recursive_list);
-               
-               recursive_list = dsdb_full_attribute_list_internal(mem_ctx, schema, 
-                                                                  class->auxiliaryClass, 
-                                                                  query);
-
-               attr_list = merge_attr_list(mem_ctx, attr_list, (const char **)recursive_list);
-               
-       }
-       return attr_list;
-}
-
-char **dsdb_full_attribute_list(TALLOC_CTX *mem_ctx, 
-                               const struct dsdb_schema *schema, 
-                               const char **class_list,
-                               enum dsdb_attr_list_query query)
-{
-       char **attr_list = dsdb_full_attribute_list_internal(mem_ctx, schema, class_list, query);
-       size_t new_len = str_list_length((const char **)attr_list);
-
-       /* Remove duplicates */
-       if (new_len > 1) {
-               int i;
-               qsort(attr_list, new_len,
-                     sizeof(*attr_list),
-                     (comparison_fn_t)strcasecmp);
-               
-               for (i=1 ; i < new_len; i++) {
-                       char **val1 = &attr_list[i-1];
-                       char **val2 = &attr_list[i];
-                       if (ldb_attr_cmp(*val1, *val2) == 0) {
-                               memmove(val1, val2, (new_len - i) * sizeof( *attr_list)); 
-                               new_len--;
-                               i--;
-                       }
-               }
-       }
-       return attr_list;
-}
-/**
- * Attach the schema to an opaque pointer on the ldb, so ldb modules
- * can find it 
- */
-
-int dsdb_set_schema(struct ldb_context *ldb, struct dsdb_schema *schema)
-{
-       int ret;
-
-       ret = ldb_set_opaque(ldb, "dsdb_schema", schema);
-       if (ret != LDB_SUCCESS) {
-               return ret;
-       }
-
-       talloc_steal(ldb, schema);
-
-       return LDB_SUCCESS;
-}
-
-/**
- * Global variable to hold one copy of the schema, used to avoid memory bloat
- */
-static struct dsdb_schema *global_schema;
-
-/**
- * Make this ldb use the 'global' schema, setup to avoid having multiple copies in this process
- */
-int dsdb_set_global_schema(struct ldb_context *ldb)
-{
-       int ret;
-       if (!global_schema) {
-               return LDB_SUCCESS;
-       }
-       ret = ldb_set_opaque(ldb, "dsdb_schema", global_schema);
-       if (ret != LDB_SUCCESS) {
-               return ret;
-       }
-
-       /* Keep a reference to this schema, just incase the global copy is replaced */
-       if (talloc_reference(ldb, global_schema) == NULL) {
-               return LDB_ERR_OPERATIONS_ERROR;
-       }
-
-       return LDB_SUCCESS;
-}
-
-/**
- * Find the schema object for this ldb
- */
-
-struct dsdb_schema *dsdb_get_schema(struct ldb_context *ldb)
-{
-       const void *p;
-       struct dsdb_schema *schema;
-
-       /* see if we have a cached copy */
-       p = ldb_get_opaque(ldb, "dsdb_schema");
-       if (!p) {
-               return NULL;
-       }
-
-       schema = talloc_get_type(p, struct dsdb_schema);
-       if (!schema) {
-               return NULL;
-       }
-
-       return schema;
-}
-
-/**
- * Make the schema found on this ldb the 'global' schema
- */
-
-void dsdb_make_schema_global(struct ldb_context *ldb)
-{
-       struct dsdb_schema *schema = dsdb_get_schema(ldb);
-       if (!schema) {
-               return;
-       }
-
-       if (global_schema) {
-               talloc_unlink(talloc_autofree_context(), schema);
-       }
-
-       talloc_steal(talloc_autofree_context(), schema);
-       global_schema = schema;
-
-       dsdb_set_global_schema(ldb);
-}
-
-
-/**
- * Rather than read a schema from the LDB itself, read it from an ldif
- * file.  This allows schema to be loaded and used while adding the
- * schema itself to the directory.
- */
-
-WERROR dsdb_attach_schema_from_ldif_file(struct ldb_context *ldb, const char *pf, const char *df)
-{
-       struct ldb_ldif *ldif;
-       struct ldb_message *msg;
-       TALLOC_CTX *mem_ctx;
-       WERROR status;
-       int ret;
-       struct dsdb_schema *schema;
-       const struct ldb_val *prefix_val;
-       const struct ldb_val *info_val;
-       struct ldb_val info_val_default;
-
-       mem_ctx = talloc_new(ldb);
-       if (!mem_ctx) {
-               goto nomem;
-       }
-
-       schema = dsdb_new_schema(mem_ctx, lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")));
-
-       schema->fsmo.we_are_master = true;
-       schema->fsmo.master_dn = ldb_dn_new_fmt(schema, ldb, "@PROVISION_SCHEMA_MASTER");
-       if (!schema->fsmo.master_dn) {
-               goto nomem;
-       }
-
-       /*
-        * load the prefixMap attribute from pf
-        */
-       ldif = ldb_ldif_read_string(ldb, &pf);
-       if (!ldif) {
-               status = WERR_INVALID_PARAM;
-               goto failed;
-       }
-       talloc_steal(mem_ctx, ldif);
-
-       msg = ldb_msg_canonicalize(ldb, ldif->msg);
-       if (!msg) {
-               goto nomem;
-       }
-       talloc_steal(mem_ctx, msg);
-       talloc_free(ldif);
-
-       prefix_val = ldb_msg_find_ldb_val(msg, "prefixMap");
-       if (!prefix_val) {
-               status = WERR_INVALID_PARAM;
-               goto failed;
-       }
-
-       info_val = ldb_msg_find_ldb_val(msg, "schemaInfo");
-       if (!info_val) {
-               info_val_default = strhex_to_data_blob("FF0000000000000000000000000000000000000000");
-               if (!info_val_default.data) {
-                       goto nomem;
-               }
-               talloc_steal(mem_ctx, info_val_default.data);
-               info_val = &info_val_default;
-       }
-
-       status = dsdb_load_oid_mappings_ldb(schema, prefix_val, info_val);
-       if (!W_ERROR_IS_OK(status)) {
-               goto failed;
-       }
-
-       /*
-        * load the attribute and class definitions outof df
-        */
-       while ((ldif = ldb_ldif_read_string(ldb, &df))) {
-               bool is_sa;
-               bool is_sc;
-
-               talloc_steal(mem_ctx, ldif);
-
-               msg = ldb_msg_canonicalize(ldb, ldif->msg);
-               if (!msg) {
-                       goto nomem;
-               }
-
-               talloc_steal(mem_ctx, msg);
-               talloc_free(ldif);
-
-               is_sa = ldb_msg_check_string_attribute(msg, "objectClass", "attributeSchema");
-               is_sc = ldb_msg_check_string_attribute(msg, "objectClass", "classSchema");
-
-               if (is_sa) {
-                       struct dsdb_attribute *sa;
-
-                       sa = talloc_zero(schema, struct dsdb_attribute);
-                       if (!sa) {
-                               goto nomem;
-                       }
-
-                       status = dsdb_attribute_from_ldb(schema, msg, sa, sa);
-                       if (!W_ERROR_IS_OK(status)) {
-                               goto failed;
-                       }
-
-                       DLIST_ADD_END(schema->attributes, sa, struct dsdb_attribute *);
-               } else if (is_sc) {
-                       struct dsdb_class *sc;
-
-                       sc = talloc_zero(schema, struct dsdb_class);
-                       if (!sc) {
-                               goto nomem;
-                       }
-
-                       status = dsdb_class_from_ldb(schema, msg, sc, sc);
-                       if (!W_ERROR_IS_OK(status)) {
-                               goto failed;
-                       }
-
-                       DLIST_ADD_END(schema->classes, sc, struct dsdb_class *);
-               }
-       }
-
-       ret = dsdb_set_schema(ldb, schema);
-       if (ret != LDB_SUCCESS) {
-               status = WERR_FOOBAR;
-               goto failed;
-       }
-
-       goto done;
-
-nomem:
-       status = WERR_NOMEM;
-failed:
-done:
-       talloc_free(mem_ctx);
-       return status;
-}
diff --git a/source4/dsdb/schema/schema_query.c b/source4/dsdb/schema/schema_query.c
new file mode 100644 (file)
index 0000000..ca26ffd
--- /dev/null
@@ -0,0 +1,344 @@
+/* 
+   Unix SMB/CIFS mplementation.
+   DSDB schema header
+   
+   Copyright (C) Stefan Metzmacher <metze@samba.org> 2006-2007
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006-2008
+
+   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 3 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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, see <http://www.gnu.org/licenses/>.
+   
+*/
+
+#include "includes.h"
+#include "dsdb/samdb/samdb.h"
+
+const struct dsdb_attribute *dsdb_attribute_by_attributeID_id(const struct dsdb_schema *schema,
+                                                             uint32_t id)
+{
+       struct dsdb_attribute *cur;
+
+       /*
+        * 0xFFFFFFFF is used as value when no mapping table is available,
+        * so don't try to match with it
+        */
+       if (id == 0xFFFFFFFF) return NULL;
+
+       /* TODO: add binary search */
+       for (cur = schema->attributes; cur; cur = cur->next) {
+               if (cur->attributeID_id != id) continue;
+
+               return cur;
+       }
+
+       return NULL;
+}
+
+const struct dsdb_attribute *dsdb_attribute_by_attributeID_oid(const struct dsdb_schema *schema,
+                                                              const char *oid)
+{
+       struct dsdb_attribute *cur;
+
+       if (!oid) return NULL;
+
+       /* TODO: add binary search */
+       for (cur = schema->attributes; cur; cur = cur->next) {
+               if (strcmp(cur->attributeID_oid, oid) != 0) continue;
+
+               return cur;
+       }
+
+       return NULL;
+}
+
+const struct dsdb_attribute *dsdb_attribute_by_lDAPDisplayName(const struct dsdb_schema *schema,
+                                                              const char *name)
+{
+       struct dsdb_attribute *cur;
+
+       if (!name) return NULL;
+
+       /* TODO: add binary search */
+       for (cur = schema->attributes; cur; cur = cur->next) {
+               if (strcasecmp(cur->lDAPDisplayName, name) != 0) continue;
+
+               return cur;
+       }
+
+       return NULL;
+}
+
+const struct dsdb_attribute *dsdb_attribute_by_linkID(const struct dsdb_schema *schema,
+                                                     int linkID)
+{
+       struct dsdb_attribute *cur;
+
+       /* TODO: add binary search */
+       for (cur = schema->attributes; cur; cur = cur->next) {
+               if (cur->linkID != linkID) continue;
+
+               return cur;
+       }
+
+       return NULL;
+}
+
+const struct dsdb_class *dsdb_class_by_governsID_id(const struct dsdb_schema *schema,
+                                                   uint32_t id)
+{
+       struct dsdb_class *cur;
+
+       /*
+        * 0xFFFFFFFF is used as value when no mapping table is available,
+        * so don't try to match with it
+        */
+       if (id == 0xFFFFFFFF) return NULL;
+
+       /* TODO: add binary search */
+       for (cur = schema->classes; cur; cur = cur->next) {
+               if (cur->governsID_id != id) continue;
+
+               return cur;
+       }
+
+       return NULL;
+}
+
+const struct dsdb_class *dsdb_class_by_governsID_oid(const struct dsdb_schema *schema,
+                                                    const char *oid)
+{
+       struct dsdb_class *cur;
+
+       if (!oid) return NULL;
+
+       /* TODO: add binary search */
+       for (cur = schema->classes; cur; cur = cur->next) {
+               if (strcmp(cur->governsID_oid, oid) != 0) continue;
+
+               return cur;
+       }
+
+       return NULL;
+}
+
+const struct dsdb_class *dsdb_class_by_lDAPDisplayName(const struct dsdb_schema *schema,
+                                                      const char *name)
+{
+       struct dsdb_class *cur;
+
+       if (!name) return NULL;
+
+       /* TODO: add binary search */
+       for (cur = schema->classes; cur; cur = cur->next) {
+               if (strcasecmp(cur->lDAPDisplayName, name) != 0) continue;
+
+               return cur;
+       }
+
+       return NULL;
+}
+
+const struct dsdb_class *dsdb_class_by_cn(const struct dsdb_schema *schema,
+                                         const char *cn)
+{
+       struct dsdb_class *cur;
+
+       if (!cn) return NULL;
+
+       /* TODO: add binary search */
+       for (cur = schema->classes; cur; cur = cur->next) {
+               if (strcasecmp(cur->cn, cn) != 0) continue;
+
+               return cur;
+       }
+
+       return NULL;
+}
+
+const char *dsdb_lDAPDisplayName_by_id(const struct dsdb_schema *schema,
+                                      uint32_t id)
+{
+       const struct dsdb_attribute *a;
+       const struct dsdb_class *c;
+
+       /* TODO: add binary search */
+       a = dsdb_attribute_by_attributeID_id(schema, id);
+       if (a) {
+               return a->lDAPDisplayName;
+       }
+
+       c = dsdb_class_by_governsID_id(schema, id);
+       if (c) {
+               return c->lDAPDisplayName;
+       }
+
+       return NULL;
+}
+
+/** 
+    Return a list of linked attributes, in lDAPDisplayName format.
+
+    This may be used to determine if a modification would require
+    backlinks to be updated, for example
+*/
+
+WERROR dsdb_linked_attribute_lDAPDisplayName_list(const struct dsdb_schema *schema, TALLOC_CTX *mem_ctx, const char ***attr_list_ret)
+{
+       const char **attr_list = NULL;
+       struct dsdb_attribute *cur;
+       int i = 0;
+       for (cur = schema->attributes; cur; cur = cur->next) {
+               if (cur->linkID == 0) continue;
+               
+               attr_list = talloc_realloc(mem_ctx, attr_list, const char *, i+2);
+               if (!attr_list) {
+                       return WERR_NOMEM;
+               }
+               attr_list[i] = cur->lDAPDisplayName;
+               i++;
+       }
+       attr_list[i] = NULL;
+       *attr_list_ret = attr_list;
+       return WERR_OK;
+}
+
+char **merge_attr_list(TALLOC_CTX *mem_ctx, 
+                      char **attrs, const char **new_attrs) 
+{
+       char **ret_attrs;
+       int i;
+       size_t new_len, orig_len = str_list_length((const char **)attrs);
+       if (!new_attrs) {
+               return attrs;
+       }
+
+       ret_attrs = talloc_realloc(mem_ctx, 
+                                  attrs, char *, orig_len + str_list_length(new_attrs) + 1);
+       if (ret_attrs) {
+               for (i=0; i < str_list_length(new_attrs); i++) {
+                       ret_attrs[orig_len + i] = new_attrs[i];
+               }
+               new_len = orig_len + str_list_length(new_attrs);
+
+               ret_attrs[new_len] = NULL;
+       }
+
+       return ret_attrs;
+}
+
+/*
+  Return a merged list of the attributes of exactly one class (not
+  considering subclasses, auxillary classes etc)
+*/
+
+char **dsdb_attribute_list(TALLOC_CTX *mem_ctx, const struct dsdb_class *class, enum dsdb_attr_list_query query)
+{
+       char **attr_list = NULL;
+       switch (query) {
+       case DSDB_SCHEMA_ALL_MAY:
+               attr_list = merge_attr_list(mem_ctx, attr_list, class->mayContain);
+               attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMayContain);
+               break;
+               
+       case DSDB_SCHEMA_ALL_MUST:
+               attr_list = merge_attr_list(mem_ctx, attr_list, class->mustContain);
+               attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMustContain);
+               break;
+               
+       case DSDB_SCHEMA_SYS_MAY:
+               attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMayContain);
+               break;
+               
+       case DSDB_SCHEMA_SYS_MUST:
+               attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMustContain);
+               break;
+               
+       case DSDB_SCHEMA_MAY:
+               attr_list = merge_attr_list(mem_ctx, attr_list, class->mayContain);
+               break;
+               
+       case DSDB_SCHEMA_MUST:
+               attr_list = merge_attr_list(mem_ctx, attr_list, class->mustContain);
+               break;
+               
+       case DSDB_SCHEMA_ALL:
+               attr_list = merge_attr_list(mem_ctx, attr_list, class->mayContain);
+               attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMayContain);
+               attr_list = merge_attr_list(mem_ctx, attr_list, class->mustContain);
+               attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMustContain);
+               break;
+       }
+       return attr_list;
+}
+
+static char **dsdb_full_attribute_list_internal(TALLOC_CTX *mem_ctx, 
+                                               const struct dsdb_schema *schema, 
+                                               const char **class_list,
+                                               enum dsdb_attr_list_query query)
+{
+       int i;
+       const struct dsdb_class *class;
+       
+       char **attr_list = NULL;
+       char **this_class_list;
+       char **recursive_list;
+
+       for (i=0; class_list && class_list[i]; i++) {
+               class = dsdb_class_by_lDAPDisplayName(schema, class_list[i]);
+               
+               this_class_list = dsdb_attribute_list(mem_ctx, class, query);
+               attr_list = merge_attr_list(mem_ctx, attr_list, (const char **)this_class_list);
+
+               recursive_list = dsdb_full_attribute_list_internal(mem_ctx, schema, 
+                                                                  class->systemAuxiliaryClass, 
+                                                                  query);
+               
+               attr_list = merge_attr_list(mem_ctx, attr_list, (const char **)recursive_list);
+               
+               recursive_list = dsdb_full_attribute_list_internal(mem_ctx, schema, 
+                                                                  class->auxiliaryClass, 
+                                                                  query);
+               
+               attr_list = merge_attr_list(mem_ctx, attr_list, (const char **)recursive_list);
+               
+       }
+       return attr_list;
+}
+
+char **dsdb_full_attribute_list(TALLOC_CTX *mem_ctx, 
+                               const struct dsdb_schema *schema, 
+                               const char **class_list,
+                               enum dsdb_attr_list_query query)
+{
+       char **attr_list = dsdb_full_attribute_list_internal(mem_ctx, schema, class_list, query);
+       size_t new_len = str_list_length((const char **)attr_list);
+
+       /* Remove duplicates */
+       if (new_len > 1) {
+               int i;
+               qsort(attr_list, new_len,
+                     sizeof(*attr_list),
+                     (comparison_fn_t)strcasecmp);
+               
+               for (i=1 ; i < new_len; i++) {
+                       char **val1 = &attr_list[i-1];
+                       char **val2 = &attr_list[i];
+                       if (ldb_attr_cmp(*val1, *val2) == 0) {
+                               memmove(val1, val2, (new_len - i) * sizeof( *attr_list)); 
+                               new_len--;
+                               i--;
+                       }
+               }
+       }
+       return attr_list;
+}
diff --git a/source4/dsdb/schema/schema_set.c b/source4/dsdb/schema/schema_set.c
new file mode 100644 (file)
index 0000000..0ca26c0
--- /dev/null
@@ -0,0 +1,434 @@
+/* 
+   Unix SMB/CIFS mplementation.
+   DSDB schema header
+   
+   Copyright (C) Stefan Metzmacher <metze@samba.org> 2006-2007
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006-2008
+
+   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 3 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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, see <http://www.gnu.org/licenses/>.
+   
+*/
+
+#include "includes.h"
+#include "dsdb/samdb/samdb.h"
+#include "lib/ldb/include/ldb_errors.h"
+#include "lib/ldb/include/ldb_private.h"
+#include "lib/util/dlinklist.h"
+#include "param/param.h"
+
+
+static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schema *schema, bool write_attributes)
+{
+       int ret = LDB_SUCCESS;
+       struct ldb_result *res;
+       struct ldb_result *res_idx;
+       struct dsdb_attribute *attr;
+       struct ldb_message *mod_msg;
+       TALLOC_CTX *mem_ctx = talloc_new(ldb);
+       
+       struct ldb_message *msg;
+       struct ldb_message *msg_idx;
+
+       if (!mem_ctx) {
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       msg = ldb_msg_new(mem_ctx);
+       if (!msg) {
+               ldb_oom(ldb);
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+       msg_idx = ldb_msg_new(mem_ctx);
+       if (!msg_idx) {
+               ldb_oom(ldb);
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+       msg->dn = ldb_dn_new(msg, ldb, "@ATTRIBUTES");
+       if (!msg->dn) {
+               ldb_oom(ldb);
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+       msg_idx->dn = ldb_dn_new(msg, ldb, "@INDEXLIST");
+       if (!msg_idx->dn) {
+               ldb_oom(ldb);
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       for (attr = schema->attributes; attr; attr = attr->next) {
+               const struct ldb_schema_syntax *s;
+               const char *syntax = attr->syntax->ldb_syntax;
+               if (!syntax) {
+                       syntax = attr->syntax->ldap_oid;
+               }
+
+               /* Write out a rough approximation of the schema as an @ATTRIBUTES value, for bootstrapping */
+               if (strcmp(syntax, LDB_SYNTAX_INTEGER) == 0) {
+                       ret = ldb_msg_add_string(msg, attr->lDAPDisplayName, "INTEGER");
+               } else if (strcmp(syntax, LDB_SYNTAX_DIRECTORY_STRING) == 0) {
+                       ret = ldb_msg_add_string(msg, attr->lDAPDisplayName, "CASE_INSENSITIVE");
+               } 
+               if (ret != LDB_SUCCESS) {
+                       return ret;
+               }
+
+               if (attr->searchFlags & SEARCH_FLAG_ATTINDEX) {
+                       ret = ldb_msg_add_string(msg_idx, "@IDXATTR", attr->lDAPDisplayName);
+                       if (ret != LDB_SUCCESS) {
+                               return ret;
+                       }
+               }
+
+               if (!attr->syntax) {
+                       continue;
+               }
+
+               ret = ldb_schema_attribute_add(ldb, attr->lDAPDisplayName, LDB_ATTR_FLAG_FIXED,
+                                              syntax);
+               if (ret != LDB_SUCCESS) {
+                       s = ldb_samba_syntax_by_name(ldb, attr->syntax->ldap_oid);
+                       if (s) {
+                               ret = ldb_schema_attribute_add_with_syntax(ldb, attr->lDAPDisplayName, LDB_ATTR_FLAG_FIXED, s);
+                       } else {
+                               ret = LDB_SUCCESS; /* Nothing to do here */
+                       }
+               }
+               
+               if (ret != LDB_SUCCESS) {
+                       return ret;
+               }
+       }
+
+       if (!write_attributes) {
+               talloc_free(mem_ctx);
+               return ret;
+       }
+
+
+       ret = ldb_transaction_start(ldb);
+       if (ret != LDB_SUCCESS) {
+               return ret;
+       }
+
+       /* Try to avoid churning the attributes too much - we only want to do this if they have changed */
+       ret = ldb_search_exp_fmt(ldb, mem_ctx, &res, msg->dn, LDB_SCOPE_BASE, NULL, "dn=%s", ldb_dn_get_linearized(msg->dn));
+       if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+               ret = ldb_add(ldb, msg);
+       } else if (ret != LDB_SUCCESS) {
+               talloc_free(mem_ctx);
+               ldb_transaction_cancel(ldb);
+               return ret;
+       } else {
+
+               if (res->count != 1) {
+                       talloc_free(mem_ctx);
+                       ldb_transaction_cancel(ldb);
+                       return LDB_ERR_NO_SUCH_OBJECT;
+               }
+               
+               ret = LDB_SUCCESS;
+               /* Annoyingly added to our search results */
+               ldb_msg_remove_attr(res->msgs[0], "distinguishedName");
+
+               mod_msg = ldb_msg_diff(ldb, res->msgs[0], msg);
+               if (mod_msg->num_elements > 0) {
+                       ret = ldb_modify(ldb, mod_msg);
+               }
+       }
+
+       if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
+               /* We might be on a read-only DB */
+               talloc_free(mem_ctx);
+               ret = ldb_transaction_cancel(ldb);
+               return ret;
+       } else if (ret != LDB_SUCCESS) {
+               ldb_transaction_cancel(ldb);
+               return ret;
+       }
+
+       /* Now write out the indexs, as found in the schema (if they have changed) */
+
+       ret = ldb_search_exp_fmt(ldb, mem_ctx, &res_idx, msg_idx->dn, LDB_SCOPE_BASE, NULL, "dn=%s", ldb_dn_get_linearized(msg_idx->dn));
+       if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+               ret = ldb_add(ldb, msg_idx);
+       } else if (ret != LDB_SUCCESS) {
+               talloc_free(mem_ctx);
+               ldb_transaction_cancel(ldb);
+               return ret;
+       } else {
+               if (res_idx->count != 1) {
+                       talloc_free(mem_ctx);
+                       ldb_transaction_cancel(ldb);
+                       return LDB_ERR_NO_SUCH_OBJECT;
+               }
+               
+               /* Annoyingly added to our search results */
+               ldb_msg_remove_attr(res_idx->msgs[0], "distinguishedName");
+
+               mod_msg = ldb_msg_diff(ldb, res_idx->msgs[0], msg_idx);
+               if (mod_msg->num_elements > 0) {
+                       ret = ldb_modify(ldb, mod_msg);
+               }
+       }
+       if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
+               /* We might be on a read-only DB */
+               talloc_free(mem_ctx);
+               return ldb_transaction_cancel(ldb);
+       } else if (ret == LDB_SUCCESS) {
+               ret = ldb_transaction_commit(ldb);
+       } else {
+               ldb_transaction_cancel(ldb);
+       }
+       talloc_free(mem_ctx);
+       return ret;
+}
+
+
+/**
+ * Attach the schema to an opaque pointer on the ldb, so ldb modules
+ * can find it 
+ */
+
+int dsdb_set_schema(struct ldb_context *ldb, struct dsdb_schema *schema)
+{
+       int ret;
+
+       ret = ldb_set_opaque(ldb, "dsdb_schema", schema);
+       if (ret != LDB_SUCCESS) {
+               return ret;
+       }
+
+       /* Set the new attributes based on the new schema */
+       ret = dsdb_schema_set_attributes(ldb, schema, true);
+       if (ret != LDB_SUCCESS) {
+               return ret;
+       }
+
+       talloc_steal(ldb, schema);
+
+       return LDB_SUCCESS;
+}
+
+/**
+ * Global variable to hold one copy of the schema, used to avoid memory bloat
+ */
+static struct dsdb_schema *global_schema;
+
+/**
+ * Make this ldb use the 'global' schema, setup to avoid having multiple copies in this process
+ */
+int dsdb_set_global_schema(struct ldb_context *ldb)
+{
+       int ret;
+       if (!global_schema) {
+               return LDB_SUCCESS;
+       }
+       ret = ldb_set_opaque(ldb, "dsdb_schema", global_schema);
+       if (ret != LDB_SUCCESS) {
+               return ret;
+       }
+
+       /* Set the new attributes based on the new schema */
+       ret = dsdb_schema_set_attributes(ldb, global_schema, false);
+       if (ret != LDB_SUCCESS) {
+               return ret;
+       }
+
+       /* Keep a reference to this schema, just incase the global copy is replaced */
+       if (talloc_reference(ldb, global_schema) == NULL) {
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       return LDB_SUCCESS;
+}
+
+/**
+ * Find the schema object for this ldb
+ */
+
+struct dsdb_schema *dsdb_get_schema(struct ldb_context *ldb)
+{
+       const void *p;
+       struct dsdb_schema *schema;
+
+       /* see if we have a cached copy */
+       p = ldb_get_opaque(ldb, "dsdb_schema");
+       if (!p) {
+               return NULL;
+       }
+
+       schema = talloc_get_type(p, struct dsdb_schema);
+       if (!schema) {
+               return NULL;
+       }
+
+       return schema;
+}
+
+/**
+ * Make the schema found on this ldb the 'global' schema
+ */
+
+void dsdb_make_schema_global(struct ldb_context *ldb)
+{
+       struct dsdb_schema *schema = dsdb_get_schema(ldb);
+       if (!schema) {
+               return;
+       }
+
+       if (global_schema) {
+               talloc_unlink(talloc_autofree_context(), schema);
+       }
+
+       talloc_steal(talloc_autofree_context(), schema);
+       global_schema = schema;
+
+       dsdb_set_global_schema(ldb);
+}
+
+
+/**
+ * Rather than read a schema from the LDB itself, read it from an ldif
+ * file.  This allows schema to be loaded and used while adding the
+ * schema itself to the directory.
+ */
+
+WERROR dsdb_attach_schema_from_ldif_file(struct ldb_context *ldb, const char *pf, const char *df)
+{
+       struct ldb_ldif *ldif;
+       struct ldb_message *msg;
+       TALLOC_CTX *mem_ctx;
+       WERROR status;
+       int ret;
+       struct dsdb_schema *schema;
+       const struct ldb_val *prefix_val;
+       const struct ldb_val *info_val;
+       struct ldb_val info_val_default;
+
+       mem_ctx = talloc_new(ldb);
+       if (!mem_ctx) {
+               goto nomem;
+       }
+
+       schema = dsdb_new_schema(mem_ctx, lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")));
+
+       schema->fsmo.we_are_master = true;
+       schema->fsmo.master_dn = ldb_dn_new_fmt(schema, ldb, "@PROVISION_SCHEMA_MASTER");
+       if (!schema->fsmo.master_dn) {
+               goto nomem;
+       }
+
+       /*
+        * load the prefixMap attribute from pf
+        */
+       ldif = ldb_ldif_read_string(ldb, &pf);
+       if (!ldif) {
+               status = WERR_INVALID_PARAM;
+               goto failed;
+       }
+       talloc_steal(mem_ctx, ldif);
+
+       msg = ldb_msg_canonicalize(ldb, ldif->msg);
+       if (!msg) {
+               goto nomem;
+       }
+       talloc_steal(mem_ctx, msg);
+       talloc_free(ldif);
+
+       prefix_val = ldb_msg_find_ldb_val(msg, "prefixMap");
+       if (!prefix_val) {
+               status = WERR_INVALID_PARAM;
+               goto failed;
+       }
+
+       info_val = ldb_msg_find_ldb_val(msg, "schemaInfo");
+       if (!info_val) {
+               info_val_default = strhex_to_data_blob("FF0000000000000000000000000000000000000000");
+               if (!info_val_default.data) {
+                       goto nomem;
+               }
+               talloc_steal(mem_ctx, info_val_default.data);
+               info_val = &info_val_default;
+       }
+
+       status = dsdb_load_oid_mappings_ldb(schema, prefix_val, info_val);
+       if (!W_ERROR_IS_OK(status)) {
+               goto failed;
+       }
+
+       /*
+        * load the attribute and class definitions outof df
+        */
+       while ((ldif = ldb_ldif_read_string(ldb, &df))) {
+               bool is_sa;
+               bool is_sc;
+
+               talloc_steal(mem_ctx, ldif);
+
+               msg = ldb_msg_canonicalize(ldb, ldif->msg);
+               if (!msg) {
+                       goto nomem;
+               }
+
+               talloc_steal(mem_ctx, msg);
+               talloc_free(ldif);
+
+               is_sa = ldb_msg_check_string_attribute(msg, "objectClass", "attributeSchema");
+               is_sc = ldb_msg_check_string_attribute(msg, "objectClass", "classSchema");
+
+               if (is_sa) {
+                       struct dsdb_attribute *sa;
+
+                       sa = talloc_zero(schema, struct dsdb_attribute);
+                       if (!sa) {
+                               goto nomem;
+                       }
+
+                       status = dsdb_attribute_from_ldb(schema, msg, sa, sa);
+                       if (!W_ERROR_IS_OK(status)) {
+                               goto failed;
+                       }
+
+                       DLIST_ADD_END(schema->attributes, sa, struct dsdb_attribute *);
+               } else if (is_sc) {
+                       struct dsdb_class *sc;
+
+                       sc = talloc_zero(schema, struct dsdb_class);
+                       if (!sc) {
+                               goto nomem;
+                       }
+
+                       status = dsdb_class_from_ldb(schema, msg, sc, sc);
+                       if (!W_ERROR_IS_OK(status)) {
+                               goto failed;
+                       }
+
+                       DLIST_ADD_END(schema->classes, sc, struct dsdb_class *);
+               }
+       }
+
+       ret = dsdb_set_schema(ldb, schema);
+       if (ret != LDB_SUCCESS) {
+               status = WERR_FOOBAR;
+               goto failed;
+       }
+
+       goto done;
+
+nomem:
+       status = WERR_NOMEM;
+failed:
+done:
+       talloc_free(mem_ctx);
+       return status;
+}
index beacfc49c2621694a8c7a073da8c8a52d3848665..97cd0020a973b95ec580499f9cd0cbfda38c5ade 100644 (file)
@@ -3,7 +3,9 @@
    DSDB schema syntaxes
    
    Copyright (C) Stefan Metzmacher <metze@samba.org> 2006
-    
+   Copyright (C) Simo Sorce 2005
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008
+
    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 3 of the License, or
@@ -1109,7 +1111,6 @@ static WERROR dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi(const struct dsdb_
        return WERR_OK;
 }
 
-
 #define OMOBJECTCLASS(val) { .length = sizeof(val) - 1, .data = discard_const_p(uint8_t, val) }
 
 static const struct dsdb_syntax dsdb_syntaxes[] = {
@@ -1120,27 +1121,36 @@ static const struct dsdb_syntax dsdb_syntaxes[] = {
                .attributeSyntax_oid    = "2.5.5.8",
                .drsuapi_to_ldb         = dsdb_syntax_BOOL_drsuapi_to_ldb,
                .ldb_to_drsuapi         = dsdb_syntax_BOOL_ldb_to_drsuapi,
+               .equality               = "booleanMatch",
+               .comment                = "Boolean" 
        },{
                .name                   = "Integer",
-               .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.27",
+               .ldap_oid               = LDB_SYNTAX_INTEGER,
                .oMSyntax               = 2,
                .attributeSyntax_oid    = "2.5.5.9",
                .drsuapi_to_ldb         = dsdb_syntax_INT32_drsuapi_to_ldb,
                .ldb_to_drsuapi         = dsdb_syntax_INT32_ldb_to_drsuapi,
+               .equality               = "integerMatch",
+               .comment                = "Integer",
        },{
                .name                   = "String(Octet)",
-               .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.40",
+               .ldap_oid               = LDB_SYNTAX_OCTET_STRING,
                .oMSyntax               = 4,
                .attributeSyntax_oid    = "2.5.5.10",
                .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
                .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
+               .equality               = "octetStringMatch",
+               .comment                = "Octet String",
        },{
                .name                   = "String(Sid)",
-               .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.40",
+               .ldap_oid               = LDB_SYNTAX_OCTET_STRING,
                .oMSyntax               = 4,
                .attributeSyntax_oid    = "2.5.5.17",
                .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
                .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
+               .equality               = "octetStringMatch",
+               .comment                = "Octet String - Security Identifier (SID)",
+               .ldb_syntax             = LDB_SYNTAX_SAMBA_SID
        },{
                .name                   = "String(Object-Identifier)",
                .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.38",
@@ -1148,9 +1158,12 @@ static const struct dsdb_syntax dsdb_syntaxes[] = {
                .attributeSyntax_oid    = "2.5.5.2",
                .drsuapi_to_ldb         = dsdb_syntax_OID_drsuapi_to_ldb,
                .ldb_to_drsuapi         = dsdb_syntax_OID_ldb_to_drsuapi,
+               .equality               = "caseIgnoreMatch", /* Would use "objectIdentifierMatch" but most are ldap attribute/class names */
+               .comment                = "OID String",
+               .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING
        },{
                .name                   = "Enumeration",
-               .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.27",
+               .ldap_oid               = LDB_SYNTAX_INTEGER,
                .oMSyntax               = 10,
                .attributeSyntax_oid    = "2.5.5.9",
                .drsuapi_to_ldb         = dsdb_syntax_INT32_drsuapi_to_ldb,
@@ -1163,6 +1176,9 @@ static const struct dsdb_syntax dsdb_syntaxes[] = {
                .attributeSyntax_oid    = "2.5.5.6",
                .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
                .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
+               .equality               = "numericStringMatch",
+               .substring              = "numericStringSubstringsMatch",
+               .comment                = "Numeric String" 
        },{
                .name                   = "String(Printable)",
                .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.44",
@@ -1177,6 +1193,10 @@ static const struct dsdb_syntax dsdb_syntaxes[] = {
                .attributeSyntax_oid    = "2.5.5.4",
                .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
                .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
+               .equality               = "caseIgnoreMatch",
+               .substring              = "caseIgnoreSubstringsMatch",
+               .comment                = "Case Insensitive String",
+               .ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
        },{
                .name                   = "String(IA5)",
                .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.26",
@@ -1184,6 +1204,8 @@ static const struct dsdb_syntax dsdb_syntaxes[] = {
                .attributeSyntax_oid    = "2.5.5.5",
                .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
                .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
+               .equality               = "caseExactIA5Match",
+               .comment                = "Printable String"
        },{
                .name                   = "String(UTC-Time)",
                .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.53",
@@ -1191,6 +1213,8 @@ static const struct dsdb_syntax dsdb_syntaxes[] = {
                .attributeSyntax_oid    = "2.5.5.11",
                .drsuapi_to_ldb         = dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb,
                .ldb_to_drsuapi         = dsdb_syntax_NTTIME_UTC_ldb_to_drsuapi,
+               .equality               = "generalizedTimeMatch",
+               .comment                = "UTC Time",
        },{
                .name                   = "String(Generalized-Time)",
                .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.24",
@@ -1198,6 +1222,9 @@ static const struct dsdb_syntax dsdb_syntaxes[] = {
                .attributeSyntax_oid    = "2.5.5.11",
                .drsuapi_to_ldb         = dsdb_syntax_NTTIME_drsuapi_to_ldb,
                .ldb_to_drsuapi         = dsdb_syntax_NTTIME_ldb_to_drsuapi,
+               .equality               = "generalizedTimeMatch",
+               .comment                = "Generalized Time",
+               .ldb_syntax             = LDB_SYNTAX_UTC_TIME,
        },{
        /* not used in w2k3 schema */
                .name                   = "String(Case Sensitive)",
@@ -1208,11 +1235,14 @@ static const struct dsdb_syntax dsdb_syntaxes[] = {
                .ldb_to_drsuapi         = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
        },{
                .name                   = "String(Unicode)",
-               .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.15",
+               .ldap_oid               = LDB_SYNTAX_DIRECTORY_STRING,
                .oMSyntax               = 64,
                .attributeSyntax_oid    = "2.5.5.12",
                .drsuapi_to_ldb         = dsdb_syntax_UNICODE_drsuapi_to_ldb,
                .ldb_to_drsuapi         = dsdb_syntax_UNICODE_ldb_to_drsuapi,
+               .equality               = "caseIgnoreMatch",
+               .substring              = "caseIgnoreSubstringsMatch",
+               .comment                = "Directory String",
        },{
                .name                   = "Interval/LargeInteger",
                .ldap_oid               = "1.2.840.113556.1.4.906",
@@ -1220,21 +1250,26 @@ static const struct dsdb_syntax dsdb_syntaxes[] = {
                .attributeSyntax_oid    = "2.5.5.16",
                .drsuapi_to_ldb         = dsdb_syntax_INT64_drsuapi_to_ldb,
                .ldb_to_drsuapi         = dsdb_syntax_INT64_ldb_to_drsuapi,
+               .equality               = "integerMatch",
+               .comment                = "Large Integer",
+               .ldb_syntax             = LDB_SYNTAX_INTEGER,
        },{
                .name                   = "String(NT-Sec-Desc)",
-               .ldap_oid               = "1.2.840.113556.1.4.907",
+               .ldap_oid               = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
                .oMSyntax               = 66,
                .attributeSyntax_oid    = "2.5.5.15",
                .drsuapi_to_ldb         = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
                .ldb_to_drsuapi         = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
        },{
                .name                   = "Object(DS-DN)",
-               .ldap_oid               = "1.3.6.1.4.1.1466.115.121.1.12",
+               .ldap_oid               = LDB_SYNTAX_DN,
                .oMSyntax               = 127,
                .oMObjectClass          = OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x4a"),
                .attributeSyntax_oid    = "2.5.5.1",
                .drsuapi_to_ldb         = dsdb_syntax_DN_drsuapi_to_ldb,
                .ldb_to_drsuapi         = dsdb_syntax_DN_ldb_to_drsuapi,
+               .equality               = "distinguishedNameMatch",
+               .comment                = "Object(DS-DN) == a DN",
        },{
                .name                   = "Object(DN-Binary)",
                .ldap_oid               = "1.2.840.113556.1.4.903",
@@ -1243,6 +1278,9 @@ static const struct dsdb_syntax dsdb_syntaxes[] = {
                .attributeSyntax_oid    = "2.5.5.7",
                .drsuapi_to_ldb         = dsdb_syntax_DN_BINARY_drsuapi_to_ldb,
                .ldb_to_drsuapi         = dsdb_syntax_DN_BINARY_ldb_to_drsuapi,
+               .equality               = "distinguishedNameMatch",
+               .comment                = "OctetString: Binary+DN",
+               .ldb_syntax             = LDB_SYNTAX_DN,
        },{
        /* not used in w2k3 schema */
                .name                   = "Object(OR-Name)",
@@ -1274,6 +1312,7 @@ static const struct dsdb_syntax dsdb_syntaxes[] = {
                .attributeSyntax_oid    = "2.5.5.13",
                .drsuapi_to_ldb         = dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb,
                .ldb_to_drsuapi         = dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi,
+               .comment                = "Presentation Address" 
        },{
        /* not used in w2k3 schema */
                .name                   = "Object(Access-Point)",
@@ -1283,6 +1322,9 @@ static const struct dsdb_syntax dsdb_syntaxes[] = {
                .attributeSyntax_oid    = "2.5.5.14",
                .drsuapi_to_ldb         = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
                .ldb_to_drsuapi         = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
+               .equality               = "distinguishedNameMatch",
+               .comment                = "OctetString: String+DN",
+               .ldb_syntax             = LDB_SYNTAX_DN,
        },{
        /* not used in w2k3 schema */
                .name                   = "Object(DN-String)",
@@ -1292,9 +1334,42 @@ static const struct dsdb_syntax dsdb_syntaxes[] = {
                .attributeSyntax_oid    = "2.5.5.14",
                .drsuapi_to_ldb         = dsdb_syntax_FOOBAR_drsuapi_to_ldb,
                .ldb_to_drsuapi         = dsdb_syntax_FOOBAR_ldb_to_drsuapi,
+               .ldb_syntax             = LDB_SYNTAX_DN,
        }
 };
 
+const struct dsdb_syntax *find_syntax_map_by_ad_oid(const char *ad_oid) 
+{
+       int i;
+       for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
+               if (strcasecmp(ad_oid, dsdb_syntaxes[i].attributeSyntax_oid) == 0) {
+                       return &dsdb_syntaxes[i];
+               }
+       }
+       return NULL;
+}
+
+const struct dsdb_syntax *find_syntax_map_by_ad_syntax(int oMSyntax) 
+{
+       int i;
+       for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
+               if (oMSyntax == dsdb_syntaxes[i].oMSyntax) {
+                       return &dsdb_syntaxes[i];
+               }
+       }
+       return NULL;
+}
+
+const struct dsdb_syntax *find_syntax_map_by_standard_oid(const char *standard_oid) 
+{
+       int i;
+       for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
+               if (strcasecmp(standard_oid, dsdb_syntaxes[i].ldap_oid) == 0) {
+                       return &dsdb_syntaxes[i];
+               }
+       }
+       return NULL;
+}
 const struct dsdb_syntax *dsdb_syntax_for_attribute(const struct dsdb_attribute *attr)
 {
        uint32_t i;
index 8dbd087da62669129a0c6896630c27544c78ffac..a6f0f31246c03b7772eb0fd42b1cbdbd4e8bea22 100644 (file)
@@ -520,16 +520,30 @@ gsskrb5_acceptor_start(OM_uint32 * minor_status,
     
     if(ctx->flags & GSS_C_MUTUAL_FLAG) {
        krb5_data outbuf;
+       int use_subkey = 0;
            
        _gsskrb5i_is_cfx(ctx, &is_cfx);
            
        if (is_cfx != 0 
            || (ap_options & AP_OPTS_USE_SUBKEY)) {
-           kret = krb5_auth_con_addflags(context,
-                                         ctx->auth_context,
-                                         KRB5_AUTH_CONTEXT_USE_SUBKEY,
-                                         NULL);
+           use_subkey = 1;
+       } else {
+           krb5_keyblock *rkey;
+           kret = krb5_auth_con_getremotesubkey(context, ctx->auth_context, &rkey);
+           if (kret == 0) {
+               kret = krb5_auth_con_setlocalsubkey(context, ctx->auth_context, rkey);
+               if (kret == 0) {
+                   use_subkey = 1;
+               }
+               krb5_free_keyblock(context, rkey);
+           }
+       }
+       if (use_subkey) {
            ctx->more_flags |= ACCEPTOR_SUBKEY;
+           krb5_auth_con_addflags(context,
+                                  ctx->auth_context,
+                                  KRB5_AUTH_CONTEXT_USE_SUBKEY,
+                                  NULL);
        }
            
        kret = krb5_mk_rep(context,
index 6452f802ab84be5bc7a9431d15cc135a3e9bca2f..bc0d736e81ac8230bb7e97da71722a2fc0c80c2e 100755 (executable)
@@ -43,7 +43,8 @@ RCSID("$Id: cfx.c 19031 2006-11-13 18:02:57Z lha $");
 #define CFXAcceptorSubkey      (1 << 2)
 
 krb5_error_code
-_gsskrb5cfx_wrap_length_cfx(krb5_context context,
+_gsskrb5cfx_wrap_length_cfx(const gsskrb5_ctx context_handle,
+                           krb5_context context,
                            krb5_crypto crypto,
                            int conf_req_flag,
                            size_t input_length,
@@ -72,7 +73,11 @@ _gsskrb5cfx_wrap_length_cfx(krb5_context context,
        /* Header is concatenated with data before encryption */
        input_length += sizeof(gss_cfx_wrap_token_desc);
 
-       ret = krb5_crypto_getpadsize(context, crypto, &padsize);
+       if (IS_DCE_STYLE(context_handle)) {
+               ret = krb5_crypto_getblocksize(context, crypto, &padsize);
+       } else {
+               ret = krb5_crypto_getpadsize(context, crypto, &padsize);
+       }
        if (ret) {
            return ret;
        }
@@ -258,7 +263,7 @@ OM_uint32 _gssapi_wrap_cfx(OM_uint32 *minor_status,
        return GSS_S_FAILURE;
     }
 
-    ret = _gsskrb5cfx_wrap_length_cfx(context,
+    ret = _gsskrb5cfx_wrap_length_cfx(context_handle, context,
                                      crypto, conf_req_flag, 
                                      input_message_buffer->length,
                                      &wrapped_len, &cksumsize, &padlength);
@@ -380,7 +385,15 @@ OM_uint32 _gssapi_wrap_cfx(OM_uint32 *minor_status,
        token->RRC[0] = (rrc >> 8) & 0xFF;  
        token->RRC[1] = (rrc >> 0) & 0xFF;
 
-       ret = rrc_rotate(cipher.data, cipher.length, rrc, FALSE);
+       /*
+        * this is really ugly, but needed against windows
+        * for DCERPC, as windows rotates by EC+RRC.
+        */
+       if (IS_DCE_STYLE(context_handle)) {
+               ret = rrc_rotate(cipher.data, cipher.length, rrc+padlength, FALSE);
+       } else {
+               ret = rrc_rotate(cipher.data, cipher.length, rrc, FALSE);
+       }
        if (ret != 0) {
            *minor_status = ret;
            krb5_crypto_destroy(context, crypto);
@@ -553,14 +566,21 @@ OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status,
     len = input_message_buffer->length;
     len -= (p - (u_char *)input_message_buffer->value);
 
-    /* Rotate by RRC; bogus to do this in-place XXX */
-    *minor_status = rrc_rotate(p, len, rrc, TRUE);
-    if (*minor_status != 0) {
-       krb5_crypto_destroy(context, crypto);
-       return GSS_S_FAILURE;
-    }
-
     if (token_flags & CFXSealed) {
+       /*
+        * this is really ugly, but needed against windows
+        * for DCERPC, as windows rotates by EC+RRC.
+        */
+       if (IS_DCE_STYLE(context_handle)) {
+               *minor_status = rrc_rotate(p, len, rrc+ec, TRUE);
+       } else {
+               *minor_status = rrc_rotate(p, len, rrc, TRUE);
+       }
+       if (*minor_status != 0) {
+           krb5_crypto_destroy(context, crypto);
+           return GSS_S_FAILURE;
+       }
+
        ret = krb5_decrypt(context, crypto, usage,
            p, len, &data);
        if (ret != 0) {
@@ -594,6 +614,13 @@ OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status,
     } else {
        Checksum cksum;
 
+       /* Rotate by RRC; bogus to do this in-place XXX */
+       *minor_status = rrc_rotate(p, len, rrc, TRUE);
+       if (*minor_status != 0) {
+           krb5_crypto_destroy(context, crypto);
+           return GSS_S_FAILURE;
+       }
+
        /* Determine checksum type */
        ret = krb5_crypto_get_checksum_type(context,
                                            crypto, &cksum.cksumtype);
index 64a0dd36b19d9cd6d0ed083915ac6a6f4a9a266a..f6edb8b247630b8e2ac3bf861355358ac3f8cb02 100644 (file)
@@ -661,6 +661,7 @@ _gsskrb5cfx_max_wrap_length_cfx (
 
 krb5_error_code
 _gsskrb5cfx_wrap_length_cfx (
+       const gsskrb5_ctx /*context_handle*/,
        krb5_context /*context*/,
        krb5_crypto /*crypto*/,
        int /*conf_req_flag*/,
index eec4078a706017102c3a12e63a0072e84de13283..c287469e96b4e0bbd8e77969f2614ec028142d59 100644 (file)
@@ -59,10 +59,17 @@ unwrap_des
   OM_uint32 ret;
   int cstate;
   int cmp;
+  int token_len;
+
+  if (IS_DCE_STYLE(context_handle)) {
+     token_len = 22 + 8 + 15; /* 45 */
+  } else {
+     token_len = input_message_buffer->length;
+  }
 
   p = input_message_buffer->value;
   ret = _gsskrb5_verify_header (&p,
-                                  input_message_buffer->length,
+                                  token_len,
                                   "\x02\x01",
                                   GSS_KRB5_MECHANISM);
   if (ret)
@@ -105,12 +112,17 @@ unwrap_des
       memset (deskey, 0, sizeof(deskey));
       memset (&schedule, 0, sizeof(schedule));
   }
-  /* check pad */
-  ret = _gssapi_verify_pad(input_message_buffer, 
-                          input_message_buffer->length - len,
-                          &padlength);
-  if (ret)
-      return ret;
+
+  if (IS_DCE_STYLE(context_handle)) {
+    padlength = 0;
+  } else {
+    /* check pad */
+    ret = _gssapi_verify_pad(input_message_buffer,
+                            input_message_buffer->length - len,
+                            &padlength);
+    if (ret)
+        return ret;
+  }
 
   MD5_Init (&md5);
   MD5_Update (&md5, p - 24, 8);
@@ -195,10 +207,17 @@ unwrap_des3
   krb5_crypto crypto;
   Checksum csum;
   int cmp;
+  int token_len;
+
+  if (IS_DCE_STYLE(context_handle)) {
+     token_len = 34 + 8 + 15; /* 57 */
+  } else {
+     token_len = input_message_buffer->length;
+  }
 
   p = input_message_buffer->value;
   ret = _gsskrb5_verify_header (&p,
-                                  input_message_buffer->length,
+                                  token_len,
                                   "\x02\x01",
                                   GSS_KRB5_MECHANISM);
   if (ret)
@@ -245,12 +264,17 @@ unwrap_des3
       memcpy (p, tmp.data, tmp.length);
       krb5_data_free(&tmp);
   }
-  /* check pad */
-  ret = _gssapi_verify_pad(input_message_buffer, 
-                          input_message_buffer->length - len,
-                          &padlength);
-  if (ret)
-      return ret;
+
+  if (IS_DCE_STYLE(context_handle)) {
+    padlength = 0;
+  } else {
+    /* check pad */
+    ret = _gssapi_verify_pad(input_message_buffer,
+                            input_message_buffer->length - len,
+                            &padlength);
+    if (ret)
+        return ret;
+  }
 
   /* verify sequence number */
   
index 6d00f2adcfbadf708d1b43e397cdd4b371e0fd42..bedeace4dd88f1c5c0c8fb7c168692bf055ecdea 100644 (file)
@@ -210,10 +210,19 @@ wrap_des
   int32_t seq_number;
   size_t len, total_len, padlength, datalen;
 
-  padlength = 8 - (input_message_buffer->length % 8);
-  datalen = input_message_buffer->length + padlength + 8;
-  len = datalen + 22;
-  _gsskrb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM);
+  if (IS_DCE_STYLE(ctx)) {
+    padlength = 0;
+    datalen = input_message_buffer->length;
+    len = 22 + 8;
+    _gsskrb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM);
+    total_len += datalen;
+    datalen += 8;
+  } else {
+    padlength = 8 - (input_message_buffer->length % 8);
+    datalen = input_message_buffer->length + padlength + 8;
+    len = datalen + 22;
+    _gsskrb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM);
+  }
 
   output_message_buffer->length = total_len;
   output_message_buffer->value  = malloc (total_len);
@@ -336,10 +345,19 @@ wrap_des3
   Checksum cksum;
   krb5_data encdata;
 
-  padlength = 8 - (input_message_buffer->length % 8);
-  datalen = input_message_buffer->length + padlength + 8;
-  len = datalen + 34;
-  _gsskrb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM);
+  if (IS_DCE_STYLE(ctx)) {
+    padlength = 0;
+    datalen = input_message_buffer->length;
+    len = 34 + 8;
+    _gsskrb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM);
+    total_len += datalen;
+    datalen += 8;
+  } else {
+    padlength = 8 - (input_message_buffer->length % 8);
+    datalen = input_message_buffer->length + padlength + 8;
+    len = datalen + 34;
+    _gsskrb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM);
+  }
 
   output_message_buffer->length = total_len;
   output_message_buffer->value  = malloc (total_len);
index 8f8ce3074b86d2cbf1ce09710aefdbc29fa2b1df..ef3a0bcb8ac0901ea413cebef7daa68dc4a0909b 100644 (file)
 #include "dsdb/samdb/samdb.h"
 #include "librpc/ndr/libndr.h"
 #include "librpc/gen_ndr/ndr_drsblobs.h"
+#include "librpc/gen_ndr/lsa.h"
 #include "libcli/auth/libcli_auth.h"
 #include "param/param.h"
 #include "events/events.h"
 #include "kdc/kdc.h"
+#include "lib/crypto/md4.h"
 
 enum hdb_ldb_ent_type 
 { HDB_LDB_ENT_TYPE_CLIENT, HDB_LDB_ENT_TYPE_SERVER, 
-  HDB_LDB_ENT_TYPE_KRBTGT, HDB_LDB_ENT_TYPE_ANY };
+  HDB_LDB_ENT_TYPE_KRBTGT, HDB_LDB_ENT_TYPE_TRUST, HDB_LDB_ENT_TYPE_ANY };
+
+enum trust_direction {
+       UNKNOWN = 0,
+       INBOUND = LSA_TRUST_DIRECTION_INBOUND, 
+       OUTBOUND = LSA_TRUST_DIRECTION_OUTBOUND
+};
 
 static const char *realm_ref_attrs[] = {
        "nCName", 
@@ -60,6 +68,18 @@ static const char *realm_ref_attrs[] = {
        NULL
 };
 
+static const char *trust_attrs[] = {
+       "trustPartner",
+       "trustAuthIncoming",
+       "trustAuthOutgoing",
+       "whenCreated",
+       "msDS-SupportedEncryptionTypes",
+       "trustAttributes",
+       "trustDirection",
+       "trustType",
+       NULL
+};
+
 static KerberosTime ldb_msg_find_krb5time_ldap_time(struct ldb_message *msg, const char *attr, KerberosTime default_val)
 {
     const char *tmp;
@@ -675,6 +695,187 @@ out:
        return ret;
 }
 
+/*
+ * Construct an hdb_entry from a directory entry.
+ */
+static krb5_error_code LDB_trust_message2entry(krb5_context context, HDB *db, 
+                                              struct loadparm_context *lp_ctx,
+                                              TALLOC_CTX *mem_ctx, krb5_const_principal principal,
+                                              enum trust_direction direction,
+                                              struct ldb_message *msg,
+                                              hdb_entry_ex *entry_ex)
+{
+       
+       const char *dnsdomain;
+       char *realm;
+       char *strdup_realm;
+       DATA_BLOB password_utf16;
+       struct samr_Password password_hash;
+       const struct ldb_val *password_val;
+       struct trustAuthInOutBlob password_blob;
+       struct hdb_ldb_private *private;
+
+       enum ndr_err_code ndr_err;
+       int i, ret, trust_direction_flags;
+
+       private = talloc(mem_ctx, struct hdb_ldb_private);
+       if (!private) {
+               ret = ENOMEM;
+               goto out;
+       }
+
+       private->entry_ex = entry_ex;
+       private->iconv_convenience = lp_iconv_convenience(lp_ctx);
+       private->netbios_name = lp_netbios_name(lp_ctx);
+
+       talloc_set_destructor(private, hdb_ldb_destrutor);
+
+       entry_ex->ctx = private;
+       entry_ex->free_entry = hdb_ldb_free_entry;
+
+       /* use 'whenCreated' */
+       entry_ex->entry.created_by.time = ldb_msg_find_krb5time_ldap_time(msg, "whenCreated", 0);
+       /* use '???' */
+       entry_ex->entry.created_by.principal = NULL;
+
+       entry_ex->entry.valid_start = NULL;
+
+       trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
+
+       if (direction == INBOUND) {
+               realm = strupper_talloc(mem_ctx, lp_realm(lp_ctx));
+               password_val = ldb_msg_find_ldb_val(msg, "trustAuthIncoming");
+
+       } else { /* OUTBOUND */
+               dnsdomain = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
+               realm = strupper_talloc(mem_ctx, dnsdomain);
+               password_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
+       }
+
+       if (!password_val || !(trust_direction_flags & direction)) {
+               ret = ENOENT;
+               goto out;
+       }
+
+       ndr_err = ndr_pull_struct_blob_all(password_val, mem_ctx, private->iconv_convenience, &password_blob,
+                                          (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               ret = EINVAL;
+               goto out;
+       }
+
+       for (i=0; i < password_blob.count; i++) {
+               if (password_blob.current->array[i].AuthType == TRUST_AUTH_TYPE_CLEAR) {
+                       password_utf16 = data_blob_const(password_blob.current->array[i].AuthInfo.clear.password,
+                                                        password_blob.current->array[i].AuthInfo.clear.size);
+                       /* In the future, generate all sorts of
+                        * hashes, but for now we can't safely convert
+                        * the random strings windows uses into
+                        * utf8 */
+
+                       /* but as it is utf16 already, we can get the NT password/arcfour-hmac-md5 key */
+                       mdfour(password_hash.hash, password_utf16.data, password_utf16.length);
+                       break;
+               } else if (password_blob.current->array[i].AuthType == TRUST_AUTH_TYPE_NT4OWF) {
+                       password_hash = password_blob.current->array[i].AuthInfo.nt4owf.password;
+                       break;
+               }
+       }
+       entry_ex->entry.keys.len = 0;
+       entry_ex->entry.keys.val = NULL;
+
+       if (i < password_blob.count) {
+               Key key;
+               /* Must have found a cleartext or MD4 password */
+               entry_ex->entry.keys.val = calloc(1, sizeof(Key));
+
+               key.mkvno = 0;
+               key.salt = NULL; /* No salt for this enc type */
+
+               if (entry_ex->entry.keys.val == NULL) {
+                       ret = ENOMEM;
+                       goto out;
+               }
+               
+               ret = krb5_keyblock_init(context,
+                                        ENCTYPE_ARCFOUR_HMAC_MD5,
+                                        password_hash.hash, sizeof(password_hash.hash), 
+                                        &key.key);
+               
+               entry_ex->entry.keys.val[entry_ex->entry.keys.len] = key;
+               entry_ex->entry.keys.len++;
+       }
+               
+       ret = copy_Principal(principal, entry_ex->entry.principal);
+       if (ret) {
+               krb5_clear_error_string(context);
+               goto out;
+       }
+       
+       /* While we have copied the client principal, tests
+        * show that Win2k3 returns the 'corrected' realm, not
+        * the client-specified realm.  This code attempts to
+        * replace the client principal's realm with the one
+        * we determine from our records */
+       
+       /* this has to be with malloc() */
+       strdup_realm = strdup(realm);
+       if (!strdup_realm) {
+               ret = ENOMEM;
+               krb5_clear_error_string(context);
+               goto out;
+       }
+       free(*krb5_princ_realm(context, entry_ex->entry.principal));
+       krb5_princ_set_realm(context, entry_ex->entry.principal, &strdup_realm);
+       
+       entry_ex->entry.flags = int2HDBFlags(0);
+       entry_ex->entry.flags.immutable = 1;
+       entry_ex->entry.flags.invalid = 0;
+       entry_ex->entry.flags.server = 1;
+       entry_ex->entry.flags.require_preauth = 1;
+
+       entry_ex->entry.pw_end = NULL;
+                       
+       entry_ex->entry.max_life = NULL;
+
+       entry_ex->entry.max_renew = NULL;
+
+       entry_ex->entry.generation = NULL;
+
+       entry_ex->entry.etypes = malloc(sizeof(*(entry_ex->entry.etypes)));
+       if (entry_ex->entry.etypes == NULL) {
+               krb5_clear_error_string(context);
+               ret = ENOMEM;
+               goto out;
+       }
+       entry_ex->entry.etypes->len = entry_ex->entry.keys.len;
+       entry_ex->entry.etypes->val = calloc(entry_ex->entry.etypes->len, sizeof(int));
+       if (entry_ex->entry.etypes->val == NULL) {
+               krb5_clear_error_string(context);
+               ret = ENOMEM;
+               goto out;
+       }
+       for (i=0; i < entry_ex->entry.etypes->len; i++) {
+               entry_ex->entry.etypes->val[i] = entry_ex->entry.keys.val[i].key.keytype;
+       }
+
+
+       private->msg = talloc_steal(private, msg);
+       private->realm_ref_msg = NULL;
+       private->samdb = (struct ldb_context *)db->hdb_db;
+       
+out:
+       if (ret != 0) {
+               /* This doesn't free ent itself, that is for the eventual caller to do */
+               hdb_free_entry(context, entry_ex);
+       } else {
+               talloc_steal(db, entry_ex->ctx);
+       }
+
+       return ret;
+
+}
+
 static krb5_error_code LDB_lookup_principal(krb5_context context, struct ldb_context *ldb_ctx,                                         
                                            TALLOC_CTX *mem_ctx,
                                            krb5_const_principal principal,
@@ -709,8 +910,7 @@ static krb5_error_code LDB_lookup_principal(krb5_context context, struct ldb_con
 
        switch (ent_type) {
        case HDB_LDB_ENT_TYPE_CLIENT:
-               /* Can't happen */
-               return EINVAL;
+       case HDB_LDB_ENT_TYPE_TRUST:
        case HDB_LDB_ENT_TYPE_ANY:
                /* Can't happen */
                return EINVAL;
@@ -745,6 +945,40 @@ static krb5_error_code LDB_lookup_principal(krb5_context context, struct ldb_con
        return 0;
 }
 
+static krb5_error_code LDB_lookup_trust(krb5_context context, struct ldb_context *ldb_ctx,                                     
+                                       TALLOC_CTX *mem_ctx,
+                                       const char *realm,
+                                       struct ldb_dn *realm_dn,
+                                       struct ldb_message ***pmsg)
+{
+       int lret;
+       char *filter = NULL;
+       const char * const *attrs = trust_attrs;
+
+       struct ldb_result *res = NULL;
+       filter = talloc_asprintf(mem_ctx, "(&(objectClass=trustedDomain)(|(flatname=%s)(trustPartner=%s)))", realm, realm);
+
+       if (!filter) {
+               krb5_set_error_string(context, "talloc_asprintf: out of memory");
+               return ENOMEM;
+       }
+
+       lret = ldb_search(ldb_ctx, ldb_get_default_basedn(ldb_ctx), LDB_SCOPE_SUBTREE, filter, attrs, &res);
+
+       if (lret != LDB_SUCCESS) {
+               DEBUG(3, ("Failed to search for %s: %s\n", filter, ldb_errstring(ldb_ctx)));
+               return HDB_ERR_NOENTRY;
+       } else if (res->count == 0 || res->count > 1) {
+               DEBUG(3, ("Failed find a single entry for %s: got %d\n", filter, res->count));
+               talloc_free(res);
+               return HDB_ERR_NOENTRY;
+       }
+       talloc_steal(mem_ctx, res->msgs);
+       *pmsg = res->msgs;
+       talloc_free(res);
+       return 0;
+}
+
 static krb5_error_code LDB_lookup_realm(krb5_context context, struct ldb_context *ldb_ctx, 
                                        TALLOC_CTX *mem_ctx,
                                        const char *realm,
@@ -853,8 +1087,10 @@ static krb5_error_code LDB_fetch_krbtgt(krb5_context context, HDB *db,
 {
        krb5_error_code ret;
        struct ldb_message **msg = NULL;
-       struct ldb_message **realm_ref_msg = NULL;
+       struct ldb_message **realm_ref_msg_1 = NULL;
+       struct ldb_message **realm_ref_msg_2 = NULL;
        struct ldb_dn *realm_dn;
+       const char *realm;
 
        krb5_principal alloc_principal = NULL;
        if (principal->name.name_string.len != 2
@@ -864,14 +1100,18 @@ static krb5_error_code LDB_fetch_krbtgt(krb5_context context, HDB *db,
        }
 
        /* krbtgt case.  Either us or a trusted realm */
+
        if ((LDB_lookup_realm(context, (struct ldb_context *)db->hdb_db,
-                             mem_ctx, principal->name.name_string.val[1], &realm_ref_msg) == 0)) {
+                             mem_ctx, principal->realm, &realm_ref_msg_1) == 0)
+           && (LDB_lookup_realm(context, (struct ldb_context *)db->hdb_db,
+                                mem_ctx, principal->name.name_string.val[1], &realm_ref_msg_2) == 0)
+           && (ldb_dn_compare(realm_ref_msg_1[0]->dn, realm_ref_msg_1[0]->dn) == 0)) {
                /* us */                
                /* Cludge, cludge cludge.  If the realm part of krbtgt/realm,
                 * is in our db, then direct the caller at our primary
-                * krgtgt */
+                * krbtgt */
                
-               const char *dnsdomain = ldb_msg_find_attr_as_string(realm_ref_msg[0], "dnsRoot", NULL);
+               const char *dnsdomain = ldb_msg_find_attr_as_string(realm_ref_msg_1[0], "dnsRoot", NULL);
                char *realm_fixed = strupper_talloc(mem_ctx, dnsdomain);
                if (!realm_fixed) {
                        krb5_set_error_string(context, "strupper_talloc: out of memory");
@@ -891,31 +1131,69 @@ static krb5_error_code LDB_fetch_krbtgt(krb5_context context, HDB *db,
                        return ENOMEM;
                }
                principal = alloc_principal;
-               realm_dn = samdb_result_dn((struct ldb_context *)db->hdb_db, mem_ctx, realm_ref_msg[0], "nCName", NULL);
+               realm_dn = samdb_result_dn((struct ldb_context *)db->hdb_db, mem_ctx, realm_ref_msg_1[0], "nCName", NULL);
+               
+               ret = LDB_lookup_principal(context, (struct ldb_context *)db->hdb_db, 
+                                          mem_ctx, 
+                                          principal, HDB_LDB_ENT_TYPE_KRBTGT, realm_dn, &msg);
+               
+               if (ret != 0) {
+                       krb5_warnx(context, "LDB_fetch: could not find principal in DB");
+                       krb5_set_error_string(context, "LDB_fetch: could not find principal in DB");
+                       return ret;
+               }
+               
+               ret = LDB_message2entry(context, db, mem_ctx, 
+                                       principal, HDB_LDB_ENT_TYPE_KRBTGT, 
+                                       msg[0], realm_ref_msg_1[0], entry_ex);
+               if (ret != 0) {
+                       krb5_warnx(context, "LDB_fetch: message2entry failed"); 
+               }
+               return ret;
+
        } else {
-               /* we should lookup trusted domains */
-               return HDB_ERR_NOENTRY;
-       }
+               enum trust_direction direction = UNKNOWN;
 
-       realm_dn = samdb_result_dn((struct ldb_context *)db->hdb_db, mem_ctx, realm_ref_msg[0], "nCName", NULL);
-       
-       ret = LDB_lookup_principal(context, (struct ldb_context *)db->hdb_db, 
-                                  mem_ctx, 
-                                  principal, HDB_LDB_ENT_TYPE_KRBTGT, realm_dn, &msg);
-       
-       if (ret != 0) {
-               krb5_warnx(context, "LDB_fetch: could not find principal in DB");
-               krb5_set_error_string(context, "LDB_fetch: could not find principal in DB");
+               struct loadparm_context *lp_ctx = talloc_get_type(ldb_get_opaque(db->hdb_db, "loadparm"), struct loadparm_context);
+               /* Either an inbound or outbound trust */
+
+               if (strcasecmp(lp_realm(lp_ctx), principal->realm) == 0) {
+                       /* look for inbound trust */
+                       direction = INBOUND;
+                       realm = principal->name.name_string.val[1];
+               }
+
+               if (strcasecmp(lp_realm(lp_ctx), principal->name.name_string.val[1]) == 0) {
+                       /* look for outbound trust */
+                       direction = OUTBOUND;
+                       realm = principal->realm;
+               }
+
+               /* Trusted domains are under CN=system */
+               
+               ret = LDB_lookup_trust(context, (struct ldb_context *)db->hdb_db, 
+                                      mem_ctx, 
+                                      realm, realm_dn, &msg);
+               
+               if (ret != 0) {
+                       krb5_warnx(context, "LDB_fetch: could not find principal in DB");
+                       krb5_set_error_string(context, "LDB_fetch: could not find principal in DB");
+                       return ret;
+               }
+               
+               ret = LDB_trust_message2entry(context, db, lp_ctx, mem_ctx, 
+                                             principal, direction, 
+                                             msg[0], entry_ex);
+               if (ret != 0) {
+                       krb5_warnx(context, "LDB_fetch: message2entry failed"); 
+               }
                return ret;
-       }
 
-       ret = LDB_message2entry(context, db, mem_ctx, 
-                               principal, HDB_LDB_ENT_TYPE_KRBTGT, 
-                               msg[0], realm_ref_msg[0], entry_ex);
-       if (ret != 0) {
-               krb5_warnx(context, "LDB_fetch: message2entry failed"); 
+               
+               /* we should lookup trusted domains */
+               return HDB_ERR_NOENTRY;
        }
-       return ret;
+
 }
 
 static krb5_error_code LDB_fetch_server(krb5_context context, HDB *db, 
@@ -1022,10 +1300,13 @@ static krb5_error_code LDB_fetch(krb5_context context, HDB *db,
                if (ret != HDB_ERR_NOENTRY) goto done;
        }
        if (flags & HDB_F_GET_SERVER) {
-               ret = LDB_fetch_server(context, db, mem_ctx, principal, flags, entry_ex);
-               if (ret != HDB_ERR_NOENTRY) goto done;
+               /* krbtgt fits into this situation for trusted realms, and for resolving different versions of our own realm name */
                ret = LDB_fetch_krbtgt(context, db, mem_ctx, principal, flags, entry_ex);
                if (ret != HDB_ERR_NOENTRY) goto done;
+
+               /* We return 'no entry' if it does not start with krbtgt/, so move to the common case quickly */
+               ret = LDB_fetch_server(context, db, mem_ctx, principal, flags, entry_ex);
+               if (ret != HDB_ERR_NOENTRY) goto done;
        }
        if (flags & HDB_F_GET_KRBTGT) {
                ret = LDB_fetch_krbtgt(context, db, mem_ctx, principal, flags, entry_ex);
index cab1446ff356a4e5edccaa9f6c19fc0f3260b64c..bee271eaa939fe869aa552f7c7d00423bb2b07c9 100644 (file)
@@ -51,7 +51,7 @@ static krb5_error_code make_pac(krb5_context context,
                                struct auth_serversupplied_info *server_info,
                                krb5_pac *pac) 
 {
-       struct PAC_LOGON_INFO_CTR logon_info;
+       union PAC_INFO info;
        struct netr_SamInfo3 *info3;
        krb5_data pac_data;
        NTSTATUS nt_status;
@@ -59,7 +59,7 @@ static krb5_error_code make_pac(krb5_context context,
        DATA_BLOB pac_out;
        krb5_error_code ret;
 
-       ZERO_STRUCT(logon_info);
+       ZERO_STRUCT(info);
 
        nt_status = auth_convert_server_info_saminfo3(mem_ctx, server_info, &info3);
        if (!NT_STATUS_IS_OK(nt_status)) {
@@ -67,15 +67,16 @@ static krb5_error_code make_pac(krb5_context context,
                return EINVAL;
        }
 
-       logon_info.info = talloc_zero(mem_ctx, struct PAC_LOGON_INFO);
+       info.logon_info.info = talloc_zero(mem_ctx, struct PAC_LOGON_INFO);
        if (!mem_ctx) {
                return ENOMEM;
        }
 
-       logon_info.info->info3 = *info3;
+       info.logon_info.info->info3 = *info3;
 
-       ndr_err = ndr_push_struct_blob(&pac_out, mem_ctx, iconv_convenience, &logon_info,
-                                      (ndr_push_flags_fn_t)ndr_push_PAC_LOGON_INFO_CTR);
+       ndr_err = ndr_push_union_blob(&pac_out, mem_ctx, iconv_convenience, &info,
+                                     PAC_TYPE_LOGON_INFO,
+                                     (ndr_push_flags_fn_t)ndr_push_PAC_INFO);
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                nt_status = ndr_map_error2ntstatus(ndr_err);
                DEBUG(1, ("PAC (presig) push failed: %s\n", nt_errstr(nt_status)));
@@ -162,7 +163,7 @@ krb5_error_code samba_kdc_reget_pac(void *priv, krb5_context context,
        krb5_data k5pac_in;
        DATA_BLOB pac_in;
 
-       struct PAC_LOGON_INFO_CTR logon_info;
+       union PAC_INFO info;
        union netr_Validation validation;
        struct auth_serversupplied_info *server_info_out;
 
@@ -191,9 +192,10 @@ krb5_error_code samba_kdc_reget_pac(void *priv, krb5_context context,
                return ENOMEM;
        }
                
-       ndr_err = ndr_pull_struct_blob(&pac_in, mem_ctx, private->iconv_convenience, &logon_info,
-                                      (ndr_pull_flags_fn_t)ndr_pull_PAC_LOGON_INFO_CTR);
-       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err) || !logon_info.info) {
+       ndr_err = ndr_pull_union_blob(&pac_in, mem_ctx, private->iconv_convenience, &info,
+                                     PAC_TYPE_LOGON_INFO,
+                                     (ndr_pull_flags_fn_t)ndr_pull_PAC_INFO);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err) || !info.logon_info.info) {
                nt_status = ndr_map_error2ntstatus(ndr_err);
                DEBUG(0,("can't parse the PAC LOGON_INFO: %s\n", nt_errstr(nt_status)));
                talloc_free(mem_ctx);
@@ -201,7 +203,7 @@ krb5_error_code samba_kdc_reget_pac(void *priv, krb5_context context,
        }
 
        /* Pull this right into the normal auth sysstem structures */
-       validation.sam3 = &logon_info.info->info3;
+       validation.sam3 = &info.logon_info.info->info3;
        nt_status = make_server_info_netlogon_validation(mem_ctx,
                                                         "",
                                                         3, &validation,
index b86df5dc9f48d3443c9f65bd2acbad8a2131a30c..4d076684cd0e5e64df0dacd69aa7e8367681ac65 100644 (file)
@@ -1,6 +1,6 @@
-[SUBSYSTEM::LIBCOMPRESSION]
+[SUBSYSTEM::LZXPRESS]
 
-LIBCOMPRESSION_OBJ_FILES = $(libcompressionsrcdir)/mszip.o
+LZXPRESS_OBJ_FILES = $(libcompressionsrcdir)/lzxpress.o
 
 [SUBSYSTEM::GENCACHE]
 PRIVATE_DEPENDENCIES = TDB_WRAP
index baa7df532b6d78fa1c5db0aa53138f13ba5edf96..c49745cd7f1799a2897483e7bbcb625941ff891b 100644 (file)
@@ -97,6 +97,7 @@ size_t count_chars_w(const char *s, char c);
 void strupper_m(char *s);
 void strlower_m(char *s);
 char *strupper_talloc(TALLOC_CTX *ctx, const char *src);
+char *strupper_talloc_n(TALLOC_CTX *ctx, const char *src, size_t n);
 char *strlower_talloc(TALLOC_CTX *ctx, const char *src);
 bool strhasupper(const char *string);
 bool strhaslower(const char *string);
index 4f4bc8fd2da70c9f9d5bb75b2ee0f946516c996a..d4f930b4622dc8893d4f58acd6a743374d5caf9d 100644 (file)
@@ -469,6 +469,9 @@ static size_t iconv_copy(void *cd, const char **inbuf, size_t *inbytesleft,
        return 0;
 }
 
+/*
+  this takes a UTF8 sequence and produces a UTF16 sequence
+ */
 static size_t utf8_pull(void *cd, const char **inbuf, size_t *inbytesleft,
                         char **outbuf, size_t *outbytesleft)
 {
@@ -586,6 +589,10 @@ error:
        return -1;
 }
 
+
+/*
+  this takes a UTF16 sequence and produces a UTF8 sequence
+ */
 static size_t utf8_push(void *cd, const char **inbuf, size_t *inbytesleft,
                        char **outbuf, size_t *outbytesleft)
 {
index 19a4f3236cfdedcdc5cffe9541d7b9cb427021c8..09ec7b04716d1db271fd906f6cf94ab53e869a3e 100644 (file)
@@ -518,8 +518,9 @@ _PUBLIC_ char *strlower_talloc(TALLOC_CTX *ctx, const char *src)
 
 /**
  Convert a string to UPPER case, allocated with talloc
+ source length limited to n bytes
 **/
-_PUBLIC_ char *strupper_talloc(TALLOC_CTX *ctx, const char *src)
+_PUBLIC_ char *strupper_talloc_n(TALLOC_CTX *ctx, const char *src, size_t n)
 {
        size_t size=0;
        char *dest;
@@ -531,12 +532,12 @@ _PUBLIC_ char *strupper_talloc(TALLOC_CTX *ctx, const char *src)
 
        /* this takes advantage of the fact that upper/lower can't
           change the length of a character by more than 1 byte */
-       dest = talloc_array(ctx, char, 2*(strlen(src))+1);
+       dest = talloc_array(ctx, char, 2*(n+1));
        if (dest == NULL) {
                return NULL;
        }
 
-       while (*src) {
+       while (*src && n--) {
                size_t c_size;
                codepoint_t c = next_codepoint(iconv_convenience, src, &c_size);
                src += c_size;
@@ -561,6 +562,16 @@ _PUBLIC_ char *strupper_talloc(TALLOC_CTX *ctx, const char *src)
        return dest;
 }
 
+/**
+ Convert a string to UPPER case, allocated with talloc
+**/
+_PUBLIC_ char *strupper_talloc(TALLOC_CTX *ctx, const char *src)
+{
+       return strupper_talloc_n(ctx, src, src?strlen(src):0);
+}
+
+
+
 /**
  Convert a string to lower case.
 **/
diff --git a/source4/lib/compression/lzxpress.c b/source4/lib/compression/lzxpress.c
new file mode 100644 (file)
index 0000000..5063051
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) Matthieu Suiche 2008
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include "includes.h"
+#include "replace.h"
+#include "lzxpress.h"
+
+
+#define __BUF_POS_CONST(buf,ofs)(((const uint8_t *)buf)+(ofs))
+#define __PULL_BYTE(buf,ofs) \
+       ((uint8_t)((*__BUF_POS_CONST(buf,ofs)) & 0xFF))
+
+#ifndef PULL_LE_UINT16
+#define PULL_LE_UINT16(buf,ofs) ((uint16_t)( \
+       ((uint16_t)(((uint16_t)(__PULL_BYTE(buf,(ofs)+0))) << 0)) | \
+       ((uint16_t)(((uint16_t)(__PULL_BYTE(buf,(ofs)+1))) << 8)) \
+))
+#endif
+
+#ifndef PULL_LE_UINT32
+#define PULL_LE_UINT32(buf,ofs) ((uint32_t)( \
+       ((uint32_t)(((uint32_t)(__PULL_BYTE(buf,(ofs)+0))) <<  0)) | \
+       ((uint32_t)(((uint32_t)(__PULL_BYTE(buf,(ofs)+1))) <<  8)) | \
+       ((uint32_t)(((uint32_t)(__PULL_BYTE(buf,(ofs)+2))) << 16)) | \
+       ((uint32_t)(((uint32_t)(__PULL_BYTE(buf,(ofs)+3))) << 24)) \
+))
+#endif
+
+static uint32_t xpress_decompress(uint8_t *input,
+                               uint32_t input_size,
+                               uint8_t *output,
+                               uint32_t output_size)
+{
+       uint32_t output_index, input_index;
+       uint32_t indicator, indicator_bit;
+       uint32_t length;
+       uint32_t offset;
+       uint32_t nibble_index;
+
+       output_index = 0;
+       input_index = 0;
+       indicator = 0;
+       indicator_bit = 0;
+       length = 0;
+       offset = 0;
+       nibble_index = 0;
+
+       do {
+               if (indicator_bit == 0) {
+                       indicator = PULL_LE_UINT32(input, input_index);
+                       input_index += sizeof(uint32_t);
+                       indicator_bit = 32;
+               }
+               indicator_bit--;
+
+               /*
+                * check whether the bit specified by indicator_bit is set or not
+                * set in indicator. For example, if indicator_bit has value 4
+                * check whether the 4th bit of the value in indicator is set
+                */
+               if (((indicator >> indicator_bit) & 1) == 0) {
+                       output[output_index] = input[input_index];
+                       input_index += sizeof(uint8_t);
+                       output_index += sizeof(uint8_t);
+               } else {
+                       length = PULL_LE_UINT16(input, input_index);
+                       input_index += sizeof(uint16_t);
+                       offset = length / 8;
+                       length = length % 8;
+
+                       if (length == 7) {
+                               if (nibble_index == 0) {
+                                       nibble_index = input_index;
+                                       length = input[input_index] % 16;
+                                       input_index += sizeof(uint8_t);
+                               } else {
+                                       length = input[nibble_index] / 16;
+                                       nibble_index = 0;
+                               }
+
+                               if (length == 15) {
+                                       length = input[input_index];
+                                       input_index += sizeof(uint8_t);
+                                               if (length == 255) {
+                                                       length = PULL_LE_UINT16(input, input_index);
+                                                       input_index += sizeof(uint16_t);
+                                                       length -= (15 + 7);
+                                               }
+                                       length += 15;
+                               }
+                               length += 7;
+                       }
+
+                       length += 3;
+
+                       do {
+                               if (output_index >= output_size) break;
+                               output[output_index] = output[output_index - offset - 1];
+                               output_index += sizeof(uint8_t);
+                               length -= sizeof(uint8_t);
+                       } while (length != 0);
+               }
+
+       } while ((output_index < output_size) && (input_index < input_size));
+
+       return output_index;
+}
+
+uint32_t lzxpress_decompress(DATA_BLOB *inbuf,
+                               DATA_BLOB *outbuf)
+{
+       return xpress_decompress(inbuf->data, inbuf->length, outbuf->data, outbuf->length);
+}
diff --git a/source4/lib/compression/lzxpress.h b/source4/lib/compression/lzxpress.h
new file mode 100644 (file)
index 0000000..4862fd2
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Matthieu Suiche 2008
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _LZXPRESS_H
+#define _LZXPRESS_H
+
+#define XPRESS_BLOCK_SIZE 0x10000
+
+uint32_t lzxpress_decompress(DATA_BLOB *inbuf,
+                            DATA_BLOB *outbuf);
+
+#endif /* _LZXPRESS_H */
index cdec317d1f8d4d6582865309d6e6fb1b257dd687..f84b44dfc72e2314f97f2b8c122da7d3034ea0a3 100644 (file)
@@ -7,5 +7,5 @@ PRIVATE_DEPENDENCIES = LIBSECURITY SAMDB_SCHEMA LIBNDR NDR_MISC NDR_DRSBLOBS
 ################################################
 
 LDBSAMBA_OBJ_FILES = $(ldb_sambasrcdir)/ldif_handlers.o
-$(eval $(call proto_header_template,$(ldb_sambasrcdir)/ldif_handlers.h,$(LDBSAMBA_OBJ_FILES:.o=.c)))
+$(eval $(call proto_header_template,$(ldb_sambasrcdir)/ldif_handlers_proto.h,$(LDBSAMBA_OBJ_FILES:.o=.c)))
 
index 1f718cc1c5adaca06d305723c3b15be581cb84e2..a16582d29458a1e0b23cfa7e822c0e1e8fecf4a1 100644 (file)
@@ -38,7 +38,7 @@ static int ldif_read_objectSid(struct ldb_context *ldb, void *mem_ctx,
 {
        enum ndr_err_code ndr_err;
        struct dom_sid *sid;
-       sid = dom_sid_parse_talloc(mem_ctx, (const char *)in->data);
+       sid = dom_sid_parse_length(mem_ctx, in);
        if (sid == NULL) {
                return -1;
        }
@@ -70,12 +70,11 @@ static int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx,
                talloc_free(sid);
                return -1;
        }
-       out->data = (uint8_t *)dom_sid_string(mem_ctx, sid);
+       *out = data_blob_string_const(dom_sid_string(mem_ctx, sid));
        talloc_free(sid);
        if (out->data == NULL) {
                return -1;
        }
-       out->length = strlen((const char *)out->data);
        return 0;
 }
 
@@ -97,13 +96,14 @@ static int ldb_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
                                    const struct ldb_val *v1, const struct ldb_val *v2)
 {
        if (ldb_comparision_objectSid_isString(v1) && ldb_comparision_objectSid_isString(v2)) {
-               return strcmp((const char *)v1->data, (const char *)v2->data);
+               return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
        } else if (ldb_comparision_objectSid_isString(v1)
                   && !ldb_comparision_objectSid_isString(v2)) {
                struct ldb_val v;
                int ret;
                if (ldif_read_objectSid(ldb, mem_ctx, v1, &v) != 0) {
-                       return -1;
+                       /* Perhaps not a string after all */
+                       return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
                }
                ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
                talloc_free(v.data);
@@ -113,7 +113,8 @@ static int ldb_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
                struct ldb_val v;
                int ret;
                if (ldif_read_objectSid(ldb, mem_ctx, v2, &v) != 0) {
-                       return -1;
+                       /* Perhaps not a string after all */
+                       return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
                }
                ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
                talloc_free(v.data);
@@ -129,7 +130,11 @@ static int ldb_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx,
                                      const struct ldb_val *in, struct ldb_val *out)
 {
        if (ldb_comparision_objectSid_isString(in)) {
-               return ldif_read_objectSid(ldb, mem_ctx, in, out);
+               if (ldif_read_objectSid(ldb, mem_ctx, in, out) != 0) {
+                       /* Perhaps not a string after all */
+                       return ldb_handler_copy(ldb, mem_ctx, in, out);
+               }
+               return 0;
        }
        return ldb_handler_copy(ldb, mem_ctx, in, out);
 }
@@ -141,10 +146,16 @@ static int ldif_read_objectGUID(struct ldb_context *ldb, void *mem_ctx,
                                const struct ldb_val *in, struct ldb_val *out)
 {
        struct GUID guid;
+       char *guid_string;
        NTSTATUS status;
        enum ndr_err_code ndr_err;
+       guid_string = talloc_strndup(mem_ctx, (const char *)in->data, in->length);
+       if (!guid_string) {
+               return -1;
+       }
 
-       status = GUID_from_string((const char *)in->data, &guid);
+       status = GUID_from_string(guid_string, &guid);
+       talloc_free(guid_string);
        if (!NT_STATUS_IS_OK(status)) {
                return -1;
        }
@@ -203,13 +214,14 @@ static int ldb_comparison_objectGUID(struct ldb_context *ldb, void *mem_ctx,
                                     const struct ldb_val *v1, const struct ldb_val *v2)
 {
        if (ldb_comparision_objectGUID_isString(v1) && ldb_comparision_objectGUID_isString(v2)) {
-               return strcmp((const char *)v1->data, (const char *)v2->data);
+               return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
        } else if (ldb_comparision_objectGUID_isString(v1)
                   && !ldb_comparision_objectGUID_isString(v2)) {
                struct ldb_val v;
                int ret;
                if (ldif_read_objectGUID(ldb, mem_ctx, v1, &v) != 0) {
-                       return -1;
+                       /* Perhaps it wasn't a valid string after all */
+                       return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
                }
                ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
                talloc_free(v.data);
@@ -219,7 +231,8 @@ static int ldb_comparison_objectGUID(struct ldb_context *ldb, void *mem_ctx,
                struct ldb_val v;
                int ret;
                if (ldif_read_objectGUID(ldb, mem_ctx, v2, &v) != 0) {
-                       return -1;
+                       /* Perhaps it wasn't a valid string after all */
+                       return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
                }
                ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
                talloc_free(v.data);
@@ -235,7 +248,11 @@ static int ldb_canonicalise_objectGUID(struct ldb_context *ldb, void *mem_ctx,
                                       const struct ldb_val *in, struct ldb_val *out)
 {
        if (ldb_comparision_objectGUID_isString(in)) {
-               return ldif_read_objectGUID(ldb, mem_ctx, in, out);
+               if (ldif_read_objectGUID(ldb, mem_ctx, in, out) != 0) {
+                       /* Perhaps it wasn't a valid string after all */
+                       return ldb_handler_copy(ldb, mem_ctx, in, out);
+               }
+               return 0;
        }
        return ldb_handler_copy(ldb, mem_ctx, in, out);
 }
@@ -314,7 +331,7 @@ static int ldif_canonicalise_objectCategory(struct ldb_context *ldb, void *mem_c
                }
                return LDB_SUCCESS;
        }
-       dn1 = ldb_dn_new(tmp_ctx, ldb, (char *)in->data);
+       dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, in);
        if ( ! ldb_dn_validate(dn1)) {
                const char *lDAPDisplayName = talloc_strndup(tmp_ctx, (char *)in->data, in->length);
                class = dsdb_class_by_lDAPDisplayName(schema, lDAPDisplayName);
@@ -561,8 +578,6 @@ static int ldif_comparison_prefixMap(struct ldb_context *ldb, void *mem_ctx,
        return ret;
 }
 
-#define LDB_SYNTAX_SAMBA_SID                   "LDB_SYNTAX_SAMBA_SID"
-#define LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR   "LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR"
 #define LDB_SYNTAX_SAMBA_GUID                  "LDB_SYNTAX_SAMBA_GUID"
 #define LDB_SYNTAX_SAMBA_OBJECT_CATEGORY       "LDB_SYNTAX_SAMBA_OBJECT_CATEGORY"
 #define LDB_SYNTAX_SAMBA_PREFIX_MAP    "LDB_SYNTAX_SAMBA_PREFIX_MAP"
@@ -619,22 +634,24 @@ static const struct {
        { "fRSReplicaSetGUID",          LDB_SYNTAX_SAMBA_GUID },
        { "netbootGUID",                LDB_SYNTAX_SAMBA_GUID },
        { "objectCategory",             LDB_SYNTAX_SAMBA_OBJECT_CATEGORY },
-       { "member",                     LDB_SYNTAX_DN },
-       { "memberOf",                   LDB_SYNTAX_DN },
-       { "nCName",                     LDB_SYNTAX_DN },
-       { "schemaNamingContext",        LDB_SYNTAX_DN },
-       { "configurationNamingContext", LDB_SYNTAX_DN },
-       { "rootDomainNamingContext",    LDB_SYNTAX_DN },
-       { "defaultNamingContext",       LDB_SYNTAX_DN },
-       { "subRefs",                    LDB_SYNTAX_DN },
-       { "dMDLocation",                LDB_SYNTAX_DN },
-       { "serverReference",            LDB_SYNTAX_DN },
-       { "masteredBy",                 LDB_SYNTAX_DN },
-       { "msDs-masteredBy",            LDB_SYNTAX_DN },
-       { "fSMORoleOwner",              LDB_SYNTAX_DN },
        { "prefixMap",                  LDB_SYNTAX_SAMBA_PREFIX_MAP }
 };
 
+const struct ldb_schema_syntax *ldb_samba_syntax_by_name(struct ldb_context *ldb, const char *name)
+{
+       uint32_t j;
+       const struct ldb_schema_syntax *s = NULL;
+       
+       for (j=0; j < ARRAY_SIZE(samba_syntaxes); j++) {
+               if (strcmp(name, samba_syntaxes[j].name) == 0) {
+                       s = &samba_syntaxes[j];
+                       break;
+               }
+       }
+       return s;
+}
+
+
 /*
   register the samba ldif handlers
 */
@@ -644,15 +661,9 @@ int ldb_register_samba_handlers(struct ldb_context *ldb)
 
        for (i=0; i < ARRAY_SIZE(samba_attributes); i++) {
                int ret;
-               uint32_t j;
                const struct ldb_schema_syntax *s = NULL;
 
-               for (j=0; j < ARRAY_SIZE(samba_syntaxes); j++) {
-                       if (strcmp(samba_attributes[i].syntax, samba_syntaxes[j].name) == 0) {
-                               s = &samba_syntaxes[j];
-                               break;
-                       }
-               }
+               s = ldb_samba_syntax_by_name(ldb, samba_attributes[i].syntax);
 
                if (!s) {
                        s = ldb_standard_syntax_by_name(ldb, samba_attributes[i].syntax);
@@ -662,7 +673,7 @@ int ldb_register_samba_handlers(struct ldb_context *ldb)
                        return -1;
                }
 
-               ret = ldb_schema_attribute_add_with_syntax(ldb, samba_attributes[i].name, 0, s);
+               ret = ldb_schema_attribute_add_with_syntax(ldb, samba_attributes[i].name, LDB_ATTR_FLAG_FIXED, s);
                if (ret != LDB_SUCCESS) {
                        return ret;
                }
diff --git a/source4/lib/ldb-samba/ldif_handlers.h b/source4/lib/ldb-samba/ldif_handlers.h
new file mode 100644 (file)
index 0000000..e37c416
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef __LIB_LDB_SAMBA_LDIF_HANDLERS_H__
+#define __LIB_LDB_SAMBA_LDIF_HANDLERS_H__
+
+#define LDB_SYNTAX_SAMBA_SID                   "LDB_SYNTAX_SAMBA_SID"
+#define LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR   "1.2.840.113556.1.4.907"
+
+#include "lib/ldb-samba/ldif_handlers_proto.h"
+
+#undef _PRINTF_ATTRIBUTE
+#define _PRINTF_ATTRIBUTE(a1, a2)
+
+#endif /* __LIB_LDB_SAMBA_LDIF_HANDLERS_H__ */
+
index 8ed2763d4df5112af67f89b43b109f0e3c359cbc..fb57e2dadc084fb74bf06d1dc7a9b1bc5fca42de 100644 (file)
@@ -55,11 +55,12 @@ int ldb_handler_fold(struct ldb_context *ldb, void *mem_ctx,
 {
        char *s, *t;
        int l;
+
        if (!in || !out || !(in->data)) {
                return -1;
        }
 
-       out->data = (uint8_t *)ldb_casefold(ldb, mem_ctx, (const char *)(in->data));
+       out->data = (uint8_t *)ldb_casefold(ldb, mem_ctx, (const char *)(in->data), in->length);
        if (out->data == NULL) {
                ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_handler_fold: unable to casefold string [%s]", in->data);
                return -1;
@@ -153,13 +154,14 @@ int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx,
                               const struct ldb_val *v1, const struct ldb_val *v2)
 {
        const char *s1=(const char *)v1->data, *s2=(const char *)v2->data;
+       size_t n1 = v1->length, n2 = v2->length;
        const char *u1, *u2;
        char *b1, *b2;
        int ret;
-       while (*s1 == ' ') s1++;
-       while (*s2 == ' ') s2++;
+       while (*s1 == ' ' && n1) { s1++; n1--; };
+       while (*s2 == ' ' && n2) { s2++; n2--; };
        /* TODO: make utf8 safe, possibly with helper function from application */
-       while (*s1 && *s2) {
+       while (*s1 && *s2 && n1 && n2) {
                /* the first 127 (0x7F) chars are ascii and utf8 guarantes they
                 * never appear in multibyte sequences */
                if (((unsigned char)s1[0]) & 0x80) goto utf8str;
@@ -167,10 +169,11 @@ int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx,
                if (toupper((unsigned char)*s1) != toupper((unsigned char)*s2))
                        break;
                if (*s1 == ' ') {
-                       while (s1[0] == s1[1]) s1++;
-                       while (s2[0] == s2[1]) s2++;
+                       while (s1[0] == s1[1] && n1) { s1++; n1--; }
+                       while (s2[0] == s2[1] && n2) { s2++; n2--; }
                }
                s1++; s2++;
+               n1--; n2--;
        }
        if (! (*s1 && *s2)) {
                /* check for trailing spaces only if one of the pointers
@@ -178,15 +181,18 @@ int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx,
                 * can mistakenly match.
                 * ex. "domain users" <-> "domainUpdates"
                 */
-               while (*s1 == ' ') s1++;
-               while (*s2 == ' ') s2++;
+               while (*s1 == ' ') { s1++; n1--; }
+               while (*s2 == ' ') { s2++; n2--; }
+       }
+       if (n1 != n2) {
+               return n1 - n2;
        }
        return (int)(toupper(*s1)) - (int)(toupper(*s2));
 
 utf8str:
        /* no need to recheck from the start, just from the first utf8 char found */
-       b1 = ldb_casefold(ldb, mem_ctx, s1);
-       b2 = ldb_casefold(ldb, mem_ctx, s2);
+       b1 = ldb_casefold(ldb, mem_ctx, s1, n1);
+       b2 = ldb_casefold(ldb, mem_ctx, s2, n2);
 
        if (b1 && b2) {
                /* Both strings converted correctly */
@@ -221,6 +227,7 @@ utf8str:
        return ret;
 }
 
+
 /*
   canonicalise a attribute in DN format
 */
index effd93ae2674e9e8ec620d53033b3bf4e2732886..747f2417811a9069b1ed4391b70672b6d54f590b 100644 (file)
@@ -51,6 +51,10 @@ int ldb_schema_attribute_add_with_syntax(struct ldb_context *ldb,
        int i, n;
        struct ldb_schema_attribute *a;
 
+       if (!syntax) {
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
        n = ldb->schema.num_attributes + 1;
 
        a = talloc_realloc(ldb, ldb->schema.attributes,
@@ -62,11 +66,24 @@ int ldb_schema_attribute_add_with_syntax(struct ldb_context *ldb,
        ldb->schema.attributes = a;
 
        for (i = 0; i < ldb->schema.num_attributes; i++) {
-               if (ldb_attr_cmp(attribute, a[i].name) < 0) {
+               int cmp = ldb_attr_cmp(attribute, a[i].name);
+               if (cmp == 0) {
+                       /* silently ignore attempts to overwrite fixed attributes */
+                       if (a[i].flags & LDB_ATTR_FLAG_FIXED) {
+                               return 0;
+                       }
+                       if (a[i].flags & LDB_ATTR_FLAG_ALLOCATED) {
+                               talloc_free(discard_const_p(char, a[i].name));
+                       }
+                       /* To cancel out increment below */
+                       ldb->schema.num_attributes--;
+                       break;
+               } else if (cmp < 0) {
                        memmove(a+i+1, a+i, sizeof(*a) * (ldb->schema.num_attributes-i));
                        break;
                }
        }
+       ldb->schema.num_attributes++;
 
        a[i].name       = attribute;
        a[i].flags      = flags;
@@ -80,7 +97,6 @@ int ldb_schema_attribute_add_with_syntax(struct ldb_context *ldb,
                }
        }
 
-       ldb->schema.num_attributes++;
        return 0;
 }
 
@@ -145,7 +161,12 @@ void ldb_schema_attribute_remove(struct ldb_context *ldb, const char *name)
        int i;
 
        a = ldb_schema_attribute_by_name(ldb, name);
-       if (a == NULL) {
+       if (a == NULL || a->name == NULL) {
+               return;
+       }
+
+       /* FIXED attributes are never removed */
+       if (a->flags & LDB_ATTR_FLAG_FIXED) {
                return;
        }
 
index 08911344b759cada33bac9786b1d2cbce1722ba1..c0d36cfbf3e0c48239b123a8920fbd4d065cc068 100644 (file)
@@ -71,7 +71,7 @@ struct ldb_dn {
 };
 
 /* strdn may be NULL */
-struct ldb_dn *ldb_dn_new(void *mem_ctx, struct ldb_context *ldb, const char *strdn)
+struct ldb_dn *ldb_dn_from_ldb_val(void *mem_ctx, struct ldb_context *ldb, const struct ldb_val *strdn)
 {
        struct ldb_dn *dn;
 
@@ -82,27 +82,27 @@ struct ldb_dn *ldb_dn_new(void *mem_ctx, struct ldb_context *ldb, const char *st
 
        dn->ldb = ldb;
 
-       if (strdn) {
-               if (strdn[0] == '@') {
+       if (strdn->data && strdn->length) {
+               if (strdn->data[0] == '@') {
                        dn->special = true;
                }
-               if (strncasecmp(strdn, "<GUID=", 6) == 0) {
+               if (strdn->length >= 6 && strncasecmp((const char *)strdn->data, "<GUID=", 6) == 0) {
                        /* this is special DN returned when the
                         * exploded_dn control is used */
                        dn->special = true;
                        /* FIXME: add a GUID string to ldb_dn structure */
-               } else if (strncasecmp(strdn, "<SID=", 8) == 0) {
+               } else if (strdn->length >= 8 && strncasecmp((const char *)strdn->data, "<SID=", 8) == 0) {
                        /* this is special DN returned when the
                         * exploded_dn control is used */
                        dn->special = true;
                        /* FIXME: add a SID string to ldb_dn structure */
-               } else if (strncasecmp(strdn, "<WKGUID=", 8) == 0) {
+               } else if (strdn->length >= 8 && strncasecmp((const char *)strdn->data, "<WKGUID=", 8) == 0) {
                        /* this is special DN returned when the
                         * exploded_dn control is used */
                        dn->special = true;
                        /* FIXME: add a WKGUID string to ldb_dn structure */
                }
-               dn->linearized = talloc_strdup(dn, strdn);
+               dn->linearized = talloc_strndup(dn, (const char *)strdn->data, strdn->length);
        } else {
                dn->linearized = talloc_strdup(dn, "");
        }
@@ -115,6 +115,15 @@ failed:
        return NULL;
 }
 
+/* strdn may be NULL */
+struct ldb_dn *ldb_dn_new(void *mem_ctx, struct ldb_context *ldb, const char *strdn)
+{
+       struct ldb_val blob;
+       blob.data = strdn;
+       blob.length = strdn ? strlen(strdn) : 0;
+       return ldb_dn_from_ldb_val(mem_ctx, ldb, &blob);
+}
+
 struct ldb_dn *ldb_dn_new_fmt(void *mem_ctx, struct ldb_context *ldb, const char *new_fmt, ...)
 {
        struct ldb_dn *dn;
index c1ea9db56bfb11a4319fb6503258199bcac471dd..2f5fe1d18c143cde271958948605ca0d82eea896 100644 (file)
@@ -389,10 +389,10 @@ int ldb_msg_find_attr_as_bool(const struct ldb_message *msg,
        if (!v || !v->data) {
                return default_value;
        }
-       if (strcasecmp((const char *)v->data, "FALSE") == 0) {
+       if (v->length == 5 && strncasecmp((const char *)v->data, "FALSE", 5) == 0) {
                return 0;
        }
-       if (strcasecmp((const char *)v->data, "TRUE") == 0) {
+       if (v->length == 4 && strncasecmp((const char *)v->data, "TRUE", 4) == 0) {
                return 1;
        }
        return default_value;
@@ -421,7 +421,7 @@ struct ldb_dn *ldb_msg_find_attr_as_dn(struct ldb_context *ldb,
        if (!v || !v->data) {
                return NULL;
        }
-       res_dn = ldb_dn_new(mem_ctx, ldb, (const char *)v->data);
+       res_dn = ldb_dn_from_ldb_val(mem_ctx, ldb, v);
        if ( ! ldb_dn_validate(res_dn)) {
                talloc_free(res_dn);
                return NULL;
index b7b4a60122f8c5b9d6e1ec7f66cca410457ae8a8..69ee2b6964f81e8a66b634f80965b3cabb823bb0 100644 (file)
@@ -40,8 +40,8 @@
   function to handle utf8 caseless comparisons
  */
 void ldb_set_utf8_fns(struct ldb_context *ldb,
-                       void *context,
-                       char *(*casefold)(void *, void *, const char *))
+                     void *context,
+                     char *(*casefold)(void *, void *, const char *, size_t))
 {
        if (context)
                ldb->utf8_fns.context = context;
@@ -53,10 +53,10 @@ void ldb_set_utf8_fns(struct ldb_context *ldb,
   a simple case folding function
   NOTE: does not handle UTF8
 */
-char *ldb_casefold_default(void *context, void *mem_ctx, const char *s)
+char *ldb_casefold_default(void *context, void *mem_ctx, const char *s, size_t n)
 {
        int i;
-       char *ret = talloc_strdup(mem_ctx, s);
+       char *ret = talloc_strndup(mem_ctx, s, n);
        if (!s) {
                errno = ENOMEM;
                return NULL;
@@ -72,9 +72,9 @@ void ldb_set_utf8_default(struct ldb_context *ldb)
        ldb_set_utf8_fns(ldb, NULL, ldb_casefold_default);
 }
 
-char *ldb_casefold(struct ldb_context *ldb, void *mem_ctx, const char *s)
+char *ldb_casefold(struct ldb_context *ldb, void *mem_ctx, const char *s, size_t n)
 {
-       return ldb->utf8_fns.casefold(ldb->utf8_fns.context, mem_ctx, s);
+       return ldb->utf8_fns.casefold(ldb->utf8_fns.context, mem_ctx, s, n);
 }
 
 /*
index 0338ae1d938654305ba1624a5cba97cd9a347437..937029f52ce3f53f2ec78274430a9d05416500d0 100644 (file)
@@ -203,7 +203,7 @@ struct ldb_debug_ops {
 */
 struct ldb_utf8_fns {
        void *context;
-       char *(*casefold)(void *context, TALLOC_CTX *mem_ctx, const char *s);
+       char *(*casefold)(void *context, TALLOC_CTX *mem_ctx, const char *s, size_t n);
 };
 
 /**
@@ -358,9 +358,9 @@ const struct ldb_schema_attribute *ldb_schema_attribute_by_name(struct ldb_conte
 #define LDB_ATTR_FLAG_ALLOCATED    (1<<1) 
 
 /**
-   The attribute is constructed from other attributes
+   The attribute is supplied by the application and should not be removed
 */
-#define LDB_ATTR_FLAG_CONSTRUCTED  (1<<1
+#define LDB_ATTR_FLAG_FIXED        (1<<2
 
 /**
   LDAP attribute syntax for a DN
@@ -1216,7 +1216,7 @@ void ldb_set_utf8_default(struct ldb_context *ldb);
    \note The default function is not yet UTF8 aware. Provide your own
          set of functions through ldb_set_utf8_fns()
 */
-char *ldb_casefold(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *s);
+char *ldb_casefold(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *s, size_t n);
 
 /**
    Check the attribute name is valid according to rfc2251
@@ -1381,6 +1381,7 @@ int ldb_base64_decode(char *s);
 
 struct ldb_dn *ldb_dn_new(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, const char *dn);
 struct ldb_dn *ldb_dn_new_fmt(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, const char *new_fmt, ...) PRINTF_ATTRIBUTE(3,4);
+struct ldb_dn *ldb_dn_from_ldb_val(void *mem_ctx, struct ldb_context *ldb, const struct ldb_val *strdn);
 bool ldb_dn_validate(struct ldb_dn *dn);
 
 char *ldb_dn_escape_value(TALLOC_CTX *mem_ctx, struct ldb_val value);
@@ -1602,8 +1603,8 @@ int ldb_set_debug(struct ldb_context *ldb,
   this allows the user to set custom utf8 function for error reporting
 */
 void ldb_set_utf8_fns(struct ldb_context *ldb,
-                       void *context,
-                       char *(*casefold)(void *, void *, const char *));
+                     void *context,
+                     char *(*casefold)(void *, void *, const char *, size_t n));
 
 /**
    this sets up debug to print messages on stderr
index d7c2efe8a1a2b86c9aa3c1abbe27ba067bb6bdb0..e1026ab781170a412cd12dcc12fddcec2c9da827 100644 (file)
@@ -91,13 +91,6 @@ struct ldb_schema {
        /* attribute handling table */
        unsigned num_attributes;
        struct ldb_schema_attribute *attributes;
-
-       /* objectclass information */
-       unsigned num_classes;
-       struct ldb_subclass {
-               char *name;
-               char **subclasses;
-       } *classes;
 };
 
 /*
@@ -242,7 +235,7 @@ int save_controls(struct ldb_control *exclude, struct ldb_request *req, struct l
 int check_critical_controls(struct ldb_control **controls);
 
 /* The following definitions come from lib/ldb/common/ldb_utf8.c */
-char *ldb_casefold_default(void *context, void *mem_ctx, const char *s);
+char *ldb_casefold_default(void *context, void *mem_ctx, const char *s, size_t n);
 
 void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el);
 
index 8742e257f3058abb96a321b81f90e7a93d5c0f70..a0e63c8da1fe817441a15977683f0bfbbeb19cc0 100644 (file)
@@ -349,23 +349,7 @@ static char *parsetree_to_sql(struct ldb_module *module,
                        return NULL;
                }
 
-               if (strcasecmp(t->u.equality.attr, "objectclass") == 0) {
-               /*
-                * For object classes, we want to search for all objectclasses
-                * that are subclasses as well.
-               */
-                       return lsqlite3_tprintf(mem_ctx,
-                                       "SELECT eid  FROM ldb_attribute_values\n"
-                                       "WHERE norm_attr_name = 'OBJECTCLASS' "
-                                       "AND norm_attr_value IN\n"
-                                       "  (SELECT class_name FROM ldb_object_classes\n"
-                                       "   WHERE tree_key GLOB\n"
-                                       "     (SELECT tree_key FROM ldb_object_classes\n"
-                                       "      WHERE class_name = '%q'\n"
-                                       "     ) || '*'\n"
-                                       "  )\n", value.data);
-
-               } else if (strcasecmp(t->u.equality.attr, "dn") == 0) {
+               if (strcasecmp(t->u.equality.attr, "dn") == 0) {
                        /* DN query is a special ldb case */
                        const char *cdn = ldb_dn_get_casefold(
                                                ldb_dn_new(mem_ctx, module->ldb,
@@ -1039,16 +1023,8 @@ static int lsql_add(struct ldb_module *module, struct ldb_request *req)
 
         /* See if this is an ltdb special */
        if (ldb_dn_is_special(msg->dn)) {
-               struct ldb_dn *c;
-
-               c = ldb_dn_new(lsql_ac, module->ldb, "@SUBCLASSES");
-               if (ldb_dn_compare(msg->dn, c) == 0) {
-#warning "insert subclasses into object class tree"
-                       ret = LDB_ERR_UNWILLING_TO_PERFORM;
-                       goto done;
-               }
-
 /*
+               struct ldb_dn *c;
                c = ldb_dn_new(local_ctx, module->ldb, "@INDEXLIST");
                if (ldb_dn_compare(module->ldb, msg->dn, c) == 0) {
 #warning "should we handle indexes somehow ?"
@@ -1177,15 +1153,6 @@ static int lsql_modify(struct ldb_module *module, struct ldb_request *req)
 
         /* See if this is an ltdb special */
        if (ldb_dn_is_special(msg->dn)) {
-               struct ldb_dn *c;
-
-               c = ldb_dn_new(lsql_ac, module->ldb, "@SUBCLASSES");
-               if (ldb_dn_compare(msg->dn, c) == 0) {
-#warning "modify subclasses into object class tree"
-                       ret = LDB_ERR_UNWILLING_TO_PERFORM;
-                       goto done;
-               }
-
                 /* Others return an error */
                ret = LDB_ERR_UNWILLING_TO_PERFORM;
                 goto done;
index 08dc50de089a05098c11828c554959c400495f44..ab7c5cc406f866a5ec95f25aaf4bc381d8c86a10 100644 (file)
@@ -326,38 +326,3 @@ UPDATE ldb_attributes
       integer_p = 0
   WHERE attr_name = 'dn'
 
--- ----------------------------------------------------------------------
-
-/*
- * dn: @SUBCLASSES
- * top: domain
- * top: person
- * domain: domainDNS
- * person: organizationalPerson
- * person: fooPerson
- * organizationalPerson: user
- * organizationalPerson: OpenLDAPperson
- * user: computer
- */
--- insertSubclass
-
-/* NOT YET UPDATED!!! *
-
-
-INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key)
-  SELECT 'domain', /* next_tree_key('top') */ '00010001';
-INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key)
-  SELECT 'person', /* next_tree_key('top') */ '00010002';
-INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key)
-  SELECT 'domainDNS', /* next_tree_key('domain') */ '000100010001';
-INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key)
-  SELECT 'organizationalPerson', /* next_tree_key('person') */ '000100020001';
-INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key)
-  SELECT 'fooPerson', /* next_tree_key('person') */ '000100020002';
-INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key)
-  SELECT 'user', /* next_tree_key('organizationalPerson') */ '0001000200010001';
-INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key)
-  SELECT 'OpenLDAPperson', /* next_tree_key('organizationPerson') */ '0001000200010002';
-INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key)
-  SELECT 'computer', /* next_tree_key('user') */ '0001000200010001';
index 1b6d9feed6117cd5175176c347540e560af54ca6..269305a4680c90c94ad4dc625486ad3b5bcaffcc 100644 (file)
@@ -767,7 +767,7 @@ int ltdb_search_indexed(struct ldb_handle *handle)
 
        if ((ac->scope == LDB_SCOPE_ONELEVEL && (idxattr+idxone == 0)) ||
            (ac->scope == LDB_SCOPE_SUBTREE && idxattr == 0)) {
-               /* no indexs? must do full search */
+               /* no indexes? must do full search */
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
index 7dc4ae08c380eee8947643e5afc7bb8394728ac8..a59e81becdd4e50eb764484eba6b2ae1a27254ce 100644 (file)
@@ -291,12 +291,6 @@ static int operational_init(struct ldb_module *ctx)
 {
        int ret = 0;
 
-       /* setup some standard attribute handlers */
-       ret |= ldb_schema_attribute_add(ctx->ldb, "whenCreated", 0, LDB_SYNTAX_UTC_TIME);
-       ret |= ldb_schema_attribute_add(ctx->ldb, "whenChanged", 0, LDB_SYNTAX_UTC_TIME);
-       ret |= ldb_schema_attribute_add(ctx->ldb, "subschemaSubentry", 0, LDB_SYNTAX_DN);
-       ret |= ldb_schema_attribute_add(ctx->ldb, "structuralObjectClass", 0, LDB_SYNTAX_OBJECTCLASS);
-
        if (ret != 0) {
                return ret;
        }
index 042469602cf7f143871afd910646bc80ba9d9f4f..bc6f80e856d2042e30cb5a750e2a44593bc78829 100755 (executable)
@@ -331,15 +331,15 @@ servicePrincipalName: host/ldaptest2computer29
         print "Testing Ambigious Name Resolution"
         # Testing ldb.search for (&(anr=ldap testy)(objectClass=user))
         res = ldb.search(expression="(&(anr=ldap testy)(objectClass=user))")
-        self.assertEquals(len(res), 3, "Could not find (&(anr=ldap testy)(objectClass=user))")
+        self.assertEquals(len(res), 3, "Found only %d of 3 for (&(anr=ldap testy)(objectClass=user))" % len(res))
 
         # Testing ldb.search for (&(anr=testy ldap)(objectClass=user))
         res = ldb.search(expression="(&(anr=testy ldap)(objectClass=user))")
-        self.assertEquals(len(res), 2, "Found only %d for (&(anr=testy ldap)(objectClass=user))" % len(res))
+        self.assertEquals(len(res), 2, "Found only %d of 2 for (&(anr=testy ldap)(objectClass=user))" % len(res))
 
         # Testing ldb.search for (&(anr=ldap)(objectClass=user))
         res = ldb.search(expression="(&(anr=ldap)(objectClass=user))")
-        self.assertEquals(len(res), 4, "Found only %d for (&(anr=ldap)(objectClass=user))" % len(res))
+        self.assertEquals(len(res), 4, "Found only %d of 4 for (&(anr=ldap)(objectClass=user))" % len(res))
 
         # Testing ldb.search for (&(anr==ldap)(objectClass=user))
         res = ldb.search(expression="(&(anr==ldap)(objectClass=user))")
@@ -353,21 +353,22 @@ servicePrincipalName: host/ldaptest2computer29
         res = ldb.search(expression="(&(anr=testy)(objectClass=user))")
         self.assertEquals(len(res), 2, "Found only %d for (&(anr=testy)(objectClass=user))" % len(res))
 
-        # Testing ldb.search for (&(anr=ldap testy)(objectClass=user))
+        # Testing ldb.search for (&(anr=testy ldap)(objectClass=user))
         res = ldb.search(expression="(&(anr=testy ldap)(objectClass=user))")
-        self.assertEquals(len(res), 2, "Found only %d for (&(anr=ldap testy)(objectClass=user))" % len(res))
+        self.assertEquals(len(res), 2, "Found only %d for (&(anr=testy ldap)(objectClass=user))" % len(res))
 
-        # Testing ldb.search for (&(anr==ldap testy)(objectClass=user))
-        res = ldb.search(expression="(&(anr==testy ldap)(objectClass=user))")
-        self.assertEquals(len(res), 1, "Found only %d for (&(anr==ldap testy)(objectClass=user))" % len(res))
+        # Testing ldb.search for (&(anr==testy ldap)(objectClass=user))
+# this test disabled for the moment, as anr with == tests are not understood
+#        res = ldb.search(expression="(&(anr==testy ldap)(objectClass=user))")
+#        self.assertEquals(len(res), 1, "Found only %d for (&(anr==testy ldap)(objectClass=user))" % len(res))
 
         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
         self.assertEquals(res[0]["cn"][0], "ldaptestuser")
         self.assertEquals(res[0]["name"][0], "ldaptestuser")
 
         # Testing ldb.search for (&(anr==testy ldap)(objectClass=user))
-        res = ldb.search(expression="(&(anr==testy ldap)(objectClass=user))")
-        self.assertEquals(len(res), 1, "Could not find (&(anr==testy ldap)(objectClass=user))")
+#        res = ldb.search(expression="(&(anr==testy ldap)(objectClass=user))")
+#        self.assertEquals(len(res), 1, "Could not find (&(anr==testy ldap)(objectClass=user))")
 
         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
         self.assertEquals(res[0]["cn"][0], "ldaptestuser")
@@ -382,32 +383,32 @@ servicePrincipalName: host/ldaptest2computer29
         self.assertEquals(res[0]["name"], "ldaptestuser2")
 
         # Testing ldb.search for (&(anr==testy ldap user2)(objectClass=user))
-        res = ldb.search(expression="(&(anr==testy ldap user2)(objectClass=user))")
-        self.assertEquals(len(res), 1, "Could not find (&(anr==testy ldap user2)(objectClass=user))")
+#        res = ldb.search(expression="(&(anr==testy ldap user2)(objectClass=user))")
+#        self.assertEquals(len(res), 1, "Could not find (&(anr==testy ldap user2)(objectClass=user))")
 
         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn))
         self.assertEquals(res[0]["cn"], "ldaptestuser2")
         self.assertEquals(res[0]["name"], "ldaptestuser2")
 
         # Testing ldb.search for (&(anr==ldap user2)(objectClass=user))
-        res = ldb.search(expression="(&(anr==ldap user2)(objectClass=user))")
-        self.assertEquals(len(res), 1, "Could not find (&(anr==ldap user2)(objectClass=user))")
+#        res = ldb.search(expression="(&(anr==ldap user2)(objectClass=user))")
+#        self.assertEquals(len(res), 1, "Could not find (&(anr==ldap user2)(objectClass=user))")
 
         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn))
         self.assertEquals(res[0]["cn"], "ldaptestuser2")
         self.assertEquals(res[0]["name"], "ldaptestuser2")
 
         # Testing ldb.search for (&(anr==not ldap user2)(objectClass=user))
-        res = ldb.search(expression="(&(anr==not ldap user2)(objectClass=user))")
-        self.assertEquals(len(res), 0, "Must not find (&(anr==not ldap user2)(objectClass=user))")
+#        res = ldb.search(expression="(&(anr==not ldap user2)(objectClass=user))")
+#        self.assertEquals(len(res), 0, "Must not find (&(anr==not ldap user2)(objectClass=user))")
 
         # Testing ldb.search for (&(anr=not ldap user2)(objectClass=user))
         res = ldb.search(expression="(&(anr=not ldap user2)(objectClass=user))")
         self.assertEquals(len(res), 0, "Must not find (&(anr=not ldap user2)(objectClass=user))")
 
         # Testing ldb.search for (&(anr="testy ldap")(objectClass=user)) (ie, with quotes)
-        res = ldb.search(expression="(&(anr==\"testy ldap\")(objectClass=user))")
-        self.assertEquals(len(res), 0, "Found (&(anr==\"testy ldap\")(objectClass=user))")
+#        res = ldb.search(expression="(&(anr==\"testy ldap\")(objectClass=user))")
+#        self.assertEquals(len(res), 0, "Found (&(anr==\"testy ldap\")(objectClass=user))")
 
         print "Testing Group Modifies"
         ldb.modify_ldif("""
@@ -970,6 +971,34 @@ class BaseDnTests(unittest.TestCase):
                 attrs=["netlogon", "highestCommittedUSN"])
         self.assertEquals(len(res), 0)
 
+class SchemaTests(unittest.TestCase):
+    def find_schemadn(self, ldb):
+        res = ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["schemaNamingContext"])
+        self.assertEquals(len(res), 1)
+        return res[0]["schemaNamingContext"][0]
+
+    def setUp(self):
+        self.ldb = ldb
+        self.schema_dn = self.find_schemadn(ldb)
+
+    def test_generated_schema(self):
+        """Testing we can read the generated schema via LDAP"""
+        res = self.ldb.search("cn=aggregate,"+self.schema_dn, scope=SCOPE_BASE, 
+                attrs=["objectClasses", "attributeTypes", "dITContentRules"])
+        self.assertEquals(len(res), 1)
+        self.assertTrue("dITContentRules" in res[0])
+        self.assertTrue("objectClasses" in res[0])
+        self.assertTrue("attributeTypes" in res[0])
+
+    def test_generated_schema_is_operational(self):
+        """Testing we don't get the generated schema via LDAP by default"""
+        res = self.ldb.search("cn=aggregate,"+self.schema_dn, scope=SCOPE_BASE, 
+                attrs=["*"])
+        self.assertEquals(len(res), 1)
+        self.assertFalse("dITContentRules" in res[0])
+        self.assertFalse("objectClasses" in res[0])
+        self.assertFalse("attributeTypes" in res[0])
 if not "://" in host:
     host = "ldap://%s" % host
 
@@ -983,4 +1012,6 @@ if not runner.run(unittest.makeSuite(BaseDnTests)).wasSuccessful():
     rc = 1
 if not runner.run(unittest.makeSuite(BasicTests)).wasSuccessful():
     rc = 1
+if not runner.run(unittest.makeSuite(SchemaTests)).wasSuccessful():
+    rc = 1
 sys.exit(rc)
index 0bb3ebead68104b69da7877fd35bd547b9290d7f..79508c4b7bc5f7dac8ac985da83a401ca4b9aa90 100644 (file)
@@ -4,12 +4,3 @@ cn: CASE_INSENSITIVE
 ou: CASE_INSENSITIVE
 dn: CASE_INSENSITIVE
 
-dn: @SUBCLASSES
-top: domain
-top: person
-domain: domainDNS
-person: organizationalPerson
-person: fooPerson
-organizationalPerson: user
-organizationalPerson: OpenLDAPperson
-user: computer
index a793537187823e28f470aef722cb7e9363cc501e..268173641d153a8905307ee44002dd6e970d64e2 100644 (file)
@@ -5,7 +5,3 @@ dn: @INDEXLIST
 dn: @ATTRIBUTES
 uid: CASE_INSENSITIVE
 
-dn: @SUBCLASSES
-top: person
-person: organizationalPerson
-organizationalPerson: OpenLDAPperson
index 6d141478ad4a097d162a0a3deb922047e351251e..169ff02da1ad9dfb75862886e156549ccff81a96 100644 (file)
@@ -93,7 +93,7 @@ static void add_records(struct ldb_context *ldb,
                el[2].name = talloc_strdup(tmp_ctx, "uid");
                el[2].num_values = 1;
                el[2].values = vals[2];
-               vals[2][0].data = (uint8_t *)ldb_casefold(ldb, tmp_ctx, name);
+               vals[2][0].data = (uint8_t *)ldb_casefold(ldb, tmp_ctx, name, strlen(name));
                vals[2][0].length = strlen((char *)vals[2][0].data);
 
                el[3].flags = 0;
index 883597108a03638696bf671689ebf91be95d9d33..6c683a1e33068eb49f8d210f7c403966a3df75b7 100644 (file)
@@ -147,17 +147,21 @@ struct ldb_context *ldb_wrap_connect(TALLOC_CTX *mem_ctx,
                talloc_free(ldb);
                return NULL;
        }
-       
-       if (lp_ctx != NULL && strcmp(lp_sam_url(lp_ctx), url) == 0) {
-               dsdb_set_global_schema(ldb);
-       }
 
+       /* This must be done before we load the schema, as these
+        * handlers for objectSid and objectGUID etc must take
+        * precedence over the 'binary attribute' declaration in the
+        * schema */
        ret = ldb_register_samba_handlers(ldb);
        if (ret == -1) {
                talloc_free(ldb);
                return NULL;
        }
 
+       if (lp_ctx != NULL && strcmp(lp_sam_url(lp_ctx), url) == 0) {
+               dsdb_set_global_schema(ldb);
+       }
+
        ldb_set_debug(ldb, ldb_wrap_debug, NULL);
 
        ldb_set_utf8_fns(ldb, NULL, wrap_casefold);
index e626b6ef8aa7d0797e59e4117553ed5a0a219365..f2982302abb2ac9794b3d36a5215ba93e3377444 100644 (file)
@@ -29,7 +29,7 @@ struct cli_credentials;
 struct loadparm_context;
 struct event_context;
 
-char *wrap_casefold(void *context, void *mem_ctx, const char *s);
+char *wrap_casefold(void *context, void *mem_ctx, const char *s, size_t n);
 
 struct ldb_context *ldb_wrap_connect(TALLOC_CTX *mem_ctx,
                                     struct event_context *ev,
index b258e47bbaf1646b5d09d7c36ea33baa9eab5fa8..57b34b7ae73d8aa698dc9df4fc164dc22a8b4512 100644 (file)
@@ -176,7 +176,7 @@ _PUBLIC_ DATA_BLOB data_blob_string_const(const char *str)
 {
        DATA_BLOB blob;
        blob.data = discard_const_p(uint8_t, str);
-       blob.length = strlen(str);
+       blob.length = str ? strlen(str) : 0;
        return blob;
 }
 
index 0a7433696e586e84d2a43aa77c6471dd254c5f49..fab729c0367b07985ef8014ff35e7db8268e4399 100644 (file)
@@ -125,9 +125,9 @@ int gendb_add_ldif(struct ldb_context *ldb, const char *ldif_string)
        return ret;
 }
 
-char *wrap_casefold(void *context, void *mem_ctx, const char *s)
+char *wrap_casefold(void *context, void *mem_ctx, const char *s, size_t n)
 {
-       return strupper_talloc(mem_ctx, s);
+       return strupper_talloc_n(mem_ctx, s, n);
 }
 
 
index 030ba7ebeef6aa0a4145eb47bbf61d665ba35bc5..43f98ae1a9f2f6f6abaace007b6345b875f191de 100644 (file)
@@ -22,6 +22,6 @@ int gendb_search_dn(struct ldb_context *ldb,
                 struct ldb_message ***res,
                 const char * const *attrs);
 int gendb_add_ldif(struct ldb_context *ldb, const char *ldif_string);
-char *wrap_casefold(void *context, void *mem_ctx, const char *s);
+char *wrap_casefold(void *context, void *mem_ctx, const char *s, size_t n);
 
 #endif /* __LIB_UTIL_UTIL_LDB_H__ */
index 007ba26277c8470d897faa87b7b9fb4b5d15e606..b5333d7b8e39047fb6c23e721653de1226dca556 100644 (file)
@@ -5,8 +5,7 @@
 
 /* @(#) $Id$ */
 
-#define ZLIB_INTERNAL
-#include "zlib.h"
+#include "zutil.h"
 
 #define BASE 65521UL    /* largest prime smaller than 65536 */
 #define NMAX 5552
index df04f0148e6d6a22ce0f5bc4e3eeeb7bb54ca605..40a53cd476964d8dd32415f6a942524c48372b61 100644 (file)
@@ -5,8 +5,7 @@
 
 /* @(#) $Id$ */
 
-#define ZLIB_INTERNAL
-#include "zlib.h"
+#include "zutil.h"
 
 /* ===========================================================================
      Compresses the source buffer into the destination buffer. The level
@@ -29,7 +28,7 @@ int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
     z_stream stream;
     int err;
 
-    stream.next_in = (Bytef*)source;
+    stream.next_in = source;
     stream.avail_in = (uInt)sourceLen;
 #ifdef MAXSEG_64K
     /* Check for source > 64K on 16-bit machine: */
index f658a9ef55ee89e930df72907790d11f5504e3ce..4d6e699e6007ebf90faccdd4b837bef5d8462b3e 100644 (file)
@@ -11,6 +11,8 @@
 
 /* @(#) $Id$ */
 
+#include "zutil.h"      /* for STDC and FAR definitions */
+
 /*
   Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
   protection on the static variables used to control the first-use generation
@@ -26,8 +28,6 @@
 #  endif /* !DYNAMIC_CRC_TABLE */
 #endif /* MAKECRCH */
 
-#include "zutil.h"      /* for STDC and FAR definitions */
-
 #define local static
 
 /* Find a four-byte integer type for crc32_little() and crc32_big(). */
index 29ce1f64a57a18f3c939f879d301ece10ac6da1b..2720aab91122f917718c8b71c25a6697360dca42 100644 (file)
@@ -154,9 +154,6 @@ local const config configuration_table[10] = {
  * meaning.
  */
 
-#define EQUAL 0
-/* result of memcmp for equal strings */
-
 #ifndef NO_DUMMY_DECL
 struct static_tree_desc_s {int dummy;}; /* for buggy compilers */
 #endif
@@ -297,7 +294,7 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
     if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
         s->pending_buf == Z_NULL) {
         s->status = FINISH_STATE;
-        strm->msg = (char*)ERR_MSG(Z_MEM_ERROR);
+        strm->msg = ERR_MSG(Z_MEM_ERROR);
         deflateEnd (strm);
         return Z_MEM_ERROR;
     }
@@ -1226,6 +1223,9 @@ local uInt longest_match_fast(s, cur_match)
 }
 
 #ifdef DEBUG
+#define EQUAL 0
+/* result of memcmp for equal strings */
+
 /* ===========================================================================
  * Check that the match at match_start is indeed a match.
  */
index 7e90f4928fc0b67a4a4a5c76ab289394c41c7e55..0b51297936856b56f506cc785226a63fbd169de7 100644 (file)
@@ -7,8 +7,6 @@
 
 /* @(#) $Id$ */
 
-#include <stdio.h>
-
 #include "zutil.h"
 
 #ifdef NO_DEFLATE       /* for compatibility with old definition */
@@ -46,7 +44,7 @@ extern void   free   OF((voidpf ptr));
 static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
 
 /* gzip flag byte */
-#define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
+/*#define ASCII_FLAG   0x01 *//* bit 0 set: file probably ascii text */
 #define HEAD_CRC     0x02 /* bit 1 set: header CRC present */
 #define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
 #define ORIG_NAME    0x08 /* bit 3 set: original file name present */
@@ -98,7 +96,7 @@ local gzFile gz_open (path, mode, fd)
     int err;
     int level = Z_DEFAULT_COMPRESSION; /* compression level */
     int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */
-    char *p = (char*)mode;
+    const char *p = mode;
     gz_stream *s;
     char fmode[80]; /* copy of mode, without the compression level */
     char *m = fmode;
@@ -565,7 +563,7 @@ int ZEXPORT gzwrite (file, buf, len)
 
     if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
 
-    s->stream.next_in = (Bytef*)buf;
+    s->stream.next_in = (const Bytef*)buf;
     s->stream.avail_in = len;
 
     while (s->stream.avail_in != 0) {
@@ -694,7 +692,7 @@ int ZEXPORT gzputs(file, s)
     gzFile file;
     const char *s;
 {
-    return gzwrite(file, (char*)s, (unsigned)strlen(s));
+    return gzwrite(file, (voidpc)s, (unsigned)strlen(s));
 }
 
 
@@ -988,7 +986,7 @@ const char * ZEXPORT gzerror (file, errnum)
     gzFile file;
     int *errnum;
 {
-    char *m;
+    const char *m;
     gz_stream *s = (gz_stream*)file;
 
     if (s == NULL) {
@@ -998,9 +996,9 @@ const char * ZEXPORT gzerror (file, errnum)
     *errnum = s->z_err;
     if (*errnum == Z_OK) return (const char*)"";
 
-    m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg);
+    m = (*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg);
 
-    if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err);
+    if (m == NULL || *m == '\0') m = ERR_MSG(s->z_err);
 
     TRYFREE(s->msg);
     s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3);
diff --git