diff options
Diffstat (limited to 'source4')
136 files changed, 4835 insertions, 2905 deletions
diff --git a/source4/auth/gensec/gensec.h b/source4/auth/gensec/gensec.h index 2a89e67ed2..2830297ffe 100644 --- a/source4/auth/gensec/gensec.h +++ b/source4/auth/gensec/gensec.h @@ -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 diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c index 1541c88e07..20d08078be 100644 --- a/source4/auth/gensec/gensec_gssapi.c +++ b/source4/auth/gensec/gensec_gssapi.c @@ -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; } diff --git a/source4/auth/gensec/spnego.c b/source4/auth/gensec/spnego.c index 1544326bb1..1855e0583d 100644 --- a/source4/auth/gensec/spnego.c +++ b/source4/auth/gensec/spnego.c @@ -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,13 +1003,45 @@ 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")); diff --git a/source4/auth/gensec/spnego_parse.c b/source4/auth/gensec/spnego_parse.c index 8012a83ba8..5ea8cf7100 100644 --- a/source4/auth/gensec/spnego_parse.c +++ b/source4/auth/gensec/spnego_parse.c @@ -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; +} diff --git a/source4/build/m4/check_path.m4 b/source4/build/m4/check_path.m4 index a209a4b85a..c45a803633 100644 --- a/source4/build/m4/check_path.m4 +++ b/source4/build/m4/check_path.m4 @@ -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) # @@ -87,25 +87,9 @@ 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 diff --git a/source4/cldap_server/netlogon.c b/source4/cldap_server/netlogon.c index f263f33d48..0b146b3c7d 100644 --- a/source4/cldap_server/netlogon.c +++ b/source4/cldap_server/netlogon.c @@ -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); diff --git a/source4/dsdb/common/flags.h b/source4/dsdb/common/flags.h index e8802fdf9c..bdd61a363c 100644 --- a/source4/dsdb/common/flags.h +++ b/source4/dsdb/common/flags.h @@ -119,6 +119,17 @@ #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 diff --git a/source4/dsdb/config.mk b/source4/dsdb/config.mk index 7b700fda22..63e8a77ce4 100644 --- a/source4/dsdb/config.mk +++ b/source4/dsdb/config.mk @@ -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 diff --git a/source4/dsdb/repl/drepl_out_helpers.c b/source4/dsdb/repl/drepl_out_helpers.c index 3629a3b92b..80b398ef5c 100644 --- a/source4/dsdb/repl/drepl_out_helpers.c +++ b/source4/dsdb/repl/drepl_out_helpers.c @@ -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)); diff --git a/source4/dsdb/samdb/ldb_modules/anr.c b/source4/dsdb/samdb/ldb_modules/anr.c index 1252c9ee42..4e2c527fe9 100644 --- a/source4/dsdb/samdb/ldb_modules/anr.c +++ b/source4/dsdb/samdb/ldb_modules/anr.c @@ -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); } diff --git a/source4/dsdb/samdb/ldb_modules/linked_attributes.c b/source4/dsdb/samdb/ldb_modules/linked_attributes.c index 04b9987071..e64472432d 100644 --- a/source4/dsdb/samdb/ldb_modules/linked_attributes.c +++ b/source4/dsdb/samdb/ldb_modules/linked_attributes.c @@ -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, diff --git a/source4/dsdb/samdb/ldb_modules/normalise.c b/source4/dsdb/samdb/ldb_modules/normalise.c index 8de9e33002..3306fd3c33 100644 --- a/source4/dsdb/samdb/ldb_modules/normalise.c +++ b/source4/dsdb/samdb/ldb_modules/normalise.c @@ -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; diff --git a/source4/dsdb/samdb/ldb_modules/partition.c b/source4/dsdb/samdb/ldb_modules/partition.c index 9285d6d0d8..9cae6ab7b5 100644 --- a/source4/dsdb/samdb/ldb_modules/partition.c +++ b/source4/dsdb/samdb/ldb_modules/partition.c @@ -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: " diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index 88590f306b..bd491bd011 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -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; diff --git a/source4/dsdb/samdb/ldb_modules/schema_fsmo.c b/source4/dsdb/samdb/ldb_modules/schema_fsmo.c index 87ada855d3..968b19c038 100644 --- a/source4/dsdb/samdb/ldb_modules/schema_fsmo.c +++ b/source4/dsdb/samdb/ldb_modules/schema_fsmo.c @@ -32,6 +32,40 @@ #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 }; diff --git a/source4/dsdb/samdb/ldb_modules/schema_syntax.c b/source4/dsdb/samdb/ldb_modules/schema_syntax.c index d800e4b6d2..ab9f32c913 100644 --- a/source4/dsdb/samdb/ldb_modules/schema_syntax.c +++ b/source4/dsdb/samdb/ldb_modules/schema_syntax.c @@ -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; } diff --git a/source4/dsdb/samdb/ldb_modules/simple_ldap_map.c b/source4/dsdb/samdb/ldb_modules/simple_ldap_map.c index 6e967aab2f..8f92995145 100644 --- a/source4/dsdb/samdb/ldb_modules/simple_ldap_map.c +++ b/source4/dsdb/samdb/ldb_modules/simple_ldap_map.c @@ -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); diff --git a/source4/dsdb/samdb/ldb_modules/tests/samba3sam.py b/source4/dsdb/samdb/ldb_modules/tests/samba3sam.py index 7c408d0436..428e6b4d4b 100644 --- a/source4/dsdb/samdb/ldb_modules/tests/samba3sam.py +++ b/source4/dsdb/samdb/ldb_modules/tests/samba3sam.py @@ -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() diff --git a/source4/dsdb/samdb/samdb.h b/source4/dsdb/samdb/samdb.h index 3e92671fa0..f24a75fd8f 100644 --- a/source4/dsdb/samdb/samdb.h +++ b/source4/dsdb/samdb/samdb.h @@ -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" diff --git a/source4/dsdb/schema/schema.h b/source4/dsdb/schema/schema.h index a4e455ae33..68dc8197cb 100644 --- a/source4/dsdb/schema/schema.h +++ b/source4/dsdb/schema/schema.h @@ -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 index 51343817b0..0000000000 --- a/source4/dsdb/schema/schema_constructed.c +++ /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 index 0000000000..9d93af9260 --- /dev/null +++ b/source4/dsdb/schema/schema_description.c @@ -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; +} diff --git a/source4/dsdb/schema/schema_init.c b/source4/dsdb/schema/schema_init.c index 85fdbe9e87..3ed7daee59 100644 --- a/source4/dsdb/schema/schema_init.c +++ b/source4/dsdb/schema/schema_init.c @@ -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 index 0000000000..ca26ffd206 --- /dev/null +++ b/source4/dsdb/schema/schema_query.c @@ -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 index 0000000000..0ca26c0fc7 --- /dev/null +++ b/source4/dsdb/schema/schema_set.c @@ -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; +} diff --git a/source4/dsdb/schema/schema_syntax.c b/source4/dsdb/schema/schema_syntax.c index beacfc49c2..97cd0020a9 100644 --- a/source4/dsdb/schema/schema_syntax.c +++ b/source4/dsdb/schema/schema_syntax.c @@ -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; diff --git a/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c b/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c index 8dbd087da6..a6f0f31246 100644 --- a/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c +++ b/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c @@ -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, diff --git a/source4/heimdal/lib/gssapi/krb5/cfx.c b/source4/heimdal/lib/gssapi/krb5/cfx.c index 6452f802ab..bc0d736e81 100755 --- a/source4/heimdal/lib/gssapi/krb5/cfx.c +++ b/source4/heimdal/lib/gssapi/krb5/cfx.c @@ -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); diff --git a/source4/heimdal/lib/gssapi/krb5/gsskrb5-private.h b/source4/heimdal/lib/gssapi/krb5/gsskrb5-private.h index 64a0dd36b1..f6edb8b247 100644 --- a/source4/heimdal/lib/gssapi/krb5/gsskrb5-private.h +++ b/source4/heimdal/lib/gssapi/krb5/gsskrb5-private.h @@ -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*/, diff --git a/source4/heimdal/lib/gssapi/krb5/unwrap.c b/source4/heimdal/lib/gssapi/krb5/unwrap.c index eec4078a70..c287469e96 100644 --- a/source4/heimdal/lib/gssapi/krb5/unwrap.c +++ b/source4/heimdal/lib/gssapi/krb5/unwrap.c @@ -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 */ diff --git a/source4/heimdal/lib/gssapi/krb5/wrap.c b/source4/heimdal/lib/gssapi/krb5/wrap.c index 6d00f2adcf..bedeace4dd 100644 --- a/source4/heimdal/lib/gssapi/krb5/wrap.c +++ b/source4/heimdal/lib/gssapi/krb5/wrap.c @@ -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); diff --git a/source4/kdc/hdb-ldb.c b/source4/kdc/hdb-ldb.c index 8f8ce3074b..ef3a0bcb8a 100644 --- a/source4/kdc/hdb-ldb.c +++ b/source4/kdc/hdb-ldb.c @@ -45,14 +45,22 @@ #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); diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c index cab1446ff3..bee271eaa9 100644 --- a/source4/kdc/pac-glue.c +++ b/source4/kdc/pac-glue.c @@ -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, diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index b86df5dc9f..4d076684cd 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -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 diff --git a/source4/lib/charset/charset.h b/source4/lib/charset/charset.h index baa7df532b..c49745cd7f 100644 --- a/source4/lib/charset/charset.h +++ b/source4/lib/charset/charset.h @@ -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); diff --git a/source4/lib/charset/iconv.c b/source4/lib/charset/iconv.c index 4f4bc8fd2d..d4f930b462 100644 --- a/source4/lib/charset/iconv.c +++ b/source4/lib/charset/iconv.c @@ -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) { diff --git a/source4/lib/charset/util_unistr.c b/source4/lib/charset/util_unistr.c index 19a4f3236c..09ec7b0471 100644 --- a/source4/lib/charset/util_unistr.c +++ b/source4/lib/charset/util_unistr.c @@ -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; @@ -562,6 +563,16 @@ _PUBLIC_ char *strupper_talloc(TALLOC_CTX *ctx, const char *src) } /** + 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. **/ _PUBLIC_ void strlower_m(char *s) diff --git a/source4/lib/compression/lzxpress.c b/source4/lib/compression/lzxpress.c new file mode 100644 index 0000000000..506305176f --- /dev/null +++ b/source4/lib/compression/lzxpress.c @@ -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 index 0000000000..4862fd2635 --- /dev/null +++ b/source4/lib/compression/lzxpress.h @@ -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 */ diff --git a/source4/lib/ldb-samba/config.mk b/source4/lib/ldb-samba/config.mk index cdec317d1f..f84b44dfc7 100644 --- a/source4/lib/ldb-samba/config.mk +++ b/source4/lib/ldb-samba/config.mk @@ -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))) diff --git a/source4/lib/ldb-samba/ldif_handlers.c b/source4/lib/ldb-samba/ldif_handlers.c index 1f718cc1c5..a16582d294 100644 --- a/source4/lib/ldb-samba/ldif_handlers.c +++ b/source4/lib/ldb-samba/ldif_handlers.c @@ -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 index 0000000000..e37c4166c8 --- /dev/null +++ b/source4/lib/ldb-samba/ldif_handlers.h @@ -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__ */ + diff --git a/source4/lib/ldb/common/attrib_handlers.c b/source4/lib/ldb/common/attrib_handlers.c index 8ed2763d4d..fb57e2dadc 100644 --- a/source4/lib/ldb/common/attrib_handlers.c +++ b/source4/lib/ldb/common/attrib_handlers.c @@ -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 */ diff --git a/source4/lib/ldb/common/ldb_attributes.c b/source4/lib/ldb/common/ldb_attributes.c index effd93ae26..747f241781 100644 --- a/source4/lib/ldb/common/ldb_attributes.c +++ b/source4/lib/ldb/common/ldb_attributes.c @@ -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; } diff --git a/source4/lib/ldb/common/ldb_dn.c b/source4/lib/ldb/common/ldb_dn.c index 08911344b7..c0d36cfbf3 100644 --- a/source4/lib/ldb/common/ldb_dn.c +++ b/source4/lib/ldb/common/ldb_dn.c @@ -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; diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c index c1ea9db56b..2f5fe1d18c 100644 --- a/source4/lib/ldb/common/ldb_msg.c +++ b/source4/lib/ldb/common/ldb_msg.c @@ -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; diff --git a/source4/lib/ldb/common/ldb_utf8.c b/source4/lib/ldb/common/ldb_utf8.c index b7b4a60122..69ee2b6964 100644 --- a/source4/lib/ldb/common/ldb_utf8.c +++ b/source4/lib/ldb/common/ldb_utf8.c @@ -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); } /* diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 0338ae1d93..937029f52c 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -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 diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index d7c2efe8a1..e1026ab781 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -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); diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index 8742e257f3..a0e63c8da1 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -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; diff --git a/source4/lib/ldb/ldb_sqlite3/schema b/source4/lib/ldb/ldb_sqlite3/schema index 08dc50de08..ab7c5cc406 100644 --- a/source4/lib/ldb/ldb_sqlite3/schema +++ b/source4/lib/ldb/ldb_sqlite3/schema @@ -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'; - diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index 1b6d9feed6..269305a468 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -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; } diff --git a/source4/lib/ldb/modules/operational.c b/source4/lib/ldb/modules/operational.c index 7dc4ae08c3..a59e81becd 100644 --- a/source4/lib/ldb/modules/operational.c +++ b/source4/lib/ldb/modules/operational.c @@ -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; } diff --git a/source4/lib/ldb/tests/python/ldap.py b/source4/lib/ldb/tests/python/ldap.py index 042469602c..bc6f80e856 100755 --- a/source4/lib/ldb/tests/python/ldap.py +++ b/source4/lib/ldb/tests/python/ldap.py @@ -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) diff --git a/source4/lib/ldb/tests/test-attribs.ldif b/source4/lib/ldb/tests/test-attribs.ldif index 0bb3ebead6..79508c4b7b 100644 --- a/source4/lib/ldb/tests/test-attribs.ldif +++ b/source4/lib/ldb/tests/test-attribs.ldif @@ -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 diff --git a/source4/lib/ldb/tests/test-index.ldif b/source4/lib/ldb/tests/test-index.ldif index a793537187..268173641d 100644 --- a/source4/lib/ldb/tests/test-index.ldif +++ b/source4/lib/ldb/tests/test-index.ldif @@ -5,7 +5,3 @@ dn: @INDEXLIST dn: @ATTRIBUTES uid: CASE_INSENSITIVE -dn: @SUBCLASSES -top: person -person: organizationalPerson -organizationalPerson: OpenLDAPperson diff --git a/source4/lib/ldb/tools/ldbtest.c b/source4/lib/ldb/tools/ldbtest.c index 6d141478ad..169ff02da1 100644 --- a/source4/lib/ldb/tools/ldbtest.c +++ b/source4/lib/ldb/tools/ldbtest.c @@ -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; diff --git a/source4/lib/ldb_wrap.c b/source4/lib/ldb_wrap.c index 883597108a..6c683a1e33 100644 --- a/source4/lib/ldb_wrap.c +++ b/source4/lib/ldb_wrap.c @@ -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); diff --git a/source4/lib/ldb_wrap.h b/source4/lib/ldb_wrap.h index e626b6ef8a..f2982302ab 100644 --- a/source4/lib/ldb_wrap.h +++ b/source4/lib/ldb_wrap.h @@ -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, diff --git a/source4/lib/util/data_blob.c b/source4/lib/util/data_blob.c index b258e47bba..57b34b7ae7 100644 --- a/source4/lib/util/data_blob.c +++ b/source4/lib/util/data_blob.c @@ -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; } diff --git a/source4/lib/util/util_ldb.c b/source4/lib/util/util_ldb.c index 0a7433696e..fab729c036 100644 --- a/source4/lib/util/util_ldb.c +++ b/source4/lib/util/util_ldb.c @@ -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); } diff --git a/source4/lib/util/util_ldb.h b/source4/lib/util/util_ldb.h index 030ba7ebee..43f98ae1a9 100644 --- a/source4/lib/util/util_ldb.h +++ b/source4/lib/util/util_ldb.h @@ -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__ */ diff --git a/source4/lib/zlib/adler32.c b/source4/lib/zlib/adler32.c index 007ba26277..b5333d7b8e 100644 --- a/source4/lib/zlib/adler32.c +++ b/source4/lib/zlib/adler32.c @@ -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 diff --git a/source4/lib/zlib/compress.c b/source4/lib/zlib/compress.c index df04f0148e..40a53cd476 100644 --- a/source4/lib/zlib/compress.c +++ b/source4/lib/zlib/compress.c @@ -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: */ diff --git a/source4/lib/zlib/crc32.c b/source4/lib/zlib/crc32.c index f658a9ef55..4d6e699e60 100644 --- a/source4/lib/zlib/crc32.c +++ b/source4/lib/zlib/crc32.c @@ -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(). */ diff --git a/source4/lib/zlib/deflate.c b/source4/lib/zlib/deflate.c index 29ce1f64a5..2720aab911 100644 --- a/source4/lib/zlib/deflate.c +++ b/source4/lib/zlib/deflate.c @@ -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. */ diff --git a/source4/lib/zlib/gzio.c b/source4/lib/zlib/gzio.c index 7e90f4928f..0b51297936 100644 --- a/source4/lib/zlib/gzio.c +++ b/source4/lib/zlib/gzio.c @@ -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 a/source4/lib/zlib/infback.c b/source4/lib/zlib/infback.c index 455dbc9ee8..5680937f34 100644 --- a/source4/lib/zlib/infback.c +++ b/source4/lib/zlib/infback.c @@ -246,7 +246,7 @@ out_func out; void FAR *out_desc; { struct inflate_state FAR *state; - unsigned char FAR *next; /* next input */ + unsigned const char FAR *next; /* next input */ unsigned char FAR *put; /* next output */ unsigned have, left; /* available input and output */ unsigned long hold; /* bit buffer */ @@ -308,7 +308,7 @@ void FAR *out_desc; state->mode = TABLE; break; case 3: - strm->msg = (char *)"invalid block type"; + strm->msg = "invalid block type"; state->mode = BAD; } DROPBITS(2); @@ -319,7 +319,7 @@ void FAR *out_desc; BYTEBITS(); /* go to byte boundary */ NEEDBITS(32); if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { - strm->msg = (char *)"invalid stored block lengths"; + strm->msg = "invalid stored block lengths"; state->mode = BAD; break; } @@ -357,7 +357,7 @@ void FAR *out_desc; DROPBITS(4); #ifndef PKZIP_BUG_WORKAROUND if (state->nlen > 286 || state->ndist > 30) { - strm->msg = (char *)"too many length or distance symbols"; + strm->msg = "too many length or distance symbols"; state->mode = BAD; break; } @@ -379,7 +379,7 @@ void FAR *out_desc; ret = inflate_table(CODES, state->lens, 19, &(state->next), &(state->lenbits), state->work); if (ret) { - strm->msg = (char *)"invalid code lengths set"; + strm->msg = "invalid code lengths set"; state->mode = BAD; break; } @@ -403,7 +403,7 @@ void FAR *out_desc; NEEDBITS(this.bits + 2); DROPBITS(this.bits); if (state->have == 0) { - strm->msg = (char *)"invalid bit length repeat"; + strm->msg = "invalid bit length repeat"; state->mode = BAD; break; } @@ -426,7 +426,7 @@ void FAR *out_desc; DROPBITS(7); } if (state->have + copy > state->nlen + state->ndist) { - strm->msg = (char *)"invalid bit length repeat"; + strm->msg = "invalid bit length repeat"; state->mode = BAD; break; } @@ -445,7 +445,7 @@ void FAR *out_desc; ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), &(state->lenbits), state->work); if (ret) { - strm->msg = (char *)"invalid literal/lengths set"; + strm->msg = "invalid literal/lengths set"; state->mode = BAD; break; } @@ -454,7 +454,7 @@ void FAR *out_desc; ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, &(state->next), &(state->distbits), state->work); if (ret) { - strm->msg = (char *)"invalid distances set"; + strm->msg = "invalid distances set"; state->mode = BAD; break; } @@ -512,7 +512,7 @@ void FAR *out_desc; /* invalid code */ if (this.op & 64) { - strm->msg = (char *)"invalid literal/length code"; + strm->msg = "invalid literal/length code"; state->mode = BAD; break; } @@ -544,7 +544,7 @@ void FAR *out_desc; } DROPBITS(this.bits); if (this.op & 64) { - strm->msg = (char *)"invalid distance code"; + strm->msg = "invalid distance code"; state->mode = BAD; break; } @@ -559,7 +559,7 @@ void FAR *out_desc; } if (state->offset > state->wsize - (state->whave < state->wsize ? left : 0)) { - strm->msg = (char *)"invalid distance too far back"; + strm->msg = "invalid distance too far back"; state->mode = BAD; break; } diff --git a/source4/lib/zlib/inffast.c b/source4/lib/zlib/inffast.c index bbee92ed1e..bfc727694a 100644 --- a/source4/lib/zlib/inffast.c +++ b/source4/lib/zlib/inffast.c @@ -69,8 +69,8 @@ z_streamp strm; unsigned start; /* inflate()'s starting value for strm->avail_out */ { struct inflate_state FAR *state; - unsigned char FAR *in; /* local strm->next_in */ - unsigned char FAR *last; /* while in < last, enough input available */ + unsigned const char FAR *in; /* local strm->next_in */ + unsigned const char FAR *last; /* while in < last, enough input available */ unsigned char FAR *out; /* local strm->next_out */ unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ unsigned char FAR *end; /* while out < end, enough space available */ @@ -187,7 +187,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ if (dist > op) { /* see if copy from window */ op = dist - op; /* distance back in window */ if (op > whave) { - strm->msg = (char *)"invalid distance too far back"; + strm->msg = "invalid distance too far back"; state->mode = BAD; break; } @@ -263,7 +263,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ goto dodist; } else { - strm->msg = (char *)"invalid distance code"; + strm->msg = "invalid distance code"; state->mode = BAD; break; } @@ -278,7 +278,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ break; } else { - strm->msg = (char *)"invalid literal/length code"; + strm->msg = "invalid literal/length code"; state->mode = BAD; break; } diff --git a/source4/lib/zlib/inflate.c b/source4/lib/zlib/inflate.c index 0c1ff17951..fbecefd8f5 100644 --- a/source4/lib/zlib/inflate.c +++ b/source4/lib/zlib/inflate.c @@ -97,7 +97,7 @@ local int updatewindow OF((z_streamp strm, unsigned out)); #ifdef BUILDFIXED void makefixed OF((void)); #endif -local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, +local unsigned syncsearch OF((unsigned FAR *have, unsigned const char FAR *buf, unsigned len)); int ZEXPORT inflateReset2(strm, flags) @@ -565,7 +565,7 @@ z_streamp strm; int flush; { struct inflate_state FAR *state; - unsigned char FAR *next; /* next input */ + unsigned const char FAR *next; /* next input */ unsigned char FAR *put; /* next output */ unsigned have, left; /* available input and output */ unsigned long hold; /* bit buffer */ @@ -617,19 +617,19 @@ int flush; if ( #endif ((BITS(8) << 8) + (hold >> 8)) % 31) { - strm->msg = (char *)"incorrect header check"; + strm->msg = "incorrect header check"; state->mode = BAD; break; } if (BITS(4) != Z_DEFLATED) { - strm->msg = (char *)"unknown compression method"; + strm->msg = "unknown compression method"; state->mode = BAD; break; } DROPBITS(4); len = BITS(4) + 8; if (len > state->wbits) { - strm->msg = (char *)"invalid window size"; + strm->msg = "invalid window size"; state->mode = BAD; break; } @@ -644,12 +644,12 @@ int flush; NEEDBITS(16); state->flags = (int)(hold); if ((state->flags & 0xff) != Z_DEFLATED) { - strm->msg = (char *)"unknown compression method"; + strm->msg = "unknown compression method"; state->mode = BAD; break; } if (state->flags & 0xe000) { - strm->msg = (char *)"unknown header flags set"; + strm->msg = "unknown header flags set"; state->mode = BAD; break; } @@ -753,7 +753,7 @@ int flush; if (state->flags & 0x0200) { NEEDBITS(16); if (hold != (state->check & 0xffff)) { - strm->msg = (char *)"header crc mismatch"; + strm->msg = "header crc mismatch"; state->mode = BAD; break; } @@ -808,7 +808,7 @@ int flush; state->mode = TABLE; break; case 3: - strm->msg = (char *)"invalid block type"; + strm->msg = "invalid block type"; state->mode = BAD; } DROPBITS(2); @@ -817,7 +817,7 @@ int flush; BYTEBITS(); /* go to byte boundary */ NEEDBITS(32); if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { - strm->msg = (char *)"invalid stored block lengths"; + strm->msg = "invalid stored block lengths"; state->mode = BAD; break; } @@ -853,7 +853,7 @@ int flush; DROPBITS(4); #ifndef PKZIP_BUG_WORKAROUND if (state->nlen > 286 || state->ndist > 30) { - strm->msg = (char *)"too many length or distance symbols"; + strm->msg = "too many length or distance symbols"; state->mode = BAD; break; } @@ -875,7 +875,7 @@ int flush; ret = inflate_table(CODES, state->lens, 19, &(state->next), &(state->lenbits), state->work); if (ret) { - strm->msg = (char *)"invalid code lengths set"; + strm->msg = "invalid code lengths set"; state->mode = BAD; break; } @@ -899,7 +899,7 @@ int flush; NEEDBITS(this.bits + 2); DROPBITS(this.bits); if (state->have == 0) { - strm->msg = (char *)"invalid bit length repeat"; + strm->msg = "invalid bit length repeat"; state->mode = BAD; break; } @@ -922,7 +922,7 @@ int flush; DROPBITS(7); } if (state->have + copy > state->nlen + state->ndist) { - strm->msg = (char *)"invalid bit length repeat"; + strm->msg = "invalid bit length repeat"; state->mode = BAD; break; } @@ -941,7 +941,7 @@ int flush; ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), &(state->lenbits), state->work); if (ret) { - strm->msg = (char *)"invalid literal/lengths set"; + strm->msg = "invalid literal/lengths set"; state->mode = BAD; break; } @@ -950,7 +950,7 @@ int flush; ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, &(state->next), &(state->distbits), state->work); if (ret) { - strm->msg = (char *)"invalid distances set"; + strm->msg = "invalid distances set"; state->mode = BAD; break; } @@ -993,7 +993,7 @@ int flush; break; } if (this.op & 64) { - strm->msg = (char *)"invalid literal/length code"; + strm->msg = "invalid literal/length code"; state->mode = BAD; break; } @@ -1025,7 +1025,7 @@ int flush; } DROPBITS(this.bits); if (this.op & 64) { - strm->msg = (char *)"invalid distance code"; + strm->msg = "invalid distance code"; state->mode = BAD; break; } @@ -1040,13 +1040,13 @@ int flush; } #ifdef INFLATE_STRICT if (state->offset > state->dmax) { - strm->msg = (char *)"invalid distance too far back"; + strm->msg = "invalid distance too far back"; state->mode = BAD; break; } #endif if (state->offset > state->whave + out - left) { - strm->msg = (char *)"invalid distance too far back"; + strm->msg = "invalid distance too far back"; state->mode = BAD; break; } @@ -1098,7 +1098,7 @@ int flush; state->flags ? hold : #endif REVERSE(hold)) != state->check) { - strm->msg = (char *)"incorrect data check"; + strm->msg = "incorrect data check"; state->mode = BAD; break; } @@ -1111,7 +1111,7 @@ int flush; if (state->wrap && state->flags) { NEEDBITS(32); if (hold != (state->total & 0xffffffffUL)) { - strm->msg = (char *)"incorrect length check"; + strm->msg = "incorrect length check"; state->mode = BAD; break; } @@ -1247,7 +1247,7 @@ gz_headerp head; */ local unsigned syncsearch(have, buf, len) unsigned FAR *have; -unsigned char FAR *buf; +unsigned const char FAR *buf; unsigned len; { unsigned got; diff --git a/source4/lib/zlib/trees.c b/source4/lib/zlib/trees.c index 395e4e1681..eb55679adc 100644 --- a/source4/lib/zlib/trees.c +++ b/source4/lib/zlib/trees.c @@ -150,8 +150,8 @@ local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); local int build_bl_tree OF((deflate_state *s)); local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, int blcodes)); -local void compress_block OF((deflate_state *s, ct_data *ltree, - ct_data *dtree)); +local void compress_block OF((deflate_state *s, const ct_data *ltree, + const ct_data *dtree)); local void set_data_type OF((deflate_state *s)); local unsigned bi_reverse OF((unsigned value, int length)); local void bi_windup OF((deflate_state *s)); @@ -986,7 +986,7 @@ void _tr_flush_block(s, buf, stored_len, eof) } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { #endif send_bits(s, (STATIC_TREES<<1)+eof, 3); - compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); + compress_block(s, static_ltree, static_dtree); #ifdef DEBUG s->compressed_len += 3 + s->static_len; #endif @@ -994,7 +994,7 @@ void _tr_flush_block(s, buf, stored_len, eof) send_bits(s, (DYN_TREES<<1)+eof, 3); send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, max_blindex+1); - compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); + compress_block(s, s->dyn_ltree, s->dyn_dtree); #ifdef DEBUG s->compressed_len += 3 + s->opt_len; #endif @@ -1071,8 +1071,8 @@ int _tr_tally (s, dist, lc) */ local void compress_block(s, ltree, dtree) deflate_state *s; - ct_data *ltree; /* literal tree */ - ct_data *dtree; /* distance tree */ + const ct_data *ltree; /* literal tree */ + const ct_data *dtree; /* distance tree */ { unsigned dist; /* distance of matched string */ int lc; /* match length or unmatched char (if dist == 0) */ diff --git a/source4/lib/zlib/uncompr.c b/source4/lib/zlib/uncompr.c index b59e3d0def..a052f22e74 100644 --- a/source4/lib/zlib/uncompr.c +++ b/source4/lib/zlib/uncompr.c @@ -5,8 +5,7 @@ /* @(#) $Id$ */ -#define ZLIB_INTERNAL -#include "zlib.h" +#include "zutil.h" /* =========================================================================== Decompresses the source buffer into the destination buffer. sourceLen is @@ -32,7 +31,7 @@ int ZEXPORT uncompress (dest, destLen, source, sourceLen) z_stream stream; int err; - stream.next_in = (Bytef*)source; + stream.next_in = source; stream.avail_in = (uInt)sourceLen; /* Check for source > 64K on 16-bit machine: */ if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; diff --git a/source4/lib/zlib/zlib.h b/source4/lib/zlib/zlib.h index 20a16d9588..edf09d2b1e 100644 --- a/source4/lib/zlib/zlib.h +++ b/source4/lib/zlib/zlib.h @@ -37,8 +37,14 @@ extern "C" { #endif -#define ZLIB_VERSION "1.2.3" -#define ZLIB_VERNUM 0x1230 +#define ZLIB_VERSION "1.2.3.1.Samba" +#define ZLIB_VERNUM 0x1231 +/* + * Modified for Samba by Stefan Metzmacher <metze@samba.org> 2008 + * + * inflateReset2() added and compiler warnings fixed + */ + /* The 'zlib' compression library provides in-memory compression and @@ -80,7 +86,7 @@ typedef void (*free_func) OF((voidpf opaque, voidpf address)); struct internal_state; typedef struct z_stream_s { - Bytef *next_in; /* next input byte */ + const Bytef *next_in; /* next input byte */ uInt avail_in; /* number of bytes available at next_in */ uLong total_in; /* total nb of input bytes read so far */ @@ -88,7 +94,7 @@ typedef struct z_stream_s { uInt avail_out; /* remaining free space at next_out */ uLong total_out; /* total nb of bytes output so far */ - char *msg; /* last error message, NULL if no error */ + const char *msg; /* last error message, NULL if no error */ struct internal_state FAR *state; /* not visible by applications */ alloc_func zalloc; /* used to allocate the internal state */ @@ -210,6 +216,16 @@ typedef gz_header FAR *gz_headerp; #define zlib_version zlibVersion() /* for compatibility with versions < 1.0.2 */ +#if (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1) +/** Use gcc attribute to check printf fns. a1 is the 1-based index of + * the parameter containing the format, and a2 the index of the first + * argument. Note that some gcc 2.x versions don't handle this + * properly **/ +#define _Z_PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) +#else +#define _Z_PRINTF_ATTRIBUTE(a1, a2) +#endif + /* basic functions */ ZEXTERN const char * ZEXPORT zlibVersion OF((void)); @@ -789,8 +805,6 @@ ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, destination. */ -ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, unsigned flags)); - ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); /* This function is equivalent to inflateEnd followed by inflateInit, @@ -889,7 +903,7 @@ ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, match the version of the header file. */ -typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef unsigned (*in_func) OF((void FAR *, unsigned const char FAR * FAR *)); typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, @@ -1134,7 +1148,8 @@ ZEXTERN int ZEXPORT gzwrite OF((gzFile file, (0 in case of error). */ -ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)) + _Z_PRINTF_ATTRIBUTE(2, 3); /* Converts, formats, and writes the args to the compressed file under control of the format string, as in fprintf. gzprintf returns the number of diff --git a/source4/lib/zlib/zutil.h b/source4/lib/zlib/zutil.h index b7d5eff81b..edd8e0acbb 100644 --- a/source4/lib/zlib/zutil.h +++ b/source4/lib/zlib/zutil.h @@ -56,7 +56,7 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ #define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] #define ERR_RETURN(strm,err) \ - return (strm->msg = (char*)ERR_MSG(err), (err)) + return (strm->msg = ERR_MSG(err), (err)) /* To be used only when the state is known to be valid */ /* common constants */ diff --git a/source4/libcli/config.mk b/source4/libcli/config.mk index affd8e277d..262a2cfa22 100644 --- a/source4/libcli/config.mk +++ b/source4/libcli/config.mk @@ -73,6 +73,14 @@ LIBCLI_NETLOGON_OBJ_FILES = $(addprefix $(libclisrcdir)/, \ $(eval $(call proto_header_template,$(libclisrcdir)/netlogon_proto.h,$(LIBCLI_NETLOGON_OBJ_FILES:.o=.c))) +[SUBSYSTEM::LIBCLI_DRSBLOBS] +PUBLIC_DEPENDENCIES = LIBNDR + +LIBCLI_DRSBLOBS_OBJ_FILES = $(addprefix $(libclisrcdir)/, \ + drsblobs.o) + +$(eval $(call proto_header_template,$(libclisrcdir)/drsblobs_proto.h,$(LIBCLI_DRSBLOBS_OBJ_FILES:.o=.c))) + [PYTHON::python_netbios] LIBRARY_REALNAME = samba/netbios.$(SHLIBEXT) PUBLIC_DEPENDENCIES = LIBCLI_NBT DYNCONFIG LIBSAMBA-HOSTCONFIG diff --git a/source4/libcli/drsblobs.c b/source4/libcli/drsblobs.c new file mode 100644 index 0000000000..126f2ccc40 --- /dev/null +++ b/source4/libcli/drsblobs.c @@ -0,0 +1,179 @@ +/* + Unix SMB/CIFS implementation. + + Manually parsed structures found in the DRS protocol + + 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 + (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 "libcli/drsblobs.h" + +/* parser auto-generated by pidl, then hand-modified by abartlet */ + +/* Modified to have 'count' specified */ +static enum ndr_err_code ndr_push_AuthenticationInformationArray_with_count(struct ndr_push *ndr, int ndr_flags, int count, + const struct AuthenticationInformationArray *r) +{ + uint32_t cntr_array_0; + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_push_align(ndr, 4)); + for (cntr_array_0 = 0; cntr_array_0 < count; cntr_array_0++) { + NDR_CHECK(ndr_push_AuthenticationInformation(ndr, NDR_SCALARS, &r->array[cntr_array_0])); + } + } + if (ndr_flags & NDR_BUFFERS) { + for (cntr_array_0 = 0; cntr_array_0 < count; cntr_array_0++) { + NDR_CHECK(ndr_push_AuthenticationInformation(ndr, NDR_BUFFERS, &r->array[cntr_array_0])); + } + } + return NDR_ERR_SUCCESS; +} + +/* Modified to have 'count' specified, and to allocate the array */ +static enum ndr_err_code ndr_pull_AuthenticationInformationArray_with_count(struct ndr_pull *ndr, int ndr_flags, int count, struct AuthenticationInformationArray *r) +{ + uint32_t cntr_array_0; + TALLOC_CTX *_mem_save_array_0; + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_pull_align(ndr, 4)); + NDR_PULL_ALLOC_N(ndr, r->array, count); + _mem_save_array_0 = NDR_PULL_GET_MEM_CTX(ndr); + NDR_PULL_SET_MEM_CTX(ndr, r->array, 0); + for (cntr_array_0 = 0; cntr_array_0 < count; cntr_array_0++) { + NDR_CHECK(ndr_pull_AuthenticationInformation(ndr, NDR_SCALARS, &r->array[cntr_array_0])); + } + NDR_PULL_SET_MEM_CTX(ndr, _mem_save_array_0, 0); + } + if (ndr_flags & NDR_BUFFERS) { + for (cntr_array_0 = 0; cntr_array_0 < count; cntr_array_0++) { + NDR_CHECK(ndr_pull_AuthenticationInformation(ndr, NDR_BUFFERS, &r->array[cntr_array_0])); + } + } + return NDR_ERR_SUCCESS; +} + +/* Modified to have 'count' specified */ +_PUBLIC_ void ndr_print_AuthenticationInformationArray_with_count(struct ndr_print *ndr, const char *name, int count, const struct AuthenticationInformationArray *r) +{ + uint32_t cntr_array_0; + ndr_print_struct(ndr, name, "AuthenticationInformationArray"); + ndr->depth++; + ndr->print(ndr, "%s: ARRAY(%d)", "array", (int)1); + ndr->depth++; + for (cntr_array_0=0;cntr_array_0<count;cntr_array_0++) { + char *idx_0=NULL; + if (asprintf(&idx_0, "[%d]", cntr_array_0) != -1) { + ndr_print_AuthenticationInformation(ndr, "array", &r->array[cntr_array_0]); + free(idx_0); + } + } + ndr->depth--; + ndr->depth--; +} + +/* Modified to call AuthenticationInformationArray with 'count' specified */ +_PUBLIC_ enum ndr_err_code ndr_push_trustAuthInOutBlob(struct ndr_push *ndr, int ndr_flags, const struct trustAuthInOutBlob *r) +{ + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_push_align(ndr, 4)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->count)); + NDR_CHECK(ndr_push_relative_ptr1(ndr, r->current)); + NDR_CHECK(ndr_push_relative_ptr1(ndr, r->previous)); + } + if (ndr_flags & NDR_BUFFERS) { + if (r->current) { + NDR_CHECK(ndr_push_relative_ptr2(ndr, r->current)); + NDR_CHECK(ndr_push_AuthenticationInformationArray_with_count(ndr, NDR_SCALARS|NDR_BUFFERS, r->count, r->current)); + } + if (r->previous) { + NDR_CHECK(ndr_push_relative_ptr2(ndr, r->previous)); + NDR_CHECK(ndr_push_AuthenticationInformationArray_with_count(ndr, NDR_SCALARS|NDR_BUFFERS, r->count, r->previous)); + } + } + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ enum ndr_err_code ndr_pull_trustAuthInOutBlob(struct ndr_pull *ndr, int ndr_flags, struct trustAuthInOutBlob *r) +{ + uint32_t _ptr_current; + TALLOC_CTX *_mem_save_current_0; + uint32_t _ptr_previous; + TALLOC_CTX *_mem_save_previous_0; + if (ndr_flags & NDR_SCALARS) { + NDR_CHECK(ndr_pull_align(ndr, 4)); + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->count)); + NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_current)); + if (_ptr_current) { + NDR_PULL_ALLOC(ndr, r->current); + NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->current, _ptr_current)); + } else { + r->current = NULL; + } + NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_previous)); + if (_ptr_previous) { + NDR_PULL_ALLOC(ndr, r->previous); + NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->previous, _ptr_previous)); + } else { + r->previous = NULL; + } + } + if (ndr_flags & NDR_BUFFERS) { + if (r->current) { + uint32_t _relative_save_offset; + _relative_save_offset = ndr->offset; + NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->current)); + _mem_save_current_0 = NDR_PULL_GET_MEM_CTX(ndr); + NDR_PULL_SET_MEM_CTX(ndr, r->current, 0); + NDR_CHECK(ndr_pull_AuthenticationInformationArray_with_count(ndr, NDR_SCALARS|NDR_BUFFERS, r->count, r->current)); + NDR_PULL_SET_MEM_CTX(ndr, _mem_save_current_0, 0); + ndr->offset = _relative_save_offset; + } + if (r->previous) { + uint32_t _relative_save_offset; + _relative_save_offset = ndr->offset; + NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->previous)); + _mem_save_previous_0 = NDR_PULL_GET_MEM_CTX(ndr); + NDR_PULL_SET_MEM_CTX(ndr, r->previous, 0); + NDR_CHECK(ndr_pull_AuthenticationInformationArray_with_count(ndr, NDR_SCALARS|NDR_BUFFERS, r->count, r->previous)); + NDR_PULL_SET_MEM_CTX(ndr, _mem_save_previous_0, 0); + ndr->offset = _relative_save_offset; + } + } + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ void ndr_print_trustAuthInOutBlob(struct ndr_print *ndr, const char *name, const struct trustAuthInOutBlob *r) +{ + ndr_print_struct(ndr, name, "trustAuthInOutBlob"); + ndr->depth++; + ndr_print_uint32(ndr, "count", r->count); + ndr_print_ptr(ndr, "current", r->current); + ndr->depth++; + if (r->current) { + ndr_print_AuthenticationInformationArray_with_count(ndr, "current", r->count, r->current); + } + ndr->depth--; + ndr_print_ptr(ndr, "previous", r->previous); + ndr->depth++; + if (r->previous) { + ndr_print_AuthenticationInformationArray_with_count(ndr, "previous", r->count, r->previous); + } + ndr->depth--; + ndr->depth--; +} + + diff --git a/source4/libcli/drsblobs.h b/source4/libcli/drsblobs.h new file mode 100644 index 0000000000..8fee4114be --- /dev/null +++ b/source4/libcli/drsblobs.h @@ -0,0 +1,28 @@ +/* + Unix SMB/CIFS implementation. + + Manually parsed structures found in the DRS protocol + + 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 + (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/>. +*/ + +#ifndef __LIBCLI_DRSBLOBS_H__ +#define __LIBCLI_DRSBLOBS_H__ + +#include "librpc/gen_ndr/ndr_drsblobs.h" + +#include "libcli/drsblobs_proto.h" +#endif /* __CLDAP_SERVER_PROTO_H__ */ diff --git a/source4/libcli/raw/smb.h b/source4/libcli/raw/smb.h index 8663792f78..d4091acf48 100644 --- a/source4/libcli/raw/smb.h +++ b/source4/libcli/raw/smb.h @@ -167,17 +167,30 @@ #define NTCREATEX_OPTIONS_NO_RECALL 0x00400000 /* Must be ignored by the server, per MS-SMB 2.2.8 */ #define NTCREATEX_OPTIONS_FREE_SPACE_QUERY 0x00800000 -/* create options these bits are for private use by backends, they are - not valid on the wire */ -#define NTCREATEX_OPTIONS_PRIVATE_MASK 0xFF000000 -#define NTCREATEX_OPTIONS_PRIVATE_DENY_DOS 0x01000000 -#define NTCREATEX_OPTIONS_PRIVATE_DENY_FCB 0x02000000 -#define NTCREATEX_OPTIONS_MUST_IGNORE_MASK ( NTCREATEX_OPTIONS_TREE_CONNECTION | NTCREATEX_OPTIONS_COMPLETE_IF_OPLOCKED | NTCREATEX_OPTIONS_OPEN_FOR_RECOVERY | NTCREATEX_OPTIONS_FREE_SPACE_QUERY | NTCREATEX_OPTIONS_OPFILTER ) +#define NTCREATEX_OPTIONS_MUST_IGNORE_MASK (NTCREATEX_OPTIONS_TREE_CONNECTION | \ + NTCREATEX_OPTIONS_OPEN_FOR_RECOVERY | \ + NTCREATEX_OPTIONS_FREE_SPACE_QUERY | \ + 0x000F0000) -#define NTCREATEX_OPTIONS_NOT_SUPPORTED_MASK (0x000F0000 | NTCREATEX_OPTIONS_OPEN_BY_FILE_ID) +#define NTCREATEX_OPTIONS_NOT_SUPPORTED_MASK (NTCREATEX_OPTIONS_OPEN_BY_FILE_ID) +#define NTCREATEX_OPTIONS_INVALID_PARAM_MASK (NTCREATEX_OPTIONS_OPFILTER | \ + NTCREATEX_OPTIONS_SYNC_ALERT | \ + NTCREATEX_OPTIONS_ASYNC_ALERT | \ + NTCREATEX_OPTIONS_OPFILTER | \ + 0xFF000000) +/* + * We reuse some ignored flags for private use. + * This values have different meaning for some ntvfs backends. + * + * TODO: use values that are ignore for sure... + */ +#define NTCREATEX_OPTIONS_PRIVATE_DENY_DOS 0x00010000 +#define NTCREATEX_OPTIONS_PRIVATE_DENY_FCB 0x00020000 +#define NTCREATEX_OPTIONS_PRIVATE_MASK (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS | \ + NTCREATEX_OPTIONS_PRIVATE_DENY_FCB) /* ntcreatex impersonation field */ #define NTCREATEX_IMPERSONATION_ANONYMOUS 0 diff --git a/source4/libcli/security/dom_sid.c b/source4/libcli/security/dom_sid.c index f5457e7e0e..1a7519e362 100644 --- a/source4/libcli/security/dom_sid.c +++ b/source4/libcli/security/dom_sid.c @@ -152,6 +152,21 @@ struct dom_sid *dom_sid_parse_talloc(TALLOC_CTX *mem_ctx, const char *sidstr) } /* + convert a string to a dom_sid, returning a talloc'd dom_sid +*/ +struct dom_sid *dom_sid_parse_length(TALLOC_CTX *mem_ctx, const DATA_BLOB *sid) +{ + struct dom_sid *ret; + char *p = talloc_strndup(mem_ctx, sid->data, sid->length); + if (!p) { + return NULL; + } + ret = dom_sid_parse_talloc(mem_ctx, p); + talloc_free(p); + return ret; +} + +/* copy a dom_sid structure */ struct dom_sid *dom_sid_dup(TALLOC_CTX *mem_ctx, const struct dom_sid *dom_sid) diff --git a/source4/libcli/smb2/connect.c b/source4/libcli/smb2/connect.c index c89c109b72..43151943d3 100644 --- a/source4/libcli/smb2/connect.c +++ b/source4/libcli/smb2/connect.c @@ -115,13 +115,19 @@ static void continue_negprot(struct smb2_request *req) transport->signing_required = false; break; case SMB_SIGNING_SUPPORTED: - case SMB_SIGNING_AUTO: if (transport->negotiate.security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) { transport->signing_required = true; } else { transport->signing_required = false; } break; + case SMB_SIGNING_AUTO: + if (transport->negotiate.security_mode & SMB2_NEGOTIATE_SIGNING_ENABLED) { + transport->signing_required = true; + } else { + transport->signing_required = false; + } + break; case SMB_SIGNING_REQUIRED: if (transport->negotiate.security_mode & SMB2_NEGOTIATE_SIGNING_ENABLED) { transport->signing_required = true; diff --git a/source4/libcli/smb2/signing.c b/source4/libcli/smb2/signing.c index 0d655d1a86..de9e1e9d29 100644 --- a/source4/libcli/smb2/signing.c +++ b/source4/libcli/smb2/signing.c @@ -94,12 +94,6 @@ NTSTATUS smb2_check_signature(struct smb2_request_buffer *buf, DATA_BLOB session return NT_STATUS_OK; } - if (session_key.length == 0) { - DEBUG(2,("Wrong session key length %u for SMB2 signing\n", - (unsigned)session_key.length)); - return NT_STATUS_ACCESS_DENIED; - } - memcpy(sig, buf->hdr+SMB2_HDR_SIGNATURE, 16); memset(buf->hdr + SMB2_HDR_SIGNATURE, 0, 16); diff --git a/source4/libcli/smb2/smb2.h b/source4/libcli/smb2/smb2.h index 5d6341a15b..f00107de60 100644 --- a/source4/libcli/smb2/smb2.h +++ b/source4/libcli/smb2/smb2.h @@ -276,7 +276,9 @@ struct smb2_request { #define SMB2_CREATE_TAG_TWRP "TWrp" #define SMB2_CREATE_TAG_QFID "QFid" - +/* SMB2 Create ignore some more create_options */ +#define SMB2_CREATE_OPTIONS_NOT_SUPPORTED_MASK (NTCREATEX_OPTIONS_TREE_CONNECTION | \ + NTCREATEX_OPTIONS_OPFILTER) /* check that a body has the expected size diff --git a/source4/libcli/smb2/transport.c b/source4/libcli/smb2/transport.c index d9691bec7c..b946a102c8 100644 --- a/source4/libcli/smb2/transport.c +++ b/source4/libcli/smb2/transport.c @@ -235,6 +235,17 @@ static NTSTATUS smb2_transport_finish_recv(void *private, DATA_BLOB blob) req->in.body_size = req->in.size - (SMB2_HDR_BODY+NBT_HDR_SIZE); req->status = NT_STATUS(IVAL(hdr, SMB2_HDR_STATUS)); + if ((flags & SMB2_HDR_FLAG_ASYNC) && + NT_STATUS_EQUAL(req->status, STATUS_PENDING)) { + req->cancel.can_cancel = true; + req->cancel.pending_id = IVAL(hdr, SMB2_HDR_PID); + for (i=0; i< req->cancel.do_cancel; i++) { + smb2_cancel(req); + } + talloc_free(buffer); + return NT_STATUS_OK; + } + if (req->session && req->session->signing_active) { status = smb2_check_signature(&req->in, req->session->session_key); @@ -244,19 +255,6 @@ static NTSTATUS smb2_transport_finish_recv(void *private, DATA_BLOB blob) return status; } } - - - if (NT_STATUS_EQUAL(req->status, STATUS_PENDING)) { - if (flags & 0x00000002) { - req->cancel.can_cancel = true; - req->cancel.pending_id = IVAL(hdr, SMB2_HDR_PID); - for (i=0; i< req->cancel.do_cancel; i++) { - smb2_cancel(req); - } - } - talloc_free(buffer); - return NT_STATUS_OK; - } buffer_code = SVAL(req->in.body, 0); req->in.body_fixed = (buffer_code & ~1); diff --git a/source4/libnet/libnet_become_dc.c b/source4/libnet/libnet_become_dc.c index 19391e7983..332b041e36 100644 --- a/source4/libnet/libnet_become_dc.c +++ b/source4/libnet/libnet_become_dc.c @@ -2465,26 +2465,33 @@ static WERROR becomeDC_drsuapi_pull_partition_recv(struct libnet_BecomeDC_state 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 { return WERR_BAD_NET_RESP; } + if (!ctr1 && ! ctr6) { + return WERR_BAD_NET_RESP; + } + if (ctr_level == 6) { if (!W_ERROR_IS_OK(ctr6->drs_error)) { return ctr6->drs_error; diff --git a/source4/librpc/config.mk b/source4/librpc/config.mk index d87683dd6f..b68d5e6a69 100644 --- a/source4/librpc/config.mk +++ b/source4/librpc/config.mk @@ -43,7 +43,8 @@ MANPAGES += $(librpcsrcdir)/tools/ndrdump.1 ################################################ # Start SUBSYSTEM NDR_COMPRESSION [SUBSYSTEM::NDR_COMPRESSION] -PUBLIC_DEPENDENCIES = LIBCOMPRESSION LIBSAMBA-ERRORS LIBNDR +PRIVATE_DEPENDENCIES = ZLIB LZXPRESS +PUBLIC_DEPENDENCIES = LIBSAMBA-ERRORS LIBNDR # End SUBSYSTEM NDR_COMPRESSION ################################################ @@ -133,7 +134,7 @@ PUBLIC_DEPENDENCIES = LIBNDR NDR_COMPRESSION NDR_SECURITY NDR_SAMR ASN1_UTIL NDR_DRSUAPI_OBJ_FILES = $(gen_ndrsrcdir)/ndr_drsuapi.o $(ndrsrcdir)/ndr_drsuapi.o [SUBSYSTEM::NDR_DRSBLOBS] -PUBLIC_DEPENDENCIES = LIBNDR NDR_MISC NDR_DRSUAPI +PUBLIC_DEPENDENCIES = LIBNDR NDR_MISC NDR_DRSUAPI LIBCLI_DRSBLOBS NDR_DRSBLOBS_OBJ_FILES = $(gen_ndrsrcdir)/ndr_drsblobs.o diff --git a/source4/librpc/idl/dcerpc.idl b/source4/librpc/idl/dcerpc.idl index e54bc2c29f..1c6574b11b 100644 --- a/source4/librpc/idl/dcerpc.idl +++ b/source4/librpc/idl/dcerpc.idl @@ -30,7 +30,6 @@ interface dcerpc } dcerpc_bind; const uint8 DCERPC_REQUEST_LENGTH = 24; - const uint8 DCERPC_MAX_SIGN_SIZE = 64; typedef struct { } dcerpc_empty; @@ -154,6 +153,8 @@ interface dcerpc [flag(NDR_REMAINING)] DATA_BLOB credentials; } dcerpc_auth; + const uint8 DCERPC_AUTH_TRAILER_LENGTH = 8; + typedef [public] struct { uint32 _pad; [flag(NDR_REMAINING)] DATA_BLOB auth_info; diff --git a/source4/librpc/idl/drsblobs.idl b/source4/librpc/idl/drsblobs.idl index b0cddfcdf9..eb85989eda 100644 --- a/source4/librpc/idl/drsblobs.idl +++ b/source4/librpc/idl/drsblobs.idl @@ -401,7 +401,7 @@ interface drsblobs { [case(TRUST_AUTH_TYPE_VERSION)] AuthInfoVersion version; } AuthInfo; - typedef struct { + typedef [public] struct { NTTIME LastUpdateTime; trustAuthType AuthType; @@ -422,32 +422,15 @@ interface drsblobs { [flag(NDR_ALIGN4)] DATA_BLOB _pad; } AuthenticationInformation; - typedef struct { - AuthenticationInformation info[1]; - } AuthenticationInformation1; - - typedef struct { - AuthenticationInformation info[2]; - } AuthenticationInformation2; - - typedef struct { - [relative] AuthenticationInformation1 *current; - [relative] AuthenticationInformation1 *previous; - } AuthenticationInformationCtr1; - - typedef struct { - [relative] AuthenticationInformation2 *current; - [relative] AuthenticationInformation2 *previous; - } AuthenticationInformationCtr2; + typedef [nopull,nopush,noprint] struct { + /* sizeis here is bogus, but this is here just for the structure */ + [size_is(1)] AuthenticationInformation array[]; + } AuthenticationInformationArray; - typedef [nodiscriminant] union { - [case(1)] AuthenticationInformationCtr1 info1; - [case(2)] AuthenticationInformationCtr2 info2; - } AuthenticationInformationCtr; - - typedef [public] struct { + typedef [public,nopull,nopush,noprint] struct { uint32 count; - [switch_is(count)] AuthenticationInformationCtr auth; + [relative] AuthenticationInformationArray *current; + [relative] AuthenticationInformationArray *previous; } trustAuthInOutBlob; void decode_trustAuthInOut( diff --git a/source4/librpc/idl/drsuapi.idl b/source4/librpc/idl/drsuapi.idl index 88d2126d0b..cc76599be6 100644 --- a/source4/librpc/idl/drsuapi.idl +++ b/source4/librpc/idl/drsuapi.idl @@ -617,36 +617,44 @@ interface drsuapi WERROR drs_error; } drsuapi_DsGetNCChangesCtr6; - typedef struct { + typedef [public] struct { + [subcontext(0xFFFFFC01)] drsuapi_DsGetNCChangesCtr1 ctr1; + } drsuapi_DsGetNCChangesCtr1TS; + + typedef [public] struct { + [subcontext(0xFFFFFC01)] drsuapi_DsGetNCChangesCtr6 ctr6; + } drsuapi_DsGetNCChangesCtr6TS; + + typedef [nopush] struct { uint32 decompressed_length; uint32 compressed_length; [subcontext(4),subcontext_size(compressed_length), compression(NDR_COMPRESSION_MSZIP,compressed_length,decompressed_length)] - drsuapi_DsGetNCChangesCtr1 *ctr1; + drsuapi_DsGetNCChangesCtr1TS *ts; } drsuapi_DsGetNCChangesMSZIPCtr1; - typedef struct { + typedef [nopush] struct { uint32 decompressed_length; uint32 compressed_length; [subcontext(4),subcontext_size(compressed_length), compression(NDR_COMPRESSION_MSZIP,compressed_length,decompressed_length)] - drsuapi_DsGetNCChangesCtr6 *ctr6; + drsuapi_DsGetNCChangesCtr6TS *ts; } drsuapi_DsGetNCChangesMSZIPCtr6; - typedef struct { + typedef [nopush] struct { uint32 decompressed_length; uint32 compressed_length; [subcontext(4),subcontext_size(compressed_length), compression(NDR_COMPRESSION_XPRESS,compressed_length,decompressed_length)] - drsuapi_DsGetNCChangesCtr1 *ctr1; + drsuapi_DsGetNCChangesCtr1TS *ts; } drsuapi_DsGetNCChangesXPRESSCtr1; - typedef struct { + typedef [nopush] struct { uint32 decompressed_length; uint32 compressed_length; [subcontext(4),subcontext_size(compressed_length), compression(NDR_COMPRESSION_XPRESS,compressed_length,decompressed_length)] - drsuapi_DsGetNCChangesCtr6 *ctr6; + drsuapi_DsGetNCChangesCtr6TS *ts; } drsuapi_DsGetNCChangesXPRESSCtr6; typedef [enum16bit] enum { diff --git a/source4/librpc/idl/krb5pac.idl b/source4/librpc/idl/krb5pac.idl index 3505fc895c..ca0efaed3e 100644 --- a/source4/librpc/idl/krb5pac.idl +++ b/source4/librpc/idl/krb5pac.idl @@ -45,10 +45,6 @@ interface krb5pac } PAC_UNKNOWN_12; typedef [public] struct { - [value(0x00081001)] uint32 unknown1; - [value(0xCCCCCCCC)] uint32 unknown2; - [value(NDR_ROUND(ndr_size_PAC_LOGON_INFO(info, ndr->flags)+4,8))] uint32 _ndr_size; - [value(0x00000000)] uint32 unknown3; PAC_LOGON_INFO *info; } PAC_LOGON_INFO_CTR; @@ -66,11 +62,15 @@ interface krb5pac } DATA_BLOB_REM; typedef [public,nodiscriminant,gensize] union { - [case(PAC_TYPE_LOGON_INFO)] PAC_LOGON_INFO_CTR logon_info; + [case(PAC_TYPE_LOGON_INFO)][subcontext(0xFFFFFC01)] PAC_LOGON_INFO_CTR logon_info; [case(PAC_TYPE_SRV_CHECKSUM)] PAC_SIGNATURE_DATA srv_cksum; [case(PAC_TYPE_KDC_CHECKSUM)] PAC_SIGNATURE_DATA kdc_cksum; [case(PAC_TYPE_LOGON_NAME)] PAC_LOGON_NAME logon_name; - [case(PAC_TYPE_UNKNOWN_12)] [subcontext(0)] DATA_BLOB_REM unknown; + /* when new PAC info types are added they are supposed to be done + in such a way that they are backwards compatible with existing + servers. This makes it safe to just use a [default] for + unknown types, which lets us ignore the data */ + [default] [subcontext(0)] DATA_BLOB_REM unknown; /* [case(PAC_TYPE_UNKNOWN_12)] PAC_UNKNOWN_12 unknown; */ } PAC_INFO; diff --git a/source4/librpc/idl/lsa.idl b/source4/librpc/idl/lsa.idl index 93cfdee201..408956b3fa 100644 --- a/source4/librpc/idl/lsa.idl +++ b/source4/librpc/idl/lsa.idl @@ -14,6 +14,7 @@ import "misc.idl", "security.idl"; ] interface lsarpc { typedef bitmap security_secinfo security_secinfo; + typedef bitmap kerb_EncTypes kerb_EncTypes; typedef [public,noejs] struct { [value(2*strlen_m(string))] uint16 length; @@ -507,22 +508,53 @@ import "misc.idl", "security.idl"; } lsa_DATA_BUF2; typedef enum { - LSA_TRUSTED_DOMAIN_INFO_NAME = 1, - LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS_INFO = 2, - LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET = 3, - LSA_TRUSTED_DOMAIN_INFO_PASSWORD = 4, - LSA_TRUSTED_DOMAIN_INFO_BASIC = 5, - LSA_TRUSTED_DOMAIN_INFO_INFO_EX = 6, - LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO = 7, - LSA_TRUSTED_DOMAIN_INFO_FULL_INFO = 8, - LSA_TRUSTED_DOMAIN_INFO_11 = 11, - LSA_TRUSTED_DOMAIN_INFO_INFO_ALL = 12 + LSA_TRUSTED_DOMAIN_INFO_NAME = 1, + LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS = 2, + LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET = 3, + LSA_TRUSTED_DOMAIN_INFO_PASSWORD = 4, + LSA_TRUSTED_DOMAIN_INFO_BASIC = 5, + LSA_TRUSTED_DOMAIN_INFO_INFO_EX = 6, + LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO = 7, + LSA_TRUSTED_DOMAIN_INFO_FULL_INFO = 8, + LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL = 9, + LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL = 10, + LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL = 11, + LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL = 12, + LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRTYPION_TYPES = 13 } lsa_TrustDomInfoEnum; + typedef [public,bitmap32bit] bitmap { + LSA_TRUST_DIRECTION_INBOUND = 0x00000001, + LSA_TRUST_DIRECTION_OUTBOUND = 0x00000002 + } lsa_TrustDirection; + + typedef [v1_enum] enum { + LSA_TRUST_TYPE_DOWNLEVEL = 0x00000001, + LSA_TRUST_TYPE_UPLEVEL = 0x00000002, + LSA_TRUST_TYPE_MIT = 0x00000003 + } lsa_TrustType; + + typedef [public,bitmap32bit] bitmap { + LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE = 0x00000001, + LSA_TRUST_ATTRIBUTE_UPLEVEL_ONLY = 0x00000002, + LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN = 0x00000004, + LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE = 0x00000008, + LSA_TRUST_ATTRIBUTE_CROSS_ORGANIZATION = 0x00000010, + LSA_TRUST_ATTRIBUTE_WITHIN_FOREST = 0x00000020, + LSA_TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL = 0x00000040, + LSA_TRUST_ATTRIBUTE_USES_RC4_ENCRYPTION = 0x00000080 + } lsa_TrustAttributes; + typedef struct { lsa_StringLarge netbios_name; } lsa_TrustDomainInfoName; + + typedef struct { + uint32 entries; + [size_is(entries)] lsa_StringLarge *netbios_names; + } lsa_TrustDomainInfoControllers; + typedef struct { uint32 posix_offset; } lsa_TrustDomainInfoPosixOffset; @@ -540,10 +572,10 @@ import "misc.idl", "security.idl"; typedef struct { lsa_StringLarge domain_name; lsa_StringLarge netbios_name; - dom_sid2 *sid; - uint32 trust_direction; - uint32 trust_type; - uint32 trust_attributes; + dom_sid2 *sid; + lsa_TrustDirection trust_direction; + lsa_TrustType trust_type; + lsa_TrustAttributes trust_attributes; } lsa_TrustDomainInfoInfoEx; typedef struct { @@ -570,25 +602,46 @@ import "misc.idl", "security.idl"; typedef struct { lsa_TrustDomainInfoInfoEx info_ex; lsa_DATA_BUF2 data1; - } lsa_TrustDomainInfo11; + } lsa_TrustDomainInfoInfoEx2Internal; typedef struct { lsa_TrustDomainInfoInfoEx info_ex; lsa_DATA_BUF2 data1; lsa_TrustDomainInfoPosixOffset posix_offset; lsa_TrustDomainInfoAuthInfo auth_info; - } lsa_TrustDomainInfoInfoAll; + } lsa_TrustDomainInfoInfo2Internal; + + typedef struct { + kerb_EncTypes enc_types; + } lsa_TrustDomainInfoSupportedEncTypes; typedef [switch_type(lsa_TrustDomInfoEnum)] union { - [case(LSA_TRUSTED_DOMAIN_INFO_NAME)] lsa_TrustDomainInfoName name; - [case(LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET)] lsa_TrustDomainInfoPosixOffset posix_offset; - [case(LSA_TRUSTED_DOMAIN_INFO_PASSWORD)] lsa_TrustDomainInfoPassword password; - [case(LSA_TRUSTED_DOMAIN_INFO_BASIC)] lsa_TrustDomainInfoBasic info_basic; - [case(LSA_TRUSTED_DOMAIN_INFO_INFO_EX)] lsa_TrustDomainInfoInfoEx info_ex; - [case(LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO)] lsa_TrustDomainInfoAuthInfo auth_info; - [case(LSA_TRUSTED_DOMAIN_INFO_FULL_INFO)] lsa_TrustDomainInfoFullInfo full_info; - [case(LSA_TRUSTED_DOMAIN_INFO_11)] lsa_TrustDomainInfo11 info11; - [case(LSA_TRUSTED_DOMAIN_INFO_INFO_ALL)] lsa_TrustDomainInfoInfoAll info_all; + [case(LSA_TRUSTED_DOMAIN_INFO_NAME)] + lsa_TrustDomainInfoName name; + [case(LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS)] + lsa_TrustDomainInfoControllers controllers; + [case(LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET)] + lsa_TrustDomainInfoPosixOffset posix_offset; + [case(LSA_TRUSTED_DOMAIN_INFO_PASSWORD)] + lsa_TrustDomainInfoPassword password; + [case(LSA_TRUSTED_DOMAIN_INFO_BASIC)] + lsa_TrustDomainInfoBasic info_basic; + [case(LSA_TRUSTED_DOMAIN_INFO_INFO_EX)] + lsa_TrustDomainInfoInfoEx info_ex; + [case(LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO)] + lsa_TrustDomainInfoAuthInfo auth_info; + [case(LSA_TRUSTED_DOMAIN_INFO_FULL_INFO)] + lsa_TrustDomainInfoFullInfo full_info; + [case(LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL)] + lsa_TrustDomainInfoAuthInfo auth_info_internal; + [case(LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL)] + lsa_TrustDomainInfoFullInfo full_info_internal; + [case(LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL)] + lsa_TrustDomainInfoInfoEx2Internal info_ex2_internal; + [case(LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL)] + lsa_TrustDomainInfoInfo2Internal info2_internal; + [case(LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRTYPION_TYPES)] + lsa_TrustDomainInfoSupportedEncTypes enc_types; } lsa_TrustedDomainInfo; /* Function: 0x1a */ @@ -658,8 +711,12 @@ import "misc.idl", "security.idl"; [in] uint16 unknown ); - /* Function: 0x22 */ - [todo] NTSTATUS lsa_DeleteObject(); + /*******************/ + /* Function: 0x22 */ + NTSTATUS lsa_DeleteObject ( + [in,out] policy_handle *handle + ); + /*******************/ diff --git a/source4/librpc/idl/nbt.idl b/source4/librpc/idl/nbt.idl index a6d0245455..63be489e0d 100644 --- a/source4/librpc/idl/nbt.idl +++ b/source4/librpc/idl/nbt.idl @@ -353,7 +353,13 @@ interface nbt NBT_SERVER_TIMESERV = 0x00000040, NBT_SERVER_CLOSEST = 0x00000080, NBT_SERVER_WRITABLE = 0x00000100, - NBT_SERVER_GOOD_TIMESERV = 0x00000200 + NBT_SERVER_GOOD_TIMESERV = 0x00000200, + NBT_SERVER_NDNC = 0x00000400, + NBT_SERVER_SEL_SEC_DOM_6 = 0x00000800, + NBT_SERVER_FUL_SEC_DOM_6 = 0x00001000, + NBT_SERVER_DS_DNS_CONTR = 0x04000000, + NBT_SERVER_DS_DNS_DOMAIN = 0x02000000, + NBT_SERVER_DS_DNS_FOREST = 0x01000000 } nbt_server_type; typedef [bitmap32bit,public] bitmap { diff --git a/source4/librpc/idl/security.idl b/source4/librpc/idl/security.idl index f8e9e9e110..80efe46453 100644 --- a/source4/librpc/idl/security.idl +++ b/source4/librpc/idl/security.idl @@ -386,4 +386,12 @@ interface security SECINFO_PROTECTED_SACL = 0x40000000, SECINFO_PROTECTED_DACL = 0x80000000 } security_secinfo; + + typedef [public,bitmap32bit] bitmap { + KERB_ENCTYPE_DES_CBC_CRC = 0x00000001, + KERB_ENCTYPE_DES_CBC_MD5 = 0x00000002, + KERB_ENCTYPE_RC4_HMAC_MD5 = 0x00000004, + KERB_ENCTYPE_AES128_CTS_HMAC_SHA1_96 = 0x00000008, + KERB_ENCTYPE_AES256_CTS_HMAC_SHA1_96 = 0x00000010 + } kerb_EncTypes; } diff --git a/source4/librpc/ndr/ndr.c b/source4/librpc/ndr/ndr.c index 40852456bc..c5e4c44794 100644 --- a/source4/librpc/ndr/ndr.c +++ b/source4/librpc/ndr/ndr.c @@ -394,6 +394,8 @@ _PUBLIC_ enum ndr_err_code ndr_pull_subcontext_start(struct ndr_pull *ndr, { struct ndr_pull *subndr; uint32_t r_content_size; + bool force_le = false; + bool force_be = false; switch (header_size) { case 0: { @@ -426,6 +428,74 @@ _PUBLIC_ enum ndr_err_code ndr_pull_subcontext_start(struct ndr_pull *ndr, r_content_size = content_size; break; } + case 0xFFFFFC01: { + /* + * Common Type Header for the Serialization Stream + * See [MS-RPCE] 2.2.6 Type Serialization Version 1 + */ + uint8_t version; + uint8_t drep; + uint16_t hdrlen; + uint32_t filler; + uint32_t content_size; + uint32_t reserved; + + /* version */ + NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &version)); + + if (version != 1) { + return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, + "Bad subcontext (PULL) Common Type Header version %d != 1", + (int)version); + } + + /* + * 0x10 little endian + * 0x00 big endian + */ + NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &drep)); + if (drep == 0x10) { + force_le = true; + } else if (drep == 0x00) { + force_be = true; + } else { + return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, + "Bad subcontext (PULL) Common Type Header invalid drep 0x%02X", + (unsigned int)drep); + } + + /* length of the "Private Header for Constructed Type" */ + NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &hdrlen)); + if (hdrlen != 8) { + return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, + "Bad subcontext (PULL) Common Type Header length %d != 8", + (int)hdrlen); + } + + /* filler should be ignored */ + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &filler)); + + /* + * Private Header for Constructed Type + */ + /* length - will be updated latter */ + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &content_size)); + if (size_is >= 0 && size_is != content_size) { + return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) size_is(%d) mismatch content_size %d", + (int)size_is, (int)content_size); + } + /* the content size must be a multiple of 8 */ + if ((content_size % 8) != 0) { + return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, + "Bad subcontext (PULL) size_is(%d) not padded to 8 content_size %d", + (int)size_is, (int)content_size); + } + r_content_size = content_size; + + /* reserved */ + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &reserved)); + break; + } default: return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) header_size %d", (int)header_size); @@ -443,6 +513,12 @@ _PUBLIC_ enum ndr_err_code ndr_pull_subcontext_start(struct ndr_pull *ndr, subndr->data_size = r_content_size; subndr->iconv_convenience = talloc_reference(subndr, ndr->iconv_convenience); + if (force_le) { + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_LITTLE_ENDIAN); + } else if (force_be) { + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_BIGENDIAN); + } + *_subndr = subndr; return NDR_ERR_SUCCESS; } @@ -487,8 +563,10 @@ _PUBLIC_ enum ndr_err_code ndr_push_subcontext_end(struct ndr_push *ndr, size_t header_size, ssize_t size_is) { + ssize_t padding_len; + if (size_is >= 0) { - ssize_t padding_len = size_is - subndr->offset; + padding_len = size_is - subndr->offset; if (padding_len > 0) { NDR_CHECK(ndr_push_zero(subndr, padding_len)); } else if (padding_len < 0) { @@ -509,6 +587,41 @@ _PUBLIC_ enum ndr_err_code ndr_push_subcontext_end(struct ndr_push *ndr, NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, subndr->offset)); break; + case 0xFFFFFC01: + /* + * Common Type Header for the Serialization Stream + * See [MS-RPCE] 2.2.6 Type Serialization Version 1 + */ + padding_len = NDR_ROUND(subndr->offset, 8) - subndr->offset; + if (padding_len > 0) { + NDR_CHECK(ndr_push_zero(subndr, padding_len)); + } + + /* version */ + NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, 1)); + + /* + * 0x10 little endian + * 0x00 big endian + */ + NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, NDR_BE(ndr)?0x00:0x10)); + + /* length of the "Private Header for Constructed Type" */ + NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, 8)); + + /* filler */ + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0xCCCCCCCC)); + + /* + * Private Header for Constructed Type + */ + /* length - will be updated latter */ + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, subndr->offset)); + + /* reserved */ + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0)); + break; + default: return ndr_push_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext header size %d", (int)header_size); diff --git a/source4/librpc/ndr/ndr_compression.c b/source4/librpc/ndr/ndr_compression.c index 86a5a2560e..37f95bb1b6 100644 --- a/source4/librpc/ndr/ndr_compression.c +++ b/source4/librpc/ndr/ndr_compression.c @@ -4,6 +4,7 @@ libndr compression support Copyright (C) Stefan Metzmacher 2005 + Copyright (C) Matthieu Suiche 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 @@ -20,13 +21,24 @@ */ #include "includes.h" -#include "lib/compression/mszip.h" +#include "lib/compression/lzxpress.h" #include "librpc/ndr/libndr.h" #include "librpc/ndr/ndr_compression.h" +#include <zlib.h> + +static voidpf ndr_zlib_alloc(voidpf opaque, uInt items, uInt size) +{ + return talloc_zero_size(opaque, items * size); +} + +static void ndr_zlib_free(voidpf opaque, voidpf address) +{ + talloc_free(address); +} static enum ndr_err_code ndr_pull_compression_mszip_chunk(struct ndr_pull *ndrpull, struct ndr_push *ndrpush, - struct decomp_state *decomp_state, + z_stream *z, bool *last) { DATA_BLOB comp_chunk; @@ -35,7 +47,7 @@ static enum ndr_err_code ndr_pull_compression_mszip_chunk(struct ndr_pull *ndrpu DATA_BLOB plain_chunk; uint32_t plain_chunk_offset; uint32_t plain_chunk_size; - int ret; + int z_ret; NDR_CHECK(ndr_pull_uint32(ndrpull, NDR_SCALARS, &plain_chunk_size)); if (plain_chunk_size > 0x00008000) { @@ -58,10 +70,71 @@ static enum ndr_err_code ndr_pull_compression_mszip_chunk(struct ndr_pull *ndrpu plain_chunk.length = plain_chunk_size; plain_chunk.data = ndrpush->data + plain_chunk_offset; - ret = ZIPdecompress(decomp_state, &comp_chunk, &plain_chunk); - if (ret != DECR_OK) { - return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION, "Bad ZIPdecompress() error %d (PULL)", - ret); + if (comp_chunk.length < 2) { + return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION, + "Bad MSZIP comp chunk size %u < 2 (PULL)", + (unsigned int)comp_chunk.length); + } + /* CK = Chris Kirmse, official Microsoft purloiner */ + if (comp_chunk.data[0] != 'C' || + comp_chunk.data[1] != 'K') { + return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION, + "Bad MSZIP invalid prefix [%c%c] != [CK]", + comp_chunk.data[0], comp_chunk.data[1]); + } + + z->next_in = comp_chunk.data + 2; + z->avail_in = comp_chunk.length -2; + z->total_in = 0; + + z->next_out = plain_chunk.data; + z->avail_out = plain_chunk.length; + z->total_out = 0; + + if (!z->opaque) { + /* the first time we need to intialize completely */ + z->zalloc = ndr_zlib_alloc; + z->zfree = ndr_zlib_free; + z->opaque = ndrpull; + + z_ret = inflateInit2(z, -15); + if (z_ret != Z_OK) { + return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION, + "Bad inflateInit2 error %s(%d) (PULL)", + zError(z_ret), z_ret); + + } + } else { + z_ret = inflateReset2(z, Z_RESET_KEEP_WINDOW); + if (z_ret != Z_OK) { + return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION, + "Bad inflateReset2 error %s(%d) (PULL)", + zError(z_ret), z_ret); + } + } + + /* call inflate untill we get Z_STREAM_END or an error */ + while (true) { + z_ret = inflate(z, Z_BLOCK); + if (z_ret != Z_OK) break; + } + + if (z_ret != Z_STREAM_END) { + return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION, + "Bad inflate(Z_BLOCK) error %s(%d) (PULL)", + zError(z_ret), z_ret); + } + + if (z->avail_in) { + return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION, + "MSZIP not all avail_in[%u] bytes consumed (PULL)", + z->avail_in); + } + + if (z->avail_out) { + return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION, + "MSZIP not all avail_out[%u] bytes consumed (PULL)", + z->avail_out); } if ((plain_chunk_size < 0x00008000) || (ndrpull->offset+4 >= ndrpull->data_size)) { @@ -72,98 +145,122 @@ static enum ndr_err_code ndr_pull_compression_mszip_chunk(struct ndr_pull *ndrpu return NDR_ERR_SUCCESS; } -static enum ndr_err_code ndr_pull_compression_mszip(struct ndr_pull *subndr, - struct ndr_pull **_comndr, - ssize_t decompressed_len) +static enum ndr_err_code ndr_push_compression_mszip_chunk(struct ndr_push *ndrpush, + struct ndr_pull *ndrpull, + z_stream *z, + bool *last) { - struct ndr_push *ndrpush; - struct ndr_pull *comndr; - DATA_BLOB uncompressed; - uint32_t payload_header[4]; - uint32_t payload_size; - uint32_t payload_offset; - uint8_t *payload; - struct decomp_state *decomp_state; - bool last = false; + DATA_BLOB comp_chunk; + uint32_t comp_chunk_size; + uint32_t comp_chunk_size_offset; + DATA_BLOB plain_chunk; + uint32_t plain_chunk_size; + uint32_t plain_chunk_offset; + uint32_t max_plain_size = 0x00008000; + uint32_t max_comp_size = 0x00008000 + 2 + 12 /*TODO: what value do we really need here?*/; + uint32_t tmp_offset; + int z_ret; - ndrpush = ndr_push_init_ctx(subndr, subndr->iconv_convenience); - NDR_ERR_HAVE_NO_MEMORY(ndrpush); + plain_chunk_size = MIN(max_plain_size, ndrpull->data_size - ndrpull->offset); + plain_chunk_offset = ndrpull->offset; + NDR_CHECK(ndr_pull_advance(ndrpull, plain_chunk_size)); - decomp_state = ZIPdecomp_state(subndr); - NDR_ERR_HAVE_NO_MEMORY(decomp_state); + plain_chunk.data = ndrpull->data + plain_chunk_offset; + plain_chunk.length = plain_chunk_size; - while (!last) { - NDR_CHECK(ndr_pull_compression_mszip_chunk(subndr, ndrpush, decomp_state, &last)); + if (plain_chunk_size < max_plain_size) { + *last = true; } - uncompressed = ndr_push_blob(ndrpush); - - if (uncompressed.length != decompressed_len) { - return ndr_pull_error(subndr, NDR_ERR_COMPRESSION, "Bad MSZIP uncompressed_len [%u] != [%d] (PULL)", - (int)uncompressed.length, (int)decompressed_len); + NDR_CHECK(ndr_push_uint32(ndrpush, NDR_SCALARS, plain_chunk_size)); + comp_chunk_size_offset = ndrpush->offset; + NDR_CHECK(ndr_push_uint32(ndrpush, NDR_SCALARS, 0xFEFEFEFE)); + + NDR_CHECK(ndr_push_expand(ndrpush, max_comp_size)); + + comp_chunk.data = ndrpush->data + ndrpush->offset; + comp_chunk.length = max_comp_size; + + /* CK = Chris Kirmse, official Microsoft purloiner */ + comp_chunk.data[0] = 'C'; + comp_chunk.data[1] = 'K'; + + z->next_in = plain_chunk.data; + z->avail_in = plain_chunk.length; + z->total_in = 0; + + z->next_out = comp_chunk.data + 2; + z->avail_out = comp_chunk.length - 2; + z->total_out = 0; + + if (!z->opaque) { + /* the first time we need to intialize completely */ + z->zalloc = ndr_zlib_alloc; + z->zfree = ndr_zlib_free; + z->opaque = ndrpull; + + /* TODO: find how to trigger the same parameters windows uses */ + z_ret = deflateInit2(z, + Z_DEFAULT_COMPRESSION, + Z_DEFLATED, + -15, + 9, + Z_DEFAULT_STRATEGY); + if (z_ret != Z_OK) { + return ndr_push_error(ndrpush, NDR_ERR_COMPRESSION, + "Bad deflateInit2 error %s(%d) (PUSH)", + zError(z_ret), z_ret); + + } + } else { + /* TODO: keep the window */ + z_ret = deflateReset(z); + if (z_ret != Z_OK) { + return ndr_push_error(ndrpush, NDR_ERR_COMPRESSION, + "Bad delateReset2 error %s(%d) (PUSH)", + zError(z_ret), z_ret); + } } - comndr = talloc_zero(subndr, struct ndr_pull); - NDR_ERR_HAVE_NO_MEMORY(comndr); - comndr->flags = subndr->flags; - comndr->current_mem_ctx = subndr->current_mem_ctx; - - comndr->data = uncompressed.data; - comndr->data_size = uncompressed.length; - comndr->offset = 0; - - comndr->iconv_convenience = talloc_reference(comndr, subndr->iconv_convenience); - - NDR_CHECK(ndr_pull_uint32(comndr, NDR_SCALARS, &payload_header[0])); - NDR_CHECK(ndr_pull_uint32(comndr, NDR_SCALARS, &payload_header[1])); - NDR_CHECK(ndr_pull_uint32(comndr, NDR_SCALARS, &payload_header[2])); - NDR_CHECK(ndr_pull_uint32(comndr, NDR_SCALARS, &payload_header[3])); - - if (payload_header[0] != 0x00081001) { - return ndr_pull_error(subndr, NDR_ERR_COMPRESSION, "Bad MSZIP payload_header[0] [0x%08X] != [0x00081001] (PULL)", - payload_header[0]); + /* call deflate untill we get Z_STREAM_END or an error */ + while (true) { + z_ret = deflate(z, Z_FINISH); + if (z_ret != Z_OK) break; } - if (payload_header[1] != 0xCCCCCCCC) { - return ndr_pull_error(subndr, NDR_ERR_COMPRESSION, "Bad MSZIP payload_header[1] [0x%08X] != [0xCCCCCCCC] (PULL)", - payload_header[1]); + if (z_ret != Z_STREAM_END) { + return ndr_push_error(ndrpush, NDR_ERR_COMPRESSION, + "Bad delate(Z_BLOCK) error %s(%d) (PUSH)", + zError(z_ret), z_ret); } - payload_size = payload_header[2]; - - if (payload_header[3] != 0x00000000) { - return ndr_pull_error(subndr, NDR_ERR_COMPRESSION, "Bad MSZIP payload_header[3] [0x%08X] != [0x00000000] (PULL)", - payload_header[3]); + if (z->avail_in) { + return ndr_push_error(ndrpush, NDR_ERR_COMPRESSION, + "MSZIP not all avail_in[%u] bytes consumed (PUSH)", + z->avail_in); } - payload_offset = comndr->offset; - NDR_CHECK(ndr_pull_advance(comndr, payload_size)); - payload = comndr->data + payload_offset; + comp_chunk_size = 2 + z->total_out; - comndr->data = payload; - comndr->data_size = payload_size; - comndr->offset = 0; + tmp_offset = ndrpush->offset; + ndrpush->offset = comp_chunk_size_offset; + NDR_CHECK(ndr_push_uint32(ndrpush, NDR_SCALARS, comp_chunk_size)); + ndrpush->offset = tmp_offset; - *_comndr = comndr; + ndrpush->offset += comp_chunk_size; return NDR_ERR_SUCCESS; } -static enum ndr_err_code ndr_push_compression_mszip(struct ndr_push *subndr, - struct ndr_push *comndr) -{ - return ndr_push_error(subndr, NDR_ERR_COMPRESSION, "Sorry MSZIP compression is not supported yet (PUSH)"); -} - static enum ndr_err_code ndr_pull_compression_xpress_chunk(struct ndr_pull *ndrpull, struct ndr_push *ndrpush, bool *last) { DATA_BLOB comp_chunk; + DATA_BLOB plain_chunk; uint32_t comp_chunk_offset; + uint32_t plain_chunk_offset; uint32_t comp_chunk_size; uint32_t plain_chunk_size; - comp_chunk_offset = ndrpull->offset; - NDR_CHECK(ndr_pull_uint32(ndrpull, NDR_SCALARS, &plain_chunk_size)); if (plain_chunk_size > 0x00010000) { return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION, "Bad XPRESS plain chunk size %08X > 0x00010000 (PULL)", @@ -172,15 +269,21 @@ static enum ndr_err_code ndr_pull_compression_xpress_chunk(struct ndr_pull *ndrp NDR_CHECK(ndr_pull_uint32(ndrpull, NDR_SCALARS, &comp_chunk_size)); + comp_chunk_offset = ndrpull->offset; NDR_CHECK(ndr_pull_advance(ndrpull, comp_chunk_size)); - comp_chunk.length = comp_chunk_size + 8; + comp_chunk.length = comp_chunk_size; comp_chunk.data = ndrpull->data + comp_chunk_offset; + plain_chunk_offset = ndrpush->offset; + NDR_CHECK(ndr_push_zero(ndrpush, plain_chunk_size)); + plain_chunk.length = plain_chunk_size; + plain_chunk.data = ndrpush->data + plain_chunk_offset; + DEBUG(10,("XPRESS plain_chunk_size: %08X (%u) comp_chunk_size: %08X (%u)\n", plain_chunk_size, plain_chunk_size, comp_chunk_size, comp_chunk_size)); - /* For now, we just copy over the compressed blob */ - NDR_CHECK(ndr_push_bytes(ndrpush, comp_chunk.data, comp_chunk.length)); + /* Uncompressing the buffer using LZ Xpress algorithm */ + lzxpress_decompress(&comp_chunk, &plain_chunk); if ((plain_chunk_size < 0x00010000) || (ndrpull->offset+4 >= ndrpull->data_size)) { /* this is the last chunk */ @@ -190,23 +293,58 @@ static enum ndr_err_code ndr_pull_compression_xpress_chunk(struct ndr_pull *ndrp return NDR_ERR_SUCCESS; } -static enum ndr_err_code ndr_pull_compression_xpress(struct ndr_pull *subndr, - struct ndr_pull **_comndr, - ssize_t decompressed_len) +static enum ndr_err_code ndr_push_compression_xpress_chunk(struct ndr_push *ndrpush, + struct ndr_pull *ndrpull, + bool *last) +{ + return ndr_push_error(ndrpush, NDR_ERR_COMPRESSION, "XPRESS compression is not supported yet (PUSH)"); +} + +/* + handle compressed subcontext buffers, which in midl land are user-marshalled, but + we use magic in pidl to make them easier to cope with +*/ +enum ndr_err_code ndr_pull_compression_start(struct ndr_pull *subndr, + struct ndr_pull **_comndr, + enum ndr_compression_alg compression_alg, + ssize_t decompressed_len) { struct ndr_push *ndrpush; struct ndr_pull *comndr; DATA_BLOB uncompressed; bool last = false; + z_stream z; ndrpush = ndr_push_init_ctx(subndr, subndr->iconv_convenience); NDR_ERR_HAVE_NO_MEMORY(ndrpush); - while (!last) { - NDR_CHECK(ndr_pull_compression_xpress_chunk(subndr, ndrpush, &last)); + switch (compression_alg) { + case NDR_COMPRESSION_MSZIP: + ZERO_STRUCT(z); + while (!last) { + NDR_CHECK(ndr_pull_compression_mszip_chunk(subndr, ndrpush, &z, &last)); + } + break; + + case NDR_COMPRESSION_XPRESS: + while (!last) { + NDR_CHECK(ndr_pull_compression_xpress_chunk(subndr, ndrpush, &last)); + } + break; + + default: + return ndr_pull_error(subndr, NDR_ERR_COMPRESSION, "Bad compression algorithm %d (PULL)", + compression_alg); } uncompressed = ndr_push_blob(ndrpush); + if (uncompressed.length != decompressed_len) { + return ndr_pull_error(subndr, NDR_ERR_COMPRESSION, + "Bad uncompressed_len [%u] != [%u](0x%08X) (PULL)", + (int)uncompressed.length, + (int)decompressed_len, + (int)decompressed_len); + } comndr = talloc_zero(subndr, struct ndr_pull); NDR_ERR_HAVE_NO_MEMORY(comndr); @@ -223,33 +361,6 @@ static enum ndr_err_code ndr_pull_compression_xpress(struct ndr_pull *subndr, return NDR_ERR_SUCCESS; } -static enum ndr_err_code ndr_push_compression_xpress(struct ndr_push *subndr, - struct ndr_push *comndr) -{ - return ndr_push_error(subndr, NDR_ERR_COMPRESSION, "XPRESS compression is not supported yet (PUSH)"); -} - -/* - handle compressed subcontext buffers, which in midl land are user-marshalled, but - we use magic in pidl to make them easier to cope with -*/ -enum ndr_err_code ndr_pull_compression_start(struct ndr_pull *subndr, - struct ndr_pull **_comndr, - enum ndr_compression_alg compression_alg, - ssize_t decompressed_len) -{ - switch (compression_alg) { - case NDR_COMPRESSION_MSZIP: - return ndr_pull_compression_mszip(subndr, _comndr, decompressed_len); - case NDR_COMPRESSION_XPRESS: - return ndr_pull_compression_xpress(subndr, _comndr, decompressed_len); - default: - return ndr_pull_error(subndr, NDR_ERR_COMPRESSION, "Bad compression algorithm %d (PULL)", - compression_alg); - } - return NDR_ERR_SUCCESS; -} - enum ndr_err_code ndr_pull_compression_end(struct ndr_pull *subndr, struct ndr_pull *comndr, enum ndr_compression_alg compression_alg, @@ -262,17 +373,27 @@ enum ndr_err_code ndr_pull_compression_end(struct ndr_pull *subndr, push a compressed subcontext */ enum ndr_err_code ndr_push_compression_start(struct ndr_push *subndr, - struct ndr_push **_comndr, + struct ndr_push **_uncomndr, enum ndr_compression_alg compression_alg, ssize_t decompressed_len) { - struct ndr_push *comndr; + struct ndr_push *uncomndr; - comndr = ndr_push_init_ctx(subndr, subndr->iconv_convenience); - NDR_ERR_HAVE_NO_MEMORY(comndr); - comndr->flags = subndr->flags; + switch (compression_alg) { + case NDR_COMPRESSION_MSZIP: + case NDR_COMPRESSION_XPRESS: + break; + default: + return ndr_push_error(subndr, NDR_ERR_COMPRESSION, + "Bad compression algorithm %d (PUSH)", + compression_alg); + } - *_comndr = comndr; + uncomndr = ndr_push_init_ctx(subndr, subndr->iconv_convenience); + NDR_ERR_HAVE_NO_MEMORY(uncomndr); + uncomndr->flags = subndr->flags; + + *_uncomndr = uncomndr; return NDR_ERR_SUCCESS; } @@ -280,18 +401,42 @@ enum ndr_err_code ndr_push_compression_start(struct ndr_push *subndr, push a compressed subcontext */ enum ndr_err_code ndr_push_compression_end(struct ndr_push *subndr, - struct ndr_push *comndr, + struct ndr_push *uncomndr, enum ndr_compression_alg compression_alg, ssize_t decompressed_len) { + struct ndr_pull *ndrpull; + bool last = false; + z_stream z; + + ndrpull = talloc_zero(uncomndr, struct ndr_pull); + NDR_ERR_HAVE_NO_MEMORY(ndrpull); + ndrpull->flags = uncomndr->flags; + ndrpull->data = uncomndr->data; + ndrpull->data_size = uncomndr->offset; + ndrpull->offset = 0; + + ndrpull->iconv_convenience = talloc_reference(ndrpull, subndr->iconv_convenience); + switch (compression_alg) { case NDR_COMPRESSION_MSZIP: - return ndr_push_compression_mszip(subndr, comndr); + ZERO_STRUCT(z); + while (!last) { + NDR_CHECK(ndr_push_compression_mszip_chunk(subndr, ndrpull, &z, &last)); + } + break; + case NDR_COMPRESSION_XPRESS: - return ndr_push_compression_xpress(subndr, comndr); + while (!last) { + NDR_CHECK(ndr_push_compression_xpress_chunk(subndr, ndrpull, &last)); + } + break; + default: return ndr_push_error(subndr, NDR_ERR_COMPRESSION, "Bad compression algorithm %d (PUSH)", compression_alg); } + + talloc_free(uncomndr); return NDR_ERR_SUCCESS; } diff --git a/source4/librpc/ndr/ndr_drsuapi.c b/source4/librpc/ndr/ndr_drsuapi.c index 1b6be9ed8e..e77ab54071 100644 --- a/source4/librpc/ndr/ndr_drsuapi.c +++ b/source4/librpc/ndr/ndr_drsuapi.c @@ -24,6 +24,7 @@ #include "librpc/gen_ndr/ndr_drsuapi.h" #include "librpc/gen_ndr/ndr_misc.h" #include "lib/util/asn1.h" +#include "librpc/ndr/ndr_compression.h" void ndr_print_drsuapi_DsReplicaObjectListItem(struct ndr_print *ndr, const char *name, const struct drsuapi_DsReplicaObjectListItem *r) @@ -176,3 +177,175 @@ size_t ndr_size_drsuapi_DsReplicaOID_oid(const char *oid, int flags) data_blob_free(&_blob); return ret; } + +enum ndr_err_code ndr_push_drsuapi_DsGetNCChangesMSZIPCtr1(struct ndr_push *ndr, int ndr_flags, const struct drsuapi_DsGetNCChangesMSZIPCtr1 *r) +{ + if (ndr_flags & NDR_SCALARS) { + uint32_t decompressed_length = 0; + uint32_t compressed_length = 0; + if (r->ts) { + { + struct ndr_push *_ndr_ts; + NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_ts, 4, -1)); + { + struct ndr_push *_ndr_ts_compressed; + NDR_CHECK(ndr_push_compression_start(_ndr_ts, &_ndr_ts_compressed, NDR_COMPRESSION_MSZIP, -1)); + NDR_CHECK(ndr_push_drsuapi_DsGetNCChangesCtr1TS(_ndr_ts_compressed, NDR_SCALARS|NDR_BUFFERS, r->ts)); + decompressed_length = _ndr_ts_compressed->offset; + NDR_CHECK(ndr_push_compression_end(_ndr_ts, _ndr_ts_compressed, NDR_COMPRESSION_MSZIP, -1)); + } + compressed_length = _ndr_ts->offset; + talloc_free(_ndr_ts); + } + } + NDR_CHECK(ndr_push_align(ndr, 4)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, decompressed_length)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, compressed_length)); + NDR_CHECK(ndr_push_unique_ptr(ndr, r->ts)); + } + if (ndr_flags & NDR_BUFFERS) { + if (r->ts) { + { + struct ndr_push *_ndr_ts; + NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_ts, 4, -1)); + { + struct ndr_push *_ndr_ts_compressed; + NDR_CHECK(ndr_push_compression_start(_ndr_ts, &_ndr_ts_compressed, NDR_COMPRESSION_MSZIP, -1)); + NDR_CHECK(ndr_push_drsuapi_DsGetNCChangesCtr1TS(_ndr_ts_compressed, NDR_SCALARS|NDR_BUFFERS, r->ts)); + NDR_CHECK(ndr_push_compression_end(_ndr_ts, _ndr_ts_compressed, NDR_COMPRESSION_MSZIP, -1)); + } + NDR_CHECK(ndr_push_subcontext_end(ndr, _ndr_ts, 4, -1)); + } + } + } + return NDR_ERR_SUCCESS; +} + +enum ndr_err_code ndr_push_drsuapi_DsGetNCChangesMSZIPCtr6(struct ndr_push *ndr, int ndr_flags, const struct drsuapi_DsGetNCChangesMSZIPCtr6 *r) +{ + if (ndr_flags & NDR_SCALARS) { + uint32_t decompressed_length = 0; + uint32_t compressed_length = 0; + if (r->ts) { + { + struct ndr_push *_ndr_ts; + NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_ts, 4, -1)); + { + struct ndr_push *_ndr_ts_compressed; + NDR_CHECK(ndr_push_compression_start(_ndr_ts, &_ndr_ts_compressed, NDR_COMPRESSION_MSZIP, -1)); + NDR_CHECK(ndr_push_drsuapi_DsGetNCChangesCtr6TS(_ndr_ts_compressed, NDR_SCALARS|NDR_BUFFERS, r->ts)); + decompressed_length = _ndr_ts_compressed->offset; + NDR_CHECK(ndr_push_compression_end(_ndr_ts, _ndr_ts_compressed, NDR_COMPRESSION_MSZIP, -1)); + } + compressed_length = _ndr_ts->offset; + talloc_free(_ndr_ts); + } + } + NDR_CHECK(ndr_push_align(ndr, 4)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, decompressed_length)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, compressed_length)); + NDR_CHECK(ndr_push_unique_ptr(ndr, r->ts)); + } + if (ndr_flags & NDR_BUFFERS) { + if (r->ts) { + { + struct ndr_push *_ndr_ts; + NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_ts, 4, -1)); + { + struct ndr_push *_ndr_ts_compressed; + NDR_CHECK(ndr_push_compression_start(_ndr_ts, &_ndr_ts_compressed, NDR_COMPRESSION_MSZIP, -1)); + NDR_CHECK(ndr_push_drsuapi_DsGetNCChangesCtr6TS(_ndr_ts_compressed, NDR_SCALARS|NDR_BUFFERS, r->ts)); + NDR_CHECK(ndr_push_compression_end(_ndr_ts, _ndr_ts_compressed, NDR_COMPRESSION_MSZIP, -1)); + } + NDR_CHECK(ndr_push_subcontext_end(ndr, _ndr_ts, 4, -1)); + } + } + } + return NDR_ERR_SUCCESS; +} + +enum ndr_err_code ndr_push_drsuapi_DsGetNCChangesXPRESSCtr1(struct ndr_push *ndr, int ndr_flags, const struct drsuapi_DsGetNCChangesXPRESSCtr1 *r) +{ + if (ndr_flags & NDR_SCALARS) { + uint32_t decompressed_length = 0; + uint32_t compressed_length = 0; + if (r->ts) { + { + struct ndr_push *_ndr_ts; + NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_ts, 4, -1)); + { + struct ndr_push *_ndr_ts_compressed; + NDR_CHECK(ndr_push_compression_start(_ndr_ts, &_ndr_ts_compressed, NDR_COMPRESSION_XPRESS, -1)); + NDR_CHECK(ndr_push_drsuapi_DsGetNCChangesCtr1TS(_ndr_ts_compressed, NDR_SCALARS|NDR_BUFFERS, r->ts)); + decompressed_length = _ndr_ts_compressed->offset; + NDR_CHECK(ndr_push_compression_end(_ndr_ts, _ndr_ts_compressed, NDR_COMPRESSION_XPRESS, -1)); + } + compressed_length = _ndr_ts->offset; + talloc_free(_ndr_ts); + } + } + NDR_CHECK(ndr_push_align(ndr, 4)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, decompressed_length)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, compressed_length)); + NDR_CHECK(ndr_push_unique_ptr(ndr, r->ts)); + } + if (ndr_flags & NDR_BUFFERS) { + if (r->ts) { + { + struct ndr_push *_ndr_ts; + NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_ts, 4, -1)); + { + struct ndr_push *_ndr_ts_compressed; + NDR_CHECK(ndr_push_compression_start(_ndr_ts, &_ndr_ts_compressed, NDR_COMPRESSION_XPRESS, -1)); + NDR_CHECK(ndr_push_drsuapi_DsGetNCChangesCtr1TS(_ndr_ts_compressed, NDR_SCALARS|NDR_BUFFERS, r->ts)); + NDR_CHECK(ndr_push_compression_end(_ndr_ts, _ndr_ts_compressed, NDR_COMPRESSION_XPRESS, -1)); + } + NDR_CHECK(ndr_push_subcontext_end(ndr, _ndr_ts, 4, -1)); + } + } + } + return NDR_ERR_SUCCESS; +} + +enum ndr_err_code ndr_push_drsuapi_DsGetNCChangesXPRESSCtr6(struct ndr_push *ndr, int ndr_flags, const struct drsuapi_DsGetNCChangesXPRESSCtr6 *r) +{ + if (ndr_flags & NDR_SCALARS) { + uint32_t decompressed_length = 0; + uint32_t compressed_length = 0; + if (r->ts) { + { + struct ndr_push *_ndr_ts; + NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_ts, 4, -1)); + { + struct ndr_push *_ndr_ts_compressed; + NDR_CHECK(ndr_push_compression_start(_ndr_ts, &_ndr_ts_compressed, NDR_COMPRESSION_XPRESS, -1)); + NDR_CHECK(ndr_push_drsuapi_DsGetNCChangesCtr6TS(_ndr_ts_compressed, NDR_SCALARS|NDR_BUFFERS, r->ts)); + decompressed_length = _ndr_ts_compressed->offset; + NDR_CHECK(ndr_push_compression_end(_ndr_ts, _ndr_ts_compressed, NDR_COMPRESSION_XPRESS, -1)); + } + compressed_length = _ndr_ts->offset; + talloc_free(_ndr_ts); + } + } + NDR_CHECK(ndr_push_align(ndr, 4)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, decompressed_length)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, compressed_length)); + NDR_CHECK(ndr_push_unique_ptr(ndr, r->ts)); + } + if (ndr_flags & NDR_BUFFERS) { + if (r->ts) { + { + struct ndr_push *_ndr_ts; + NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_ts, 4, -1)); + { + struct ndr_push *_ndr_ts_compressed; + NDR_CHECK(ndr_push_compression_start(_ndr_ts, &_ndr_ts_compressed, NDR_COMPRESSION_XPRESS, -1)); + NDR_CHECK(ndr_push_drsuapi_DsGetNCChangesCtr6TS(_ndr_ts_compressed, NDR_SCALARS|NDR_BUFFERS, r->ts)); + NDR_CHECK(ndr_push_compression_end(_ndr_ts, _ndr_ts_compressed, NDR_COMPRESSION_XPRESS, -1)); + } + NDR_CHECK(ndr_push_subcontext_end(ndr, _ndr_ts, 4, -1)); + } + } + } + return NDR_ERR_SUCCESS; +} diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c index a6c7e0020d..28b5cd65a9 100644 --- a/source4/librpc/rpc/dcerpc.c +++ b/source4/librpc/rpc/dcerpc.c @@ -334,6 +334,7 @@ static NTSTATUS ncacn_pull_request_auth(struct dcerpc_connection *c, TALLOC_CTX */ static NTSTATUS ncacn_push_request_sign(struct dcerpc_connection *c, DATA_BLOB *blob, TALLOC_CTX *mem_ctx, + size_t sig_size, struct ncacn_packet *pkt) { NTSTATUS status; @@ -384,8 +385,7 @@ static NTSTATUS ncacn_push_request_sign(struct dcerpc_connection *c, * GENSEC mech does AEAD signing of the packet * headers */ c->security_state.auth_info->credentials - = data_blob_talloc(mem_ctx, NULL, gensec_sig_size(c->security_state.generic_state, - payload_length)); + = data_blob_talloc(mem_ctx, NULL, sig_size); data_blob_clear(&c->security_state.auth_info->credentials); break; @@ -1042,6 +1042,7 @@ static void dcerpc_ship_next_request(struct dcerpc_connection *c) DATA_BLOB blob; uint32_t remaining, chunk_size; bool first_packet = true; + size_t sig_size = 0; req = c->request_queue; if (req == NULL) { @@ -1065,7 +1066,15 @@ static void dcerpc_ship_next_request(struct dcerpc_connection *c) /* we can write a full max_recv_frag size, minus the dcerpc request header size */ - chunk_size = p->conn->srv_max_recv_frag - (DCERPC_MAX_SIGN_SIZE+DCERPC_REQUEST_LENGTH); + chunk_size = p->conn->srv_max_recv_frag; + chunk_size -= DCERPC_REQUEST_LENGTH; + if (c->security_state.generic_state) { + chunk_size -= DCERPC_AUTH_TRAILER_LENGTH; + sig_size = gensec_sig_size(c->security_state.generic_state, + p->conn->srv_max_recv_frag); + chunk_size -= sig_size; + chunk_size -= (chunk_size % 16); + } pkt.ptype = DCERPC_PKT_REQUEST; pkt.call_id = req->call_id; @@ -1101,7 +1110,7 @@ static void dcerpc_ship_next_request(struct dcerpc_connection *c) (stub_data->length - remaining); pkt.u.request.stub_and_verifier.length = chunk; - req->status = ncacn_push_request_sign(p->conn, &blob, req, &pkt); + req->status = ncacn_push_request_sign(p->conn, &blob, req, sig_size, &pkt); if (!NT_STATUS_IS_OK(req->status)) { req->state = RPC_REQUEST_DONE; DLIST_REMOVE(p->conn->pending, req); diff --git a/source4/ntp_signd/ntp_signd.c b/source4/ntp_signd/ntp_signd.c index c1ac7dbcf4..546743e4e6 100644 --- a/source4/ntp_signd/ntp_signd.c +++ b/source4/ntp_signd/ntp_signd.c @@ -123,7 +123,7 @@ static NTSTATUS ntp_signd_recv(void *private, DATA_BLOB wrapped_input) struct signed_reply signed_reply; enum ndr_err_code ndr_err; struct ldb_result *res; - const char *attrs[] = { "unicodePwd", "userAccountControl", NULL }; + const char *attrs[] = { "unicodePwd", "userAccountControl", "cn", NULL }; struct MD5Context ctx; struct samr_Password *nt_hash; uint32_t user_account_control; @@ -168,7 +168,7 @@ static NTSTATUS ntp_signd_recv(void *private, DATA_BLOB wrapped_input) ret = ldb_search_exp_fmt(ntp_signdconn->ntp_signd->samdb, tmp_ctx, &res, samdb_base_dn(ntp_signdconn->ntp_signd->samdb), - LDB_SCOPE_SUBTREE, attrs, "(&(objectSid=%s)(objectClass=computer))", + LDB_SCOPE_SUBTREE, attrs, "(&(objectSid=%s)(objectClass=user))", dom_sid_string(tmp_ctx, sid)); if (ret != LDB_SUCCESS) { DEBUG(2, ("Failed to search for SID %s in SAM for NTP signing: %s\n", dom_sid_string(tmp_ctx, sid), @@ -188,7 +188,13 @@ static NTSTATUS ntp_signd_recv(void *private, DATA_BLOB wrapped_input) user_account_control = ldb_msg_find_attr_as_uint(res->msgs[0], "userAccountControl", 0); if (user_account_control & UF_ACCOUNTDISABLE) { - DEBUG(1, ("Account for SID [%s] is disabled\n", dom_sid_string(tmp_ctx, sid))); + DEBUG(1, ("Account %s for SID [%s] is disabled\n", ldb_dn_get_linearized(res->msgs[0]->dn), dom_sid_string(tmp_ctx, sid))); + talloc_free(tmp_ctx); + return NT_STATUS_ACCESS_DENIED; + } + + if (!(user_account_control & (UF_INTERDOMAIN_TRUST_ACCOUNT|UF_SERVER_TRUST_ACCOUNT|UF_WORKSTATION_TRUST_ACCOUNT))) { + DEBUG(1, ("Account %s for SID [%s] is not a trust account\n", ldb_dn_get_linearized(res->msgs[0]->dn), dom_sid_string(tmp_ctx, sid))); talloc_free(tmp_ctx); return NT_STATUS_ACCESS_DENIED; } diff --git a/source4/ntvfs/ntvfs_generic.c b/source4/ntvfs/ntvfs_generic.c index 4f3a7e2198..c34bb7125e 100644 --- a/source4/ntvfs/ntvfs_generic.c +++ b/source4/ntvfs/ntvfs_generic.c @@ -532,16 +532,14 @@ NTSTATUS ntvfs_map_open(struct ntvfs_module_context *ntvfs, } /* we need to check these bits before we check the private mask */ - if (io2->generic.in.create_options & NTCREATEX_OPTIONS_NOT_SUPPORTED_MASK) { + if (io2->generic.in.create_options & SMB2_CREATE_OPTIONS_NOT_SUPPORTED_MASK) { status = NT_STATUS_NOT_SUPPORTED; break; } - /* we use a couple of bits of the create options internally */ - if (io2->generic.in.create_options & NTCREATEX_OPTIONS_PRIVATE_MASK) { - status = NT_STATUS_INVALID_PARAMETER; - break; - } + /* TODO: find out why only SMB2 ignores these */ + io2->generic.in.create_options &= ~NTCREATEX_OPTIONS_SYNC_ALERT; + io2->generic.in.create_options &= ~NTCREATEX_OPTIONS_ASYNC_ALERT; status = ntvfs->ops->open(ntvfs, req, io2); break; diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 6114b2052c..c127885a68 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1181,6 +1181,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, int fd; struct odb_lock *lck; uint32_t create_options; + uint32_t create_options_must_ignore_mask; uint32_t share_access; uint32_t access_mask; uint32_t create_action = NTCREATEX_ACTION_EXISTED; @@ -1206,13 +1207,22 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return NT_STATUS_INVALID_PARAMETER; } - /* These options are ignored */ - create_options &= ~NTCREATEX_OPTIONS_MUST_IGNORE_MASK; + /* + * These options are ignored, + * but we reuse some of them as private values for the generic mapping + */ + create_options_must_ignore_mask = NTCREATEX_OPTIONS_MUST_IGNORE_MASK; + create_options_must_ignore_mask &= ~NTCREATEX_OPTIONS_PRIVATE_MASK; + create_options &= ~create_options_must_ignore_mask; if (create_options & NTCREATEX_OPTIONS_NOT_SUPPORTED_MASK) { return NT_STATUS_NOT_SUPPORTED; } + if (create_options & NTCREATEX_OPTIONS_INVALID_PARAM_MASK) { + return NT_STATUS_INVALID_PARAMETER; + } + /* TODO: When we implement HSM, add a hook here not to pull * the actual file off tape, when this option is passed from * the client */ diff --git a/source4/pidl/lib/Parse/Pidl/NDR.pm b/source4/pidl/lib/Parse/Pidl/NDR.pm index 1e4504764a..10bd29715b 100644 --- a/source4/pidl/lib/Parse/Pidl/NDR.pm +++ b/source4/pidl/lib/Parse/Pidl/NDR.pm @@ -287,6 +287,22 @@ sub GetElementLevelTable($$) return $order; } +sub GetTypedefLevelTable($$$) +{ + my ($e, $data, $pointer_default) = @_; + + my $order = []; + + push (@$order, { + TYPE => "TYPEDEF" + }); + + my $i = 0; + foreach (@$order) { $_->{LEVEL_INDEX} = $i; $i+=1; } + + return $order; +} + ##################################################################### # see if a type contains any deferred data sub can_contain_deferred($) @@ -575,6 +591,7 @@ sub ParseTypedef($$) NAME => $d->{NAME}, TYPE => $d->{TYPE}, PROPERTIES => $d->{PROPERTIES}, + LEVELS => GetTypedefLevelTable($d, $data, $pointer_default), DATA => $data, ORIGINAL => $d }; @@ -795,20 +812,21 @@ sub ContainsDeferred($$) sub el_name($) { my $e = shift; + my $name = "<ANONYMOUS>"; - if ($e->{PARENT} && $e->{PARENT}->{NAME}) { - return "$e->{PARENT}->{NAME}.$e->{NAME}"; - } + $name = $e->{NAME} if defined($e->{NAME}); - if ($e->{PARENT} && $e->{PARENT}->{PARENT}->{NAME}) { - return "$e->{PARENT}->{PARENT}->{NAME}.$e->{NAME}"; + if (defined($e->{PARENT}) and defined($e->{PARENT}->{NAME})) { + return "$e->{PARENT}->{NAME}.$name"; } - if ($e->{PARENT}) { - return "$e->{PARENT}->{NAME}.$e->{NAME}"; + if (defined($e->{PARENT}) and + defined($e->{PARENT}->{PARENT}) and + defined($e->{PARENT}->{PARENT}->{NAME})) { + return "$e->{PARENT}->{PARENT}->{NAME}.$name"; } - return $e->{NAME}; + return $name; } ################################### @@ -858,25 +876,25 @@ my %property_list = ( "unique" => ["ELEMENT"], "ignore" => ["ELEMENT"], "relative" => ["ELEMENT"], - "relative_base" => ["TYPEDEF"], + "relative_base" => ["TYPEDEF", "STRUCT", "UNION"], - "gensize" => ["TYPEDEF"], + "gensize" => ["TYPEDEF", "STRUCT", "UNION"], "value" => ["ELEMENT"], - "flag" => ["ELEMENT", "TYPEDEF"], + "flag" => ["ELEMENT", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP"], # generic - "public" => ["FUNCTION", "TYPEDEF"], - "nopush" => ["FUNCTION", "TYPEDEF"], - "nopull" => ["FUNCTION", "TYPEDEF"], - "nosize" => ["FUNCTION", "TYPEDEF"], - "noprint" => ["FUNCTION", "TYPEDEF"], - "noejs" => ["FUNCTION", "TYPEDEF"], + "public" => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP"], + "nopush" => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP"], + "nopull" => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP"], + "nosize" => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP"], + "noprint" => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP", "ELEMENT"], + "noejs" => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP"], "todo" => ["FUNCTION"], # union "switch_is" => ["ELEMENT"], - "switch_type" => ["ELEMENT", "TYPEDEF"], - "nodiscriminant" => ["TYPEDEF"], + "switch_type" => ["ELEMENT", "UNION"], + "nodiscriminant" => ["UNION"], "case" => ["ELEMENT"], "default" => ["ELEMENT"], @@ -889,15 +907,15 @@ my %property_list = ( "compression" => ["ELEMENT"], # enum - "enum8bit" => ["TYPEDEF"], - "enum16bit" => ["TYPEDEF"], - "v1_enum" => ["TYPEDEF"], + "enum8bit" => ["ENUM"], + "enum16bit" => ["ENUM"], + "v1_enum" => ["ENUM"], # bitmap - "bitmap8bit" => ["TYPEDEF"], - "bitmap16bit" => ["TYPEDEF"], - "bitmap32bit" => ["TYPEDEF"], - "bitmap64bit" => ["TYPEDEF"], + "bitmap8bit" => ["BITMAP"], + "bitmap16bit" => ["BITMAP"], + "bitmap32bit" => ["BITMAP"], + "bitmap64bit" => ["BITMAP"], # array "range" => ["ELEMENT"], @@ -921,7 +939,7 @@ sub ValidProperties($$) unless defined($property_list{$key}); fatal($e, el_name($e) . ": property '$key' not allowed on '$t'") - unless grep($t, @{$property_list{$key}}); + unless grep(/^$t$/, @{$property_list{$key}}); } } @@ -1101,6 +1119,9 @@ sub ValidTypedef($) $data->{PARENT} = $typedef; + $data->{FILE} = $typedef->{FILE} unless defined($data->{FILE}); + $data->{LINE} = $typedef->{LINE} unless defined($data->{LINE}); + ValidType($data) if (ref($data) eq "HASH"); } diff --git a/source4/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm b/source4/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm index a0de1f127a..745777d012 100644 --- a/source4/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm +++ b/source4/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm @@ -158,26 +158,26 @@ sub fn_declare($$$$) ################################################################### # setup any special flags for an element or structure -sub start_flags($$) +sub start_flags($$$) { - my ($self, $e) = @_; + my ($self, $e, $ndr) = @_; my $flags = has_property($e, "flag"); if (defined $flags) { $self->pidl("{"); $self->indent; - $self->pidl("uint32_t _flags_save_$e->{TYPE} = ndr->flags;"); - $self->pidl("ndr_set_flags(&ndr->flags, $flags);"); + $self->pidl("uint32_t _flags_save_$e->{TYPE} = $ndr->flags;"); + $self->pidl("ndr_set_flags(&$ndr->flags, $flags);"); } } ################################################################### # end any special flags for an element or structure -sub end_flags($$) +sub end_flags($$$) { - my ($self, $e) = @_; + my ($self, $e, $ndr) = @_; my $flags = has_property($e, "flag"); if (defined $flags) { - $self->pidl("ndr->flags = _flags_save_$e->{TYPE};"); + $self->pidl("$ndr->flags = _flags_save_$e->{TYPE};"); $self->deindent; $self->pidl("}"); } @@ -331,12 +331,12 @@ sub ParseArrayPullHeader($$$$$$) } else { $length = $size = ParseExprExt($l->{SIZE_IS}, $env, $e->{ORIGINAL}, check_null_pointer($e, $env, sub { $self->pidl(shift); }, - "return ndr_pull_error(ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for size_is()\");"), + "return ndr_pull_error($ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for size_is()\");"), check_fully_dereferenced($e, $env)); } if ((!$l->{IS_SURROUNDING}) and $l->{IS_CONFORMANT}) { - $self->pidl("NDR_CHECK(ndr_pull_array_size(ndr, " . get_pointer_to($var_name) . "));"); + $self->pidl("NDR_CHECK(ndr_pull_array_size($ndr, " . get_pointer_to($var_name) . "));"); } if ($l->{IS_VARYING}) { @@ -357,9 +357,9 @@ sub ParseArrayPullHeader($$$$$$) $self->defer_indent; my $size = ParseExprExt($l->{SIZE_IS}, $env, $e->{ORIGINAL}, check_null_pointer($e, $env, sub { $self->defer(shift); }, - "return ndr_pull_error(ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for size_is()\");"), + "return ndr_pull_error($ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for size_is()\");"), check_fully_dereferenced($e, $env)); - $self->defer("NDR_CHECK(ndr_check_array_size(ndr, (void*)" . get_pointer_to($var_name) . ", $size));"); + $self->defer("NDR_CHECK(ndr_check_array_size($ndr, (void*)" . get_pointer_to($var_name) . ", $size));"); $self->defer_deindent; $self->defer("}"); } @@ -369,9 +369,9 @@ sub ParseArrayPullHeader($$$$$$) $self->defer_indent; my $length = ParseExprExt($l->{LENGTH_IS}, $env, $e->{ORIGINAL}, check_null_pointer($e, $env, sub { $self->defer(shift); }, - "return ndr_pull_error(ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for length_is()\");"), + "return ndr_pull_error($ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for length_is()\");"), check_fully_dereferenced($e, $env)); - $self->defer("NDR_CHECK(ndr_check_array_length(ndr, (void*)" . get_pointer_to($var_name) . ", $length));"); + $self->defer("NDR_CHECK(ndr_check_array_length($ndr, (void*)" . get_pointer_to($var_name) . ", $length));"); $self->defer_deindent; $self->defer("}"); } @@ -543,7 +543,7 @@ sub ParseElementPushLevel $self->ParseElementPushLevel($e, GetNextLevel($e, $l), $subndr, $var_name, $env, 1, 1); $self->ParseSubcontextPushEnd($e, $l, $ndr, $env); } elsif ($l->{TYPE} eq "POINTER") { - $self->ParsePtrPush($e, $l, $var_name); + $self->ParsePtrPush($e, $l, $ndr, $var_name); } elsif ($l->{TYPE} eq "ARRAY") { my $length = $self->ParseArrayPushHeader($e, $l, $ndr, $var_name, $env); @@ -561,6 +561,8 @@ sub ParseElementPushLevel $self->ParseSwitchPush($e, $l, $ndr, $var_name, $env); } elsif ($l->{TYPE} eq "DATA") { $self->ParseDataPush($e, $l, $ndr, $var_name, $primitives, $deferred); + } elsif ($l->{TYPE} eq "TYPEDEF") { + $typefamily{$e->{DATA}->{TYPE}}->{PUSH_FN_BODY}->($self, $e->{DATA}, $ndr, $var_name); } } @@ -569,7 +571,7 @@ sub ParseElementPushLevel $self->pidl("if ($var_name) {"); $self->indent; if ($l->{POINTER_TYPE} eq "relative") { - $self->pidl("NDR_CHECK(ndr_push_relative_ptr2(ndr, $var_name));"); + $self->pidl("NDR_CHECK(ndr_push_relative_ptr2($ndr, $var_name));"); } } $var_name = get_value_of($var_name); @@ -629,7 +631,7 @@ sub ParseElementPush($$$$$$) $var_name = append_prefix($e, $var_name); - $self->start_flags($e); + $self->start_flags($e, $ndr); if (defined(my $value = has_property($e, "value"))) { $var_name = ParseExpr($value, $env, $e->{ORIGINAL}); @@ -637,7 +639,7 @@ sub ParseElementPush($$$$$$) $self->ParseElementPushLevel($e, $e->{LEVELS}[0], $ndr, $var_name, $env, $primitives, $deferred); - $self->end_flags($e); + $self->end_flags($e, $ndr); if ($e->{REPRESENTATION_TYPE} ne $e->{TYPE}) { $self->deindent; @@ -647,25 +649,25 @@ sub ParseElementPush($$$$$$) ##################################################################### # parse a pointer in a struct element or function -sub ParsePtrPush($$$$) +sub ParsePtrPush($$$$$) { - my ($self,$e,$l,$var_name) = @_; + my ($self,$e,$l,$ndr,$var_name) = @_; if ($l->{POINTER_TYPE} eq "ref") { $self->pidl("if ($var_name == NULL) {"); $self->indent; - $self->pidl("return ndr_push_error(ndr, NDR_ERR_INVALID_POINTER, \"NULL [ref] pointer\");"); + $self->pidl("return ndr_push_error($ndr, NDR_ERR_INVALID_POINTER, \"NULL [ref] pointer\");"); $self->deindent; $self->pidl("}"); if ($l->{LEVEL} eq "EMBEDDED") { $self->pidl("NDR_CHECK(ndr_push_ref_ptr(ndr));"); } } elsif ($l->{POINTER_TYPE} eq "relative") { - $self->pidl("NDR_CHECK(ndr_push_relative_ptr1(ndr, $var_name));"); + $self->pidl("NDR_CHECK(ndr_push_relative_ptr1($ndr, $var_name));"); } elsif ($l->{POINTER_TYPE} eq "unique") { - $self->pidl("NDR_CHECK(ndr_push_unique_ptr(ndr, $var_name));"); + $self->pidl("NDR_CHECK(ndr_push_unique_ptr($ndr, $var_name));"); } elsif ($l->{POINTER_TYPE} eq "full") { - $self->pidl("NDR_CHECK(ndr_push_full_ptr(ndr, $var_name));"); + $self->pidl("NDR_CHECK(ndr_push_full_ptr($ndr, $var_name));"); } else { die("Unhandled pointer type $l->{POINTER_TYPE}"); } @@ -702,45 +704,45 @@ sub need_pointer_to($$$) return 0; } -sub ParseDataPrint($$$$) +sub ParseDataPrint($$$$$) { - my ($self, $e, $l, $var_name) = @_; - + my ($self, $e, $l, $ndr, $var_name) = @_; + if (not ref($l->{DATA_TYPE}) or defined($l->{DATA_TYPE}->{NAME})) { if (need_pointer_to($e, $l, 1)) { $var_name = get_pointer_to($var_name); } - $self->pidl(TypeFunctionName("ndr_print", $l->{DATA_TYPE})."(ndr, \"$e->{NAME}\", $var_name);"); + $self->pidl(TypeFunctionName("ndr_print", $l->{DATA_TYPE})."($ndr, \"$e->{NAME}\", $var_name);"); } else { - $self->ParseTypePrint($l->{DATA_TYPE}, $var_name); + $self->ParseTypePrint($l->{DATA_TYPE}, $ndr, $var_name); } } ##################################################################### # print scalars in a structure element -sub ParseElementPrint($$$$) +sub ParseElementPrint($$$$$) { - my($self, $e, $var_name, $env) = @_; + my($self, $e, $ndr, $var_name, $env) = @_; return if (has_property($e, "noprint")); if ($e->{REPRESENTATION_TYPE} ne $e->{TYPE}) { - $self->pidl("ndr_print_$e->{REPRESENTATION_TYPE}(ndr, \"$e->{NAME}\", $var_name);"); + $self->pidl("ndr_print_$e->{REPRESENTATION_TYPE}($ndr, \"$e->{NAME}\", $var_name);"); return; } $var_name = append_prefix($e, $var_name); if (defined(my $value = has_property($e, "value"))) { - $var_name = "(ndr->flags & LIBNDR_PRINT_SET_VALUES)?" . ParseExpr($value,$env, $e->{ORIGINAL}) . ":$var_name"; + $var_name = "($ndr->flags & LIBNDR_PRINT_SET_VALUES)?" . ParseExpr($value,$env, $e->{ORIGINAL}) . ":$var_name"; } foreach my $l (@{$e->{LEVELS}}) { if ($l->{TYPE} eq "POINTER") { - $self->pidl("ndr_print_ptr(ndr, \"$e->{NAME}\", $var_name);"); - $self->pidl("ndr->depth++;"); + $self->pidl("ndr_print_ptr($ndr, \"$e->{NAME}\", $var_name);"); + $self->pidl("$ndr->depth++;"); if ($l->{POINTER_TYPE} ne "ref") { $self->pidl("if ($var_name) {"); $self->indent; @@ -761,17 +763,17 @@ sub ParseElementPrint($$$$) } if (is_charset_array($e,$l)) { - $self->pidl("ndr_print_string(ndr, \"$e->{NAME}\", $var_name);"); + $self->pidl("ndr_print_string($ndr, \"$e->{NAME}\", $var_name);"); last; } elsif (has_fast_array($e, $l)) { my $nl = GetNextLevel($e, $l); - $self->pidl("ndr_print_array_$nl->{DATA_TYPE}(ndr, \"$e->{NAME}\", $var_name, $length);"); + $self->pidl("ndr_print_array_$nl->{DATA_TYPE}($ndr, \"$e->{NAME}\", $var_name, $length);"); last; } else { my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}"; - $self->pidl("ndr->print(ndr, \"\%s: ARRAY(\%d)\", \"$e->{NAME}\", (int)$length);"); - $self->pidl("ndr->depth++;"); + $self->pidl("$ndr->print($ndr, \"\%s: ARRAY(\%d)\", \"$e->{NAME}\", (int)$length);"); + $self->pidl("$ndr->depth++;"); $self->pidl("for ($counter=0;$counter<$length;$counter++) {"); $self->indent; $self->pidl("char *idx_$l->{LEVEL_INDEX}=NULL;"); @@ -781,11 +783,11 @@ sub ParseElementPrint($$$$) $var_name = get_array_element($var_name, $counter); } } elsif ($l->{TYPE} eq "DATA") { - $self->ParseDataPrint($e, $l, $var_name); + $self->ParseDataPrint($e, $l, $ndr, $var_name); } elsif ($l->{TYPE} eq "SWITCH") { my $switch_var = ParseExprExt($l->{SWITCH_IS}, $env, $e->{ORIGINAL}, check_null_pointer($e, $env, sub { $self->pidl(shift); }, "return;"), check_fully_dereferenced($e, $env)); - $self->pidl("ndr_print_set_switch_value(ndr, " . get_pointer_to($var_name) . ", $switch_var);"); + $self->pidl("ndr_print_set_switch_value($ndr, " . get_pointer_to($var_name) . ", $switch_var);"); } } @@ -795,7 +797,7 @@ sub ParseElementPrint($$$$) $self->deindent; $self->pidl("}"); } - $self->pidl("ndr->depth--;"); + $self->pidl("$ndr->depth--;"); } elsif (($l->{TYPE} eq "ARRAY") and not is_charset_array($e,$l) and not has_fast_array($e,$l)) { @@ -804,7 +806,7 @@ sub ParseElementPrint($$$$) $self->pidl("}"); $self->deindent; $self->pidl("}"); - $self->pidl("ndr->depth--;"); + $self->pidl("$ndr->depth--;"); } } } @@ -816,7 +818,7 @@ sub ParseSwitchPull($$$$$$) my($self,$e,$l,$ndr,$var_name,$env) = @_; my $switch_var = ParseExprExt($l->{SWITCH_IS}, $env, $e->{ORIGINAL}, check_null_pointer($e, $env, sub { $self->pidl(shift); }, - "return ndr_pull_error(ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for switch_is()\");"), + "return ndr_pull_error($ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for switch_is()\");"), check_fully_dereferenced($e, $env)); $var_name = get_pointer_to($var_name); @@ -830,7 +832,7 @@ sub ParseSwitchPush($$$$$$) my($self,$e,$l,$ndr,$var_name,$env) = @_; my $switch_var = ParseExprExt($l->{SWITCH_IS}, $env, $e->{ORIGINAL}, check_null_pointer($e, $env, sub { $self->pidl(shift); }, - "return ndr_push_error(ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for switch_is()\");"), + "return ndr_push_error($ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for switch_is()\");"), check_fully_dereferenced($e, $env)); $var_name = get_pointer_to($var_name); @@ -861,7 +863,7 @@ sub ParseDataPull($$$$$$$) $self->pidl("}"); } } else { - $self->ParseTypePull($l->{DATA_TYPE}, $var_name, $primitives, $deferred); + $self->ParseTypePull($l->{DATA_TYPE}, $ndr, $var_name, $primitives, $deferred); } } @@ -880,7 +882,7 @@ sub ParseDataPush($$$$$$$) $self->pidl("NDR_CHECK(".TypeFunctionName("ndr_push", $l->{DATA_TYPE})."($ndr, $ndr_flags, $var_name));"); } else { - $self->ParseTypePush($l->{DATA_TYPE}, $var_name, $primitives, $deferred); + $self->ParseTypePush($l->{DATA_TYPE}, $ndr, $var_name, $primitives, $deferred); } } @@ -936,9 +938,9 @@ sub ParseMemCtxPullFlags($$$$) return $mem_flags; } -sub ParseMemCtxPullStart($$$$) +sub ParseMemCtxPullStart($$$$$) { - my ($self, $e, $l, $ptr_name) = @_; + my ($self, $e, $l, $ndr, $ptr_name) = @_; my $mem_r_ctx = "_mem_save_$e->{NAME}_$l->{LEVEL_INDEX}"; my $mem_c_ctx = $ptr_name; @@ -946,20 +948,20 @@ sub ParseMemCtxPullStart($$$$) return unless defined($mem_c_flags); - $self->pidl("$mem_r_ctx = NDR_PULL_GET_MEM_CTX(ndr);"); - $self->pidl("NDR_PULL_SET_MEM_CTX(ndr, $mem_c_ctx, $mem_c_flags);"); + $self->pidl("$mem_r_ctx = NDR_PULL_GET_MEM_CTX($ndr);"); + $self->pidl("NDR_PULL_SET_MEM_CTX($ndr, $mem_c_ctx, $mem_c_flags);"); } -sub ParseMemCtxPullEnd($$$) +sub ParseMemCtxPullEnd($$$$) { - my ($self, $e, $l) = @_; + my ($self, $e, $l, $ndr) = @_; my $mem_r_ctx = "_mem_save_$e->{NAME}_$l->{LEVEL_INDEX}"; my $mem_r_flags = $self->ParseMemCtxPullFlags($e, $l); return unless defined($mem_r_flags); - $self->pidl("NDR_PULL_SET_MEM_CTX(ndr, $mem_r_ctx, $mem_r_flags);"); + $self->pidl("NDR_PULL_SET_MEM_CTX($ndr, $mem_r_ctx, $mem_r_flags);"); } sub CheckStringTerminator($$$$$) @@ -1011,6 +1013,8 @@ sub ParseElementPullLevel $self->ParseSwitchPull($e, $l, $ndr, $var_name, $env); } elsif ($l->{TYPE} eq "DATA") { $self->ParseDataPull($e, $l, $ndr, $var_name, $primitives, $deferred); + } elsif ($l->{TYPE} eq "TYPEDEF") { + $typefamily{$e->{DATA}->{TYPE}}->{PULL_FN_BODY}->($self, $e->{DATA}, $ndr, $var_name); } } @@ -1022,21 +1026,21 @@ sub ParseElementPullLevel if ($l->{POINTER_TYPE} eq "relative") { $self->pidl("uint32_t _relative_save_offset;"); - $self->pidl("_relative_save_offset = ndr->offset;"); - $self->pidl("NDR_CHECK(ndr_pull_relative_ptr2(ndr, $var_name));"); + $self->pidl("_relative_save_offset = $ndr->offset;"); + $self->pidl("NDR_CHECK(ndr_pull_relative_ptr2($ndr, $var_name));"); } } - $self->ParseMemCtxPullStart($e, $l, $var_name); + $self->ParseMemCtxPullStart($e, $l, $ndr, $var_name); $var_name = get_value_of($var_name); $self->ParseElementPullLevel($e, GetNextLevel($e,$l), $ndr, $var_name, $env, 1, 1); - $self->ParseMemCtxPullEnd($e,$l); + $self->ParseMemCtxPullEnd($e, $l, $ndr); if ($l->{POINTER_TYPE} ne "ref") { if ($l->{POINTER_TYPE} eq "relative") { - $self->pidl("ndr->offset = _relative_save_offset;"); + $self->pidl("$ndr->offset = _relative_save_offset;"); } $self->deindent; $self->pidl("}"); @@ -1049,7 +1053,7 @@ sub ParseElementPullLevel $var_name = get_array_element($var_name, $counter); - $self->ParseMemCtxPullStart($e, $l, $array_name); + $self->ParseMemCtxPullStart($e, $l, $ndr, $array_name); if (($primitives and not $l->{IS_DEFERRED}) or ($deferred and $l->{IS_DEFERRED})) { my $nl = GetNextLevel($e,$l); @@ -1073,7 +1077,7 @@ sub ParseElementPullLevel $self->pidl("}"); } - $self->ParseMemCtxPullEnd($e, $l); + $self->ParseMemCtxPullEnd($e, $l, $ndr); } elsif ($l->{TYPE} eq "SWITCH") { $self->ParseElementPullLevel($e, GetNextLevel($e,$l), $ndr, $var_name, $env, $primitives, $deferred); @@ -1103,11 +1107,11 @@ sub ParseElementPull($$$$$$) $var_name = append_prefix($e, $var_name); - $self->start_flags($e); + $self->start_flags($e, $ndr); $self->ParseElementPullLevel($e,$e->{LEVELS}[0],$ndr,$var_name,$env,$primitives,$deferred); - $self->end_flags($e); + $self->end_flags($e, $ndr); # Representation type is different from transmit_as if ($e->{REPRESENTATION_TYPE} ne $e->{TYPE}) { @@ -1131,7 +1135,7 @@ sub ParsePtrPull($$$$$) if ($l->{POINTER_TYPE} eq "ref" and $l->{LEVEL} eq "TOP") { if (!$next_is_array and !$next_is_string) { - $self->pidl("if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {"); + $self->pidl("if ($ndr->flags & LIBNDR_FLAG_REF_ALLOC) {"); $self->pidl("\tNDR_PULL_ALLOC($ndr, $var_name);"); $self->pidl("}"); } @@ -1172,9 +1176,9 @@ sub ParsePtrPull($$$$$) $self->pidl("}"); } -sub ParseStructPushPrimitives($$$$) +sub ParseStructPushPrimitives($$$$$) { - my ($self, $struct, $varname, $env) = @_; + my ($self, $struct, $ndr, $varname, $env) = @_; # see if the structure contains a conformant array. If it # does, then it must be the last element of the structure, and @@ -1198,39 +1202,39 @@ sub ParseStructPushPrimitives($$$$) $size = ParseExpr($e->{LEVELS}[0]->{SIZE_IS}, $env, $e->{ORIGINAL}); } - $self->pidl("NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, $size));"); + $self->pidl("NDR_CHECK(ndr_push_uint32($ndr, NDR_SCALARS, $size));"); } else { - $self->pidl("NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_string_array_size(ndr, $varname->$e->{NAME})));"); + $self->pidl("NDR_CHECK(ndr_push_uint32($ndr, NDR_SCALARS, ndr_string_array_size($ndr, $varname->$e->{NAME})));"); } } - $self->pidl("NDR_CHECK(ndr_push_align(ndr, $struct->{ALIGN}));"); + $self->pidl("NDR_CHECK(ndr_push_align($ndr, $struct->{ALIGN}));"); if (defined($struct->{PROPERTIES}{relative_base})) { # set the current offset as base for relative pointers # and store it based on the toplevel struct/union - $self->pidl("NDR_CHECK(ndr_push_setup_relative_base_offset1(ndr, $varname, ndr->offset));"); + $self->pidl("NDR_CHECK(ndr_push_setup_relative_base_offset1($ndr, $varname, $ndr->offset));"); } - $self->ParseElementPush($_, "ndr", $env, 1, 0) foreach (@{$struct->{ELEMENTS}}); + $self->ParseElementPush($_, $ndr, $env, 1, 0) foreach (@{$struct->{ELEMENTS}}); } -sub ParseStructPushDeferred($$$) +sub ParseStructPushDeferred($$$$) { - my ($self, $struct, $varname, $env) = @_; + my ($self, $struct, $ndr, $varname, $env) = @_; if (defined($struct->{PROPERTIES}{relative_base})) { # retrieve the current offset as base for relative pointers # based on the toplevel struct/union - $self->pidl("NDR_CHECK(ndr_push_setup_relative_base_offset2(ndr, $varname));"); + $self->pidl("NDR_CHECK(ndr_push_setup_relative_base_offset2($ndr, $varname));"); } - $self->ParseElementPush($_, "ndr", $env, 0, 1) foreach (@{$struct->{ELEMENTS}}); + $self->ParseElementPush($_, $ndr, $env, 0, 1) foreach (@{$struct->{ELEMENTS}}); } ##################################################################### # parse a struct -sub ParseStructPush($$$) +sub ParseStructPush($$$$) { - my ($self, $struct, $varname) = @_; + my ($self, $struct, $ndr, $varname) = @_; return unless defined($struct->{ELEMENTS}); @@ -1240,61 +1244,61 @@ sub ParseStructPush($$$) $self->DeclareArrayVariables($_) foreach (@{$struct->{ELEMENTS}}); - $self->start_flags($struct); + $self->start_flags($struct, $ndr); $self->pidl("if (ndr_flags & NDR_SCALARS) {"); $self->indent; - $self->ParseStructPushPrimitives($struct, $varname, $env); + $self->ParseStructPushPrimitives($struct, $ndr, $varname, $env); $self->deindent; $self->pidl("}"); $self->pidl("if (ndr_flags & NDR_BUFFERS) {"); $self->indent; - $self->ParseStructPushDeferred($struct, $varname, $env); + $self->ParseStructPushDeferred($struct, $ndr, $varname, $env); $self->deindent; $self->pidl("}"); - $self->end_flags($struct); + $self->end_flags($struct, $ndr); } ##################################################################### # generate a push function for an enum -sub ParseEnumPush($$$) +sub ParseEnumPush($$$$) { - my($self,$enum,$varname) = @_; + my($self,$enum,$ndr,$varname) = @_; my($type_fn) = $enum->{BASE_TYPE}; - $self->start_flags($enum); - $self->pidl("NDR_CHECK(ndr_push_$type_fn(ndr, NDR_SCALARS, $varname));"); - $self->end_flags($enum); + $self->start_flags($enum, $ndr); + $self->pidl("NDR_CHECK(ndr_push_$type_fn($ndr, NDR_SCALARS, $varname));"); + $self->end_flags($enum, $ndr); } ##################################################################### # generate a pull function for an enum -sub ParseEnumPull($$$) +sub ParseEnumPull($$$$) { - my($self,$enum,$varname) = @_; + my($self,$enum,$ndr,$varname) = @_; my($type_fn) = $enum->{BASE_TYPE}; my($type_v_decl) = mapTypeName($type_fn); $self->pidl("$type_v_decl v;"); - $self->start_flags($enum); - $self->pidl("NDR_CHECK(ndr_pull_$type_fn(ndr, NDR_SCALARS, &v));"); + $self->start_flags($enum, $ndr); + $self->pidl("NDR_CHECK(ndr_pull_$type_fn($ndr, NDR_SCALARS, &v));"); $self->pidl("*$varname = v;"); - $self->end_flags($enum); + $self->end_flags($enum, $ndr); } ##################################################################### # generate a print function for an enum -sub ParseEnumPrint($$$$) +sub ParseEnumPrint($$$$$) { - my($self,$enum,$name,$varname) = @_; + my($self,$enum,$ndr,$name,$varname) = @_; $self->pidl("const char *val = NULL;"); $self->pidl(""); - $self->start_flags($enum); + $self->start_flags($enum, $ndr); $self->pidl("switch ($varname) {"); $self->indent; @@ -1311,9 +1315,9 @@ sub ParseEnumPrint($$$$) $self->deindent; $self->pidl("}"); - $self->pidl("ndr_print_enum(ndr, name, \"$enum->{TYPE}\", val, $varname);"); + $self->pidl("ndr_print_enum($ndr, name, \"$enum->{TYPE}\", val, $varname);"); - $self->end_flags($enum); + $self->end_flags($enum, $ndr); } sub DeclEnum($$$$) @@ -1332,39 +1336,39 @@ $typefamily{ENUM} = { ##################################################################### # generate a push function for a bitmap -sub ParseBitmapPush($$$) +sub ParseBitmapPush($$$$) { - my($self,$bitmap,$varname) = @_; + my($self,$bitmap,$ndr,$varname) = @_; my($type_fn) = $bitmap->{BASE_TYPE}; - $self->start_flags($bitmap); + $self->start_flags($bitmap, $ndr); - $self->pidl("NDR_CHECK(ndr_push_$type_fn(ndr, NDR_SCALARS, $varname));"); + $self->pidl("NDR_CHECK(ndr_push_$type_fn($ndr, NDR_SCALARS, $varname));"); - $self->end_flags($bitmap); + $self->end_flags($bitmap, $ndr); } ##################################################################### # generate a pull function for an bitmap -sub ParseBitmapPull($$$) +sub ParseBitmapPull($$$$) { - my($self,$bitmap,$varname) = @_; + my($self,$bitmap,$ndr,$varname) = @_; my $type_fn = $bitmap->{BASE_TYPE}; my($type_decl) = mapTypeName($bitmap->{BASE_TYPE}); $self->pidl("$type_decl v;"); - $self->start_flags($bitmap); - $self->pidl("NDR_CHECK(ndr_pull_$type_fn(ndr, NDR_SCALARS, &v));"); + $self->start_flags($bitmap, $ndr); + $self->pidl("NDR_CHECK(ndr_pull_$type_fn($ndr, NDR_SCALARS, &v));"); $self->pidl("*$varname = v;"); - $self->end_flags($bitmap); + $self->end_flags($bitmap, $ndr); } ##################################################################### # generate a print function for an bitmap -sub ParseBitmapPrintElement($$$$$) +sub ParseBitmapPrintElement($$$$$$) { - my($self,$e,$bitmap,$name,$varname) = @_; + my($self,$e,$bitmap,$ndr,$name,$varname) = @_; my($type_decl) = mapTypeName($bitmap->{BASE_TYPE}); my($type_fn) = $bitmap->{BASE_TYPE}; my($flag); @@ -1375,28 +1379,28 @@ sub ParseBitmapPrintElement($$$$$) die "Bitmap: \"$name\" invalid Flag: \"$e\""; } - $self->pidl("ndr_print_bitmap_flag(ndr, sizeof($type_decl), \"$flag\", $flag, $varname);"); + $self->pidl("ndr_print_bitmap_flag($ndr, sizeof($type_decl), \"$flag\", $flag, $varname);"); } ##################################################################### # generate a print function for an bitmap -sub ParseBitmapPrint($$$$) +sub ParseBitmapPrint($$$$$) { - my($self,$bitmap,$name,$varname) = @_; + my($self,$bitmap,$ndr,$name,$varname) = @_; my($type_decl) = mapTypeName($bitmap->{TYPE}); my($type_fn) = $bitmap->{BASE_TYPE}; - $self->start_flags($bitmap); + $self->start_flags($bitmap, $ndr); - $self->pidl("ndr_print_$type_fn(ndr, name, $varname);"); + $self->pidl("ndr_print_$type_fn($ndr, name, $varname);"); - $self->pidl("ndr->depth++;"); + $self->pidl("$ndr->depth++;"); foreach my $e (@{$bitmap->{ELEMENTS}}) { - $self->ParseBitmapPrintElement($e, $bitmap, $name, $varname); + $self->ParseBitmapPrintElement($e, $bitmap, $ndr, $name, $varname); } - $self->pidl("ndr->depth--;"); + $self->pidl("$ndr->depth--;"); - $self->end_flags($bitmap); + $self->end_flags($bitmap, $ndr); } sub DeclBitmap($$$$) @@ -1415,9 +1419,9 @@ $typefamily{BITMAP} = { ##################################################################### # generate a struct print function -sub ParseStructPrint($$$$) +sub ParseStructPrint($$$$$) { - my($self,$struct,$name,$varname) = @_; + my($self,$struct,$ndr,$name,$varname) = @_; return unless defined $struct->{ELEMENTS}; @@ -1425,17 +1429,17 @@ sub ParseStructPrint($$$$) $self->DeclareArrayVariables($_) foreach (@{$struct->{ELEMENTS}}); - $self->pidl("ndr_print_struct(ndr, name, \"$name\");"); + $self->pidl("ndr_print_struct($ndr, name, \"$name\");"); - $self->start_flags($struct); + $self->start_flags($struct, $ndr); - $self->pidl("ndr->depth++;"); + $self->pidl("$ndr->depth++;"); - $self->ParseElementPrint($_, $env->{$_->{NAME}}, $env) + $self->ParseElementPrint($_, $ndr, $env->{$_->{NAME}}, $env) foreach (@{$struct->{ELEMENTS}}); - $self->pidl("ndr->depth--;"); + $self->pidl("$ndr->depth--;"); - $self->end_flags($struct); + $self->end_flags($struct, $ndr); } sub DeclarePtrVariables($$) @@ -1474,38 +1478,38 @@ sub DeclareMemCtxVariables($$) } } -sub ParseStructPullPrimitives($$$$) +sub ParseStructPullPrimitives($$$$$) { - my($self,$struct,$varname,$env) = @_; + my($self,$struct,$ndr,$varname,$env) = @_; if (defined $struct->{SURROUNDING_ELEMENT}) { - $self->pidl("NDR_CHECK(ndr_pull_array_size(ndr, &$varname->$struct->{SURROUNDING_ELEMENT}->{NAME}));"); + $self->pidl("NDR_CHECK(ndr_pull_array_size($ndr, &$varname->$struct->{SURROUNDING_ELEMENT}->{NAME}));"); } - $self->pidl("NDR_CHECK(ndr_pull_align(ndr, $struct->{ALIGN}));"); + $self->pidl("NDR_CHECK(ndr_pull_align($ndr, $struct->{ALIGN}));"); if (defined($struct->{PROPERTIES}{relative_base})) { # set the current offset as base for relative pointers # and store it based on the toplevel struct/union - $self->pidl("NDR_CHECK(ndr_pull_setup_relative_base_offset1(ndr, $varname, ndr->offset));"); + $self->pidl("NDR_CHECK(ndr_pull_setup_relative_base_offset1($ndr, $varname, $ndr->offset));"); } - $self->ParseElementPull($_, "ndr", $env, 1, 0) foreach (@{$struct->{ELEMENTS}}); + $self->ParseElementPull($_, $ndr, $env, 1, 0) foreach (@{$struct->{ELEMENTS}}); $self->add_deferred(); } -sub ParseStructPullDeferred($$$$) +sub ParseStructPullDeferred($$$$$) { - my ($self,$struct,$varname,$env) = @_; + my ($self,$struct,$ndr,$varname,$env) = @_; if (defined($struct->{PROPERTIES}{relative_base})) { # retrieve the current offset as base for relative pointers # based on the toplevel struct/union - $self->pidl("NDR_CHECK(ndr_pull_setup_relative_base_offset2(ndr, $varname));"); + $self->pidl("NDR_CHECK(ndr_pull_setup_relative_base_offset2($ndr, $varname));"); } foreach my $e (@{$struct->{ELEMENTS}}) { - $self->ParseElementPull($e, "ndr", $env, 0, 1); + $self->ParseElementPull($e, $ndr, $env, 0, 1); } $self->add_deferred(); @@ -1513,9 +1517,9 @@ sub ParseStructPullDeferred($$$$) ##################################################################### # parse a struct - pull side -sub ParseStructPull($$$) +sub ParseStructPull($$$$) { - my($self,$struct,$varname) = @_; + my($self,$struct,$ndr,$varname) = @_; return unless defined $struct->{ELEMENTS}; @@ -1526,22 +1530,22 @@ sub ParseStructPull($$$) $self->DeclareMemCtxVariables($e); } - $self->start_flags($struct); + $self->start_flags($struct, $ndr); my $env = GenerateStructEnv($struct, $varname); $self->pidl("if (ndr_flags & NDR_SCALARS) {"); $self->indent; - $self->ParseStructPullPrimitives($struct,$varname,$env); + $self->ParseStructPullPrimitives($struct,$ndr,$varname,$env); $self->deindent; $self->pidl("}"); $self->pidl("if (ndr_flags & NDR_BUFFERS) {"); $self->indent; - $self->ParseStructPullDeferred($struct,$varname,$env); + $self->ParseStructPullDeferred($struct,$ndr,$varname,$env); $self->deindent; $self->pidl("}"); - $self->end_flags($struct); + $self->end_flags($struct, $ndr); } ##################################################################### @@ -1592,16 +1596,16 @@ sub ParseUnionNdrSize($$$) $self->pidl("return ndr_size_union($varname, flags, level, (ndr_push_flags_fn_t)ndr_push_$name);"); } -sub ParseUnionPushPrimitives($$$) +sub ParseUnionPushPrimitives($$$$) { - my ($self, $e, $varname) = @_; + my ($self, $e, $ndr ,$varname) = @_; my $have_default = 0; - $self->pidl("int level = ndr_push_get_switch_value(ndr, $varname);"); + $self->pidl("int level = ndr_push_get_switch_value($ndr, $varname);"); if (defined($e->{SWITCH_TYPE})) { - $self->pidl("NDR_CHECK(ndr_push_$e->{SWITCH_TYPE}(ndr, NDR_SCALARS, level));"); + $self->pidl("NDR_CHECK(ndr_push_$e->{SWITCH_TYPE}($ndr, NDR_SCALARS, level));"); } $self->pidl("switch (level) {"); @@ -1615,13 +1619,13 @@ sub ParseUnionPushPrimitives($$$) if ($el->{TYPE} ne "EMPTY") { $self->indent; if (defined($e->{PROPERTIES}{relative_base})) { - $self->pidl("NDR_CHECK(ndr_push_align(ndr, $el->{ALIGN}));"); + $self->pidl("NDR_CHECK(ndr_push_align($ndr, $el->{ALIGN}));"); # set the current offset as base for relative pointers # and store it based on the toplevel struct/union - $self->pidl("NDR_CHECK(ndr_push_setup_relative_base_offset1(ndr, $varname, ndr->offset));"); + $self->pidl("NDR_CHECK(ndr_push_setup_relative_base_offset1($ndr, $varname, $ndr->offset));"); } $self->DeclareArrayVariables($el); - $self->ParseElementPush($el, "ndr", {$el->{NAME} => "$varname->$el->{NAME}"}, 1, 0); + $self->ParseElementPush($el, $ndr, {$el->{NAME} => "$varname->$el->{NAME}"}, 1, 0); $self->deindent; } $self->pidl("break; }"); @@ -1629,23 +1633,23 @@ sub ParseUnionPushPrimitives($$$) } if (! $have_default) { $self->pidl("default:"); - $self->pidl("\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);"); + $self->pidl("\treturn ndr_push_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);"); } $self->deindent; $self->pidl("}"); } -sub ParseUnionPushDeferred($$$) +sub ParseUnionPushDeferred($$$$) { - my ($self,$e,$varname) = @_; + my ($self,$e,$ndr,$varname) = @_; my $have_default = 0; - $self->pidl("int level = ndr_push_get_switch_value(ndr, $varname);"); + $self->pidl("int level = ndr_push_get_switch_value($ndr, $varname);"); if (defined($e->{PROPERTIES}{relative_base})) { # retrieve the current offset as base for relative pointers # based on the toplevel struct/union - $self->pidl("NDR_CHECK(ndr_push_setup_relative_base_offset2(ndr, $varname));"); + $self->pidl("NDR_CHECK(ndr_push_setup_relative_base_offset2($ndr, $varname));"); } $self->pidl("switch (level) {"); $self->indent; @@ -1657,7 +1661,7 @@ sub ParseUnionPushDeferred($$$) $self->pidl("$el->{CASE}:"); if ($el->{TYPE} ne "EMPTY") { $self->indent; - $self->ParseElementPush($el, "ndr", {$el->{NAME} => "$varname->$el->{NAME}"}, 0, 1); + $self->ParseElementPush($el, $ndr, {$el->{NAME} => "$varname->$el->{NAME}"}, 0, 1); $self->deindent; } $self->pidl("break;"); @@ -1665,7 +1669,7 @@ sub ParseUnionPushDeferred($$$) } if (! $have_default) { $self->pidl("default:"); - $self->pidl("\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);"); + $self->pidl("\treturn ndr_push_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);"); } $self->deindent; $self->pidl("}"); @@ -1673,31 +1677,31 @@ sub ParseUnionPushDeferred($$$) ##################################################################### # parse a union - push side -sub ParseUnionPush($$$) +sub ParseUnionPush($$$$) { - my ($self,$e,$varname) = @_; + my ($self,$e,$ndr,$varname) = @_; my $have_default = 0; - $self->start_flags($e); + $self->start_flags($e, $ndr); $self->pidl("if (ndr_flags & NDR_SCALARS) {"); $self->indent; - $self->ParseUnionPushPrimitives($e, $varname); + $self->ParseUnionPushPrimitives($e, $ndr, $varname); $self->deindent; $self->pidl("}"); $self->pidl("if (ndr_flags & NDR_BUFFERS) {"); $self->indent; - $self->ParseUnionPushDeferred($e, $varname); + $self->ParseUnionPushDeferred($e, $ndr, $varname); $self->deindent; $self->pidl("}"); - $self->end_flags($e); + $self->end_flags($e, $ndr); } ##################################################################### # print a union -sub ParseUnionPrint($$$$) +sub ParseUnionPrint($$$$$) { - my ($self,$e,$name,$varname) = @_; + my ($self,$e,$ndr,$name,$varname) = @_; my $have_default = 0; $self->pidl("int level;"); @@ -1705,11 +1709,11 @@ sub ParseUnionPrint($$$$) $self->DeclareArrayVariables($el); } - $self->start_flags($e); + $self->start_flags($e, $ndr); - $self->pidl("level = ndr_print_get_switch_value(ndr, $varname);"); + $self->pidl("level = ndr_print_get_switch_value($ndr, $varname);"); - $self->pidl("ndr_print_union(ndr, name, level, \"$name\");"); + $self->pidl("ndr_print_union($ndr, name, level, \"$name\");"); $self->pidl("switch (level) {"); $self->indent; @@ -1720,7 +1724,7 @@ sub ParseUnionPrint($$$$) $self->pidl("$el->{CASE}:"); if ($el->{TYPE} ne "EMPTY") { $self->indent; - $self->ParseElementPrint($el, "$varname->$el->{NAME}", {}); + $self->ParseElementPrint($el, $ndr, "$varname->$el->{NAME}", {}); $self->deindent; } $self->pidl("break;"); @@ -1728,23 +1732,23 @@ sub ParseUnionPrint($$$$) } if (! $have_default) { $self->pidl("default:"); - $self->pidl("\tndr_print_bad_level(ndr, name, level);"); + $self->pidl("\tndr_print_bad_level($ndr, name, level);"); } $self->deindent; $self->pidl("}"); - $self->end_flags($e); + $self->end_flags($e, $ndr); } -sub ParseUnionPullPrimitives($$$$) +sub ParseUnionPullPrimitives($$$$$) { - my ($self,$e,$varname,$switch_type) = @_; + my ($self,$e,$ndr,$varname,$switch_type) = @_; my $have_default = 0; if (defined($switch_type)) { - $self->pidl("NDR_CHECK(ndr_pull_$switch_type(ndr, NDR_SCALARS, &_level));"); + $self->pidl("NDR_CHECK(ndr_pull_$switch_type($ndr, NDR_SCALARS, &_level));"); $self->pidl("if (_level != level) {"); - $self->pidl("\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u for $varname\", _level);"); + $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u for $varname\", _level);"); $self->pidl("}"); } @@ -1761,12 +1765,12 @@ sub ParseUnionPullPrimitives($$$$) $self->DeclarePtrVariables($el); $self->DeclareArrayVariables($el); if (defined($e->{PROPERTIES}{relative_base})) { - $self->pidl("NDR_CHECK(ndr_pull_align(ndr, $el->{ALIGN}));"); + $self->pidl("NDR_CHECK(ndr_pull_align($ndr, $el->{ALIGN}));"); # set the current offset as base for relative pointers # and store it based on the toplevel struct/union - $self->pidl("NDR_CHECK(ndr_pull_setup_relative_base_offset1(ndr, $varname, ndr->offset));"); + $self->pidl("NDR_CHECK(ndr_pull_setup_relative_base_offset1($ndr, $varname, $ndr->offset));"); } - $self->ParseElementPull($el, "ndr", {$el->{NAME} => "$varname->$el->{NAME}"}, 1, 0); + $self->ParseElementPull($el, $ndr, {$el->{NAME} => "$varname->$el->{NAME}"}, 1, 0); $self->deindent; } $self->pidl("break; }"); @@ -1774,21 +1778,21 @@ sub ParseUnionPullPrimitives($$$$) } if (! $have_default) { $self->pidl("default:"); - $self->pidl("\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);"); + $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);"); } $self->deindent; $self->pidl("}"); } -sub ParseUnionPullDeferred($$$) +sub ParseUnionPullDeferred($$$$) { - my ($self,$e,$varname) = @_; + my ($self,$e,$ndr,$varname) = @_; my $have_default = 0; if (defined($e->{PROPERTIES}{relative_base})) { # retrieve the current offset as base for relative pointers # based on the toplevel struct/union - $self->pidl("NDR_CHECK(ndr_pull_setup_relative_base_offset2(ndr, $varname));"); + $self->pidl("NDR_CHECK(ndr_pull_setup_relative_base_offset2($ndr, $varname));"); } $self->pidl("switch (level) {"); $self->indent; @@ -1800,7 +1804,7 @@ sub ParseUnionPullDeferred($$$) $self->pidl("$el->{CASE}:"); if ($el->{TYPE} ne "EMPTY") { $self->indent; - $self->ParseElementPull($el, "ndr", {$el->{NAME} => "$varname->$el->{NAME}"}, 0, 1); + $self->ParseElementPull($el, $ndr, {$el->{NAME} => "$varname->$el->{NAME}"}, 0, 1); $self->deindent; } $self->pidl("break;"); @@ -1808,7 +1812,7 @@ sub ParseUnionPullDeferred($$$) } if (! $have_default) { $self->pidl("default:"); - $self->pidl("\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);"); + $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);"); } $self->deindent; $self->pidl("}"); @@ -1818,9 +1822,9 @@ sub ParseUnionPullDeferred($$$) ##################################################################### # parse a union - pull side -sub ParseUnionPull($$$) +sub ParseUnionPull($$$$) { - my ($self,$e,$varname) = @_; + my ($self,$e,$ndr,$varname) = @_; my $switch_type = $e->{SWITCH_TYPE}; $self->pidl("int level;"); @@ -1839,25 +1843,25 @@ sub ParseUnionPull($$$) $double_cases{"$el->{NAME}"} = 1; } - $self->start_flags($e); + $self->start_flags($e, $ndr); - $self->pidl("level = ndr_pull_get_switch_value(ndr, $varname);"); + $self->pidl("level = ndr_pull_get_switch_value($ndr, $varname);"); $self->pidl("if (ndr_flags & NDR_SCALARS) {"); $self->indent; - $self->ParseUnionPullPrimitives($e,$varname,$switch_type); + $self->ParseUnionPullPrimitives($e,$ndr,$varname,$switch_type); $self->deindent; $self->pidl("}"); $self->pidl("if (ndr_flags & NDR_BUFFERS) {"); $self->indent; - $self->ParseUnionPullDeferred($e,$varname); + $self->ParseUnionPullDeferred($e,$ndr,$varname); $self->deindent; $self->pidl("}"); $self->add_deferred(); - $self->end_flags($e); + $self->end_flags($e, $ndr); } sub DeclUnion($$$$) @@ -1883,29 +1887,37 @@ $typefamily{UNION} = { ##################################################################### # parse a typedef - push side -sub ParseTypedefPush($$$) +sub ParseTypedefPush($$$$) { - my($self,$e,$varname) = @_; + my($self,$e,$ndr,$varname) = @_; + + my $env; + + $env->{$e->{NAME}} = $varname; - $typefamily{$e->{DATA}->{TYPE}}->{PUSH_FN_BODY}->($self, $e->{DATA}, $varname); + $self->ParseElementPushLevel($e, $e->{LEVELS}[0], $ndr, $varname, $env, 1, 1); } ##################################################################### # parse a typedef - pull side -sub ParseTypedefPull($$$) +sub ParseTypedefPull($$$$) { - my($self,$e,$varname) = @_; + my($self,$e,$ndr,$varname) = @_; - $typefamily{$e->{DATA}->{TYPE}}->{PULL_FN_BODY}->($self, $e->{DATA}, $varname); + my $env; + + $env->{$e->{NAME}} = $varname; + + $self->ParseElementPullLevel($e, $e->{LEVELS}[0], $ndr, $varname, $env, 1, 1); } ##################################################################### # parse a typedef - print side -sub ParseTypedefPrint($$$$) +sub ParseTypedefPrint($$$$$) { - my($self,$e,$name,$varname) = @_; + my($self,$e,$ndr,$name,$varname) = @_; - $typefamily{$e->{DATA}->{TYPE}}->{PRINT_FN_BODY}->($self, $e->{DATA}, $name, $varname); + $typefamily{$e->{DATA}->{TYPE}}->{PRINT_FN_BODY}->($self, $e->{DATA}, $ndr, $name, $varname); } ##################################################################### @@ -1944,12 +1956,13 @@ $typefamily{TYPEDEF} = { sub ParseFunctionPrint($$) { my($self, $fn) = @_; + my $ndr = "ndr"; - $self->pidl_hdr("void ndr_print_$fn->{NAME}(struct ndr_print *ndr, const char *name, int flags, const struct $fn->{NAME} *r);"); + $self->pidl_hdr("void ndr_print_$fn->{NAME}(struct ndr_print *$ndr, const char *name, int flags, const struct $fn->{NAME} *r);"); return if has_property($fn, "noprint"); - $self->pidl("_PUBLIC_ void ndr_print_$fn->{NAME}(struct ndr_print *ndr, const char *name, int flags, const struct $fn->{NAME} *r)"); + $self->pidl("_PUBLIC_ void ndr_print_$fn->{NAME}(struct ndr_print *$ndr, const char *name, int flags, const struct $fn->{NAME} *r)"); $self->pidl("{"); $self->indent; @@ -1957,48 +1970,48 @@ sub ParseFunctionPrint($$) $self->DeclareArrayVariables($e); } - $self->pidl("ndr_print_struct(ndr, name, \"$fn->{NAME}\");"); - $self->pidl("ndr->depth++;"); + $self->pidl("ndr_print_struct($ndr, name, \"$fn->{NAME}\");"); + $self->pidl("$ndr->depth++;"); $self->pidl("if (flags & NDR_SET_VALUES) {"); - $self->pidl("\tndr->flags |= LIBNDR_PRINT_SET_VALUES;"); + $self->pidl("\t$ndr->flags |= LIBNDR_PRINT_SET_VALUES;"); $self->pidl("}"); $self->pidl("if (flags & NDR_IN) {"); $self->indent; - $self->pidl("ndr_print_struct(ndr, \"in\", \"$fn->{NAME}\");"); - $self->pidl("ndr->depth++;"); + $self->pidl("ndr_print_struct($ndr, \"in\", \"$fn->{NAME}\");"); + $self->pidl("$ndr->depth++;"); my $env = GenerateFunctionInEnv($fn); foreach my $e (@{$fn->{ELEMENTS}}) { if (grep(/in/,@{$e->{DIRECTION}})) { - $self->ParseElementPrint($e, $env->{$e->{NAME}}, $env); + $self->ParseElementPrint($e, $ndr, $env->{$e->{NAME}}, $env); } } - $self->pidl("ndr->depth--;"); + $self->pidl("$ndr->depth--;"); $self->deindent; $self->pidl("}"); $self->pidl("if (flags & NDR_OUT) {"); $self->indent; - $self->pidl("ndr_print_struct(ndr, \"out\", \"$fn->{NAME}\");"); - $self->pidl("ndr->depth++;"); + $self->pidl("ndr_print_struct($ndr, \"out\", \"$fn->{NAME}\");"); + $self->pidl("$ndr->depth++;"); $env = GenerateFunctionOutEnv($fn); foreach my $e (@{$fn->{ELEMENTS}}) { if (grep(/out/,@{$e->{DIRECTION}})) { - $self->ParseElementPrint($e, $env->{$e->{NAME}}, $env); + $self->ParseElementPrint($e, $ndr, $env->{$e->{NAME}}, $env); } } if ($fn->{RETURN_TYPE}) { - $self->pidl("ndr_print_$fn->{RETURN_TYPE}(ndr, \"result\", r->out.result);"); + $self->pidl("ndr_print_$fn->{RETURN_TYPE}($ndr, \"result\", r->out.result);"); } - $self->pidl("ndr->depth--;"); + $self->pidl("$ndr->depth--;"); $self->deindent; $self->pidl("}"); - $self->pidl("ndr->depth--;"); + $self->pidl("$ndr->depth--;"); $self->deindent; $self->pidl("}"); $self->pidl(""); @@ -2009,8 +2022,9 @@ sub ParseFunctionPrint($$) sub ParseFunctionPush($$) { my($self, $fn) = @_; + my $ndr = "ndr"; - $self->fn_declare("push", $fn, "enum ndr_err_code ndr_push_$fn->{NAME}(struct ndr_push *ndr, int flags, const struct $fn->{NAME} *r)") or return; + $self->fn_declare("push", $fn, "enum ndr_err_code ndr_push_$fn->{NAME}(struct ndr_push *$ndr, int flags, const struct $fn->{NAME} *r)") or return; return if has_property($fn, "nopush"); @@ -2030,7 +2044,7 @@ sub ParseFunctionPush($$) foreach my $e (@{$fn->{ELEMENTS}}) { if (grep(/in/,@{$e->{DIRECTION}})) { - $self->ParseElementPush($e, "ndr", $env, 1, 1); + $self->ParseElementPush($e, $ndr, $env, 1, 1); } } @@ -2043,12 +2057,12 @@ sub ParseFunctionPush($$) $env = GenerateFunctionOutEnv($fn); foreach my $e (@{$fn->{ELEMENTS}}) { if (grep(/out/,@{$e->{DIRECTION}})) { - $self->ParseElementPush($e, "ndr", $env, 1, 1); + $self->ParseElementPush($e, $ndr, $env, 1, 1); } } if ($fn->{RETURN_TYPE}) { - $self->pidl("NDR_CHECK(ndr_push_$fn->{RETURN_TYPE}(ndr, NDR_SCALARS, r->out.result));"); + $self->pidl("NDR_CHECK(ndr_push_$fn->{RETURN_TYPE}($ndr, NDR_SCALARS, r->out.result));"); } $self->deindent; @@ -2068,7 +2082,7 @@ sub AllocateArrayLevel($$$$$$) $pl->{TYPE} eq "POINTER" and $pl->{POINTER_TYPE} eq "ref" and not $l->{IS_ZERO_TERMINATED}) { - $self->pidl("if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {"); + $self->pidl("if ($ndr->flags & LIBNDR_FLAG_REF_ALLOC) {"); $self->pidl("\tNDR_PULL_ALLOC_N($ndr, $var, $size);"); $self->pidl("}"); if (grep(/in/,@{$e->{DIRECTION}}) and @@ -2086,9 +2100,10 @@ sub AllocateArrayLevel($$$$$$) sub ParseFunctionPull($$) { my($self,$fn) = @_; + my $ndr = "ndr"; # pull function args - $self->fn_declare("pull", $fn, "enum ndr_err_code ndr_pull_$fn->{NAME}(struct ndr_pull *ndr, int flags, struct $fn->{NAME} *r)") or return; + $self->fn_declare("pull", $fn, "enum ndr_err_code ndr_pull_$fn->{NAME}(struct ndr_pull *$ndr, int flags, struct $fn->{NAME} *r)") or return; $self->pidl("{"); $self->indent; @@ -2125,7 +2140,7 @@ sub ParseFunctionPull($$) foreach my $e (@{$fn->{ELEMENTS}}) { next unless (grep(/in/, @{$e->{DIRECTION}})); - $self->ParseElementPull($e, "ndr", $env, 1, 1); + $self->ParseElementPull($e, $ndr, $env, 1, 1); } # allocate the "simple" out ref variables. FIXME: Shouldn't this have it's @@ -2143,9 +2158,9 @@ sub ParseFunctionPull($$) if ($e->{LEVELS}[1]->{TYPE} eq "ARRAY") { my $size = ParseExprExt($e->{LEVELS}[1]->{SIZE_IS}, $env, $e->{ORIGINAL}, check_null_pointer($e, $env, sub { $self->pidl(shift); }, - "return ndr_pull_error(ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for size_is()\");"), + "return ndr_pull_error($ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for size_is()\");"), check_fully_dereferenced($e, $env)); - $self->pidl("NDR_PULL_ALLOC_N(ndr, r->out.$e->{NAME}, $size);"); + $self->pidl("NDR_PULL_ALLOC_N($ndr, r->out.$e->{NAME}, $size);"); if (grep(/in/, @{$e->{DIRECTION}})) { $self->pidl("memcpy(r->out.$e->{NAME}, r->in.$e->{NAME}, ($size) * sizeof(*r->in.$e->{NAME}));"); @@ -2153,7 +2168,7 @@ sub ParseFunctionPull($$) $self->pidl("memset(r->out.$e->{NAME}, 0, ($size) * sizeof(*r->out.$e->{NAME}));"); } } else { - $self->pidl("NDR_PULL_ALLOC(ndr, r->out.$e->{NAME});"); + $self->pidl("NDR_PULL_ALLOC($ndr, r->out.$e->{NAME});"); if (grep(/in/, @{$e->{DIRECTION}})) { $self->pidl("*r->out.$e->{NAME} = *r->in.$e->{NAME};"); @@ -2173,11 +2188,11 @@ sub ParseFunctionPull($$) $env = GenerateFunctionOutEnv($fn); foreach my $e (@{$fn->{ELEMENTS}}) { next unless grep(/out/, @{$e->{DIRECTION}}); - $self->ParseElementPull($e, "ndr", $env, 1, 1); + $self->ParseElementPull($e, $ndr, $env, 1, 1); } if ($fn->{RETURN_TYPE}) { - $self->pidl("NDR_CHECK(ndr_pull_$fn->{RETURN_TYPE}(ndr, NDR_SCALARS, &r->out.result));"); + $self->pidl("NDR_CHECK(ndr_pull_$fn->{RETURN_TYPE}($ndr, NDR_SCALARS, &r->out.result));"); } $self->add_deferred(); @@ -2364,81 +2379,86 @@ sub HeaderInterface($$$) } -sub ParseTypePush($$$$$) +sub ParseTypePush($$$$$$) { - my ($self,$e,$varname, $primitives, $deferred) = @_; + my ($self,$e, $ndr, $varname, $primitives, $deferred) = @_; # save the old relative_base_offset - $self->pidl("uint32_t _save_relative_base_offset = ndr_push_get_relative_base_offset(ndr);") if defined(has_property($e, "relative_base")); - $typefamily{$e->{TYPE}}->{PUSH_FN_BODY}->($self, $e, $varname); + $self->pidl("uint32_t _save_relative_base_offset = ndr_push_get_relative_base_offset($ndr);") if defined(has_property($e, "relative_base")); + $typefamily{$e->{TYPE}}->{PUSH_FN_BODY}->($self, $e, $ndr, $varname); # restore the old relative_base_offset - $self->pidl("ndr_push_restore_relative_base_offset(ndr, _save_relative_base_offset);") if defined(has_property($e, "relative_base")); + $self->pidl("ndr_push_restore_relative_base_offset($ndr, _save_relative_base_offset);") if defined(has_property($e, "relative_base")); } sub ParseTypePushFunction($$$) { my ($self, $e, $varname) = @_; + my $ndr = "ndr"; my $args = $typefamily{$e->{TYPE}}->{DECL}->($e, "push", $e->{NAME}, $varname); - $self->fn_declare("push", $e, "enum ndr_err_code ".TypeFunctionName("ndr_push", $e)."(struct ndr_push *ndr, int ndr_flags, $args)") or return; + + $self->fn_declare("push", $e, "enum ndr_err_code ".TypeFunctionName("ndr_push", $e)."(struct ndr_push *$ndr, int ndr_flags, $args)") or return; $self->pidl("{"); $self->indent; - $self->ParseTypePush($e, $varname, 1, 1); + $self->ParseTypePush($e, $ndr, $varname, 1, 1); $self->pidl("return NDR_ERR_SUCCESS;"); $self->deindent; $self->pidl("}"); $self->pidl("");; } -sub ParseTypePull($$$$$) +sub ParseTypePull($$$$$$) { - my ($self, $e, $varname, $primitives, $deferred) = @_; + my ($self, $e, $ndr, $varname, $primitives, $deferred) = @_; # save the old relative_base_offset - $self->pidl("uint32_t _save_relative_base_offset = ndr_pull_get_relative_base_offset(ndr);") if defined(has_property($e, "relative_base")); - $typefamily{$e->{TYPE}}->{PULL_FN_BODY}->($self, $e, $varname); + $self->pidl("uint32_t _save_relative_base_offset = ndr_pull_get_relative_base_offset($ndr);") if defined(has_property($e, "relative_base")); + $typefamily{$e->{TYPE}}->{PULL_FN_BODY}->($self, $e, $ndr, $varname); # restore the old relative_base_offset - $self->pidl("ndr_pull_restore_relative_base_offset(ndr, _save_relative_base_offset);") if defined(has_property($e, "relative_base")); + $self->pidl("ndr_pull_restore_relative_base_offset($ndr, _save_relative_base_offset);") if defined(has_property($e, "relative_base")); } sub ParseTypePullFunction($$) { my ($self, $e, $varname) = @_; + my $ndr = "ndr"; my $args = $typefamily{$e->{TYPE}}->{DECL}->($e, "pull", $e->{NAME}, $varname); - $self->fn_declare("pull", $e, "enum ndr_err_code ".TypeFunctionName("ndr_pull", $e)."(struct ndr_pull *ndr, int ndr_flags, $args)") or return; + $self->fn_declare("pull", $e, "enum ndr_err_code ".TypeFunctionName("ndr_pull", $e)."(struct ndr_pull *$ndr, int ndr_flags, $args)") or return; $self->pidl("{"); $self->indent; - $self->ParseTypePull($e, $varname, 1, 1); + $self->ParseTypePull($e, $ndr, $varname, 1, 1); $self->pidl("return NDR_ERR_SUCCESS;"); $self->deindent; $self->pidl("}"); $self->pidl(""); } -sub ParseTypePrint($$$) +sub ParseTypePrint($$$$) { - my ($self, $e, $varname) = @_; + my ($self, $e, $ndr, $varname) = @_; - $typefamily{$e->{TYPE}}->{PRINT_FN_BODY}->($self, $e, $e->{NAME}, $varname); + $typefamily{$e->{TYPE}}->{PRINT_FN_BODY}->($self, $e, $ndr, $e->{NAME}, $varname); } sub ParseTypePrintFunction($$$) { my ($self, $e, $varname) = @_; + my $ndr = "ndr"; + my $args = $typefamily{$e->{TYPE}}->{DECL}->($e, "print", $e->{NAME}, $varname); $self->pidl_hdr("void ".TypeFunctionName("ndr_print", $e)."(struct ndr_print *ndr, const char *name, $args);"); return if (has_property($e, "noprint")); - $self->pidl("_PUBLIC_ void ".TypeFunctionName("ndr_print", $e)."(struct ndr_print *ndr, const char *name, $args)"); + $self->pidl("_PUBLIC_ void ".TypeFunctionName("ndr_print", $e)."(struct ndr_print *$ndr, const char *name, $args)"); $self->pidl("{"); $self->indent; - $self->ParseTypePrint($e, $varname); + $self->ParseTypePrint($e, $ndr, $varname); $self->deindent; $self->pidl("}"); $self->pidl(""); diff --git a/source4/pidl/tests/samba-ndr.pl b/source4/pidl/tests/samba-ndr.pl index 114ca01cfa..cdfe0514f1 100755 --- a/source4/pidl/tests/samba-ndr.pl +++ b/source4/pidl/tests/samba-ndr.pl @@ -220,7 +220,7 @@ $generator->ParseStructPush({ TYPE => "STRUCT", PROPERTIES => {}, ALIGN => 4, - ELEMENTS => [ ]}, "x"); + ELEMENTS => [ ]}, "ndr", "x"); is($generator->{res}, "if (ndr_flags & NDR_SCALARS) { NDR_CHECK(ndr_push_align(ndr, 4)); } @@ -243,7 +243,7 @@ $generator->ParseStructPush({ PROPERTIES => {}, ALIGN => 4, SURROUNDING_ELEMENT => $e, - ELEMENTS => [ $e ]}, "x"); + ELEMENTS => [ $e ]}, "ndr", "x"); is($generator->{res}, "if (ndr_flags & NDR_SCALARS) { NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_string_array_size(ndr, x->el1))); NDR_CHECK(ndr_push_align(ndr, 4)); @@ -262,20 +262,23 @@ is(TypeFunctionName("ndr_push", {TYPE => "STRUCT", NAME => "bar"}), "ndr_push_ST $generator = new Parse::Pidl::Samba4::NDR::Parser(); $generator->ParseElementPrint({ NAME => "x", TYPE => "rt", REPRESENTATION_TYPE => "rt", PROPERTIES => { noprint => 1}, - LEVELS => [ { TYPE => "DATA", DATA_TYPE => "rt"} ]}, "var", { "x" => "r->foobar" } ); + LEVELS => [ { TYPE => "DATA", DATA_TYPE => "rt"} ]}, + "ndr", "var", { "x" => "r->foobar" } ); is($generator->{res}, ""); $generator = new Parse::Pidl::Samba4::NDR::Parser(); $generator->ParseElementPrint({ NAME => "x", TYPE => "rt", REPRESENTATION_TYPE => "rt", PROPERTIES => {}, - LEVELS => [ { TYPE => "DATA", DATA_TYPE => "rt" }]}, "var", { "x" => "r->foobar" } ); + LEVELS => [ { TYPE => "DATA", DATA_TYPE => "rt" }]}, + "ndr", "var", { "x" => "r->foobar" } ); is($generator->{res}, "ndr_print_rt(ndr, \"x\", &var);\n"); # make sure that a print function for an element with value() set works $generator = new Parse::Pidl::Samba4::NDR::Parser(); $generator->ParseElementPrint({ NAME => "x", TYPE => "uint32", REPRESENTATION_TYPE => "uint32", PROPERTIES => { value => "23" }, - LEVELS => [ { TYPE => "DATA", DATA_TYPE => "uint32"} ]}, "var", { "x" => "r->foobar" } ); + LEVELS => [ { TYPE => "DATA", DATA_TYPE => "uint32"} ]}, + "ndr", "var", { "x" => "r->foobar" } ); is($generator->{res}, "ndr_print_uint32(ndr, \"x\", (ndr->flags & LIBNDR_PRINT_SET_VALUES)?23:var);\n"); $generator = new Parse::Pidl::Samba4::NDR::Parser(); diff --git a/source4/pidl/tests/samba3-cli.pl b/source4/pidl/tests/samba3-cli.pl index 80725d28cf..d762954159 100755 --- a/source4/pidl/tests/samba3-cli.pl +++ b/source4/pidl/tests/samba3-cli.pl @@ -44,7 +44,6 @@ is($x->{res}, status = cli_do_rpc_ndr(cli, mem_ctx, - PI_FOO, &ndr_table_foo, NDR_BAR, &r); @@ -89,7 +88,6 @@ is($x->{res}, status = cli_do_rpc_ndr(cli, mem_ctx, - PI_FOO, &ndr_table_foo, NDR_BAR, &r); diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c index a336ddb339..fa7b8d26f5 100644 --- a/source4/rpc_server/dcerpc_server.c +++ b/source4/rpc_server/dcerpc_server.c @@ -917,6 +917,7 @@ _PUBLIC_ NTSTATUS dcesrv_reply(struct dcesrv_call_state *call) DATA_BLOB stub; uint32_t total_length, chunk_size; struct dcesrv_connection_context *context = call->context; + size_t sig_size = 0; /* call the reply function */ status = context->iface->reply(call, call, call->r); @@ -948,7 +949,15 @@ _PUBLIC_ NTSTATUS dcesrv_reply(struct dcesrv_call_state *call) /* we can write a full max_recv_frag size, minus the dcerpc request header size */ - chunk_size = call->conn->cli_max_recv_frag - (DCERPC_MAX_SIGN_SIZE+DCERPC_REQUEST_LENGTH); + chunk_size = call->conn->cli_max_recv_frag; + chunk_size -= DCERPC_REQUEST_LENGTH; + if (call->conn->auth_state.gensec_security) { + chunk_size -= DCERPC_AUTH_TRAILER_LENGTH; + sig_size = gensec_sig_size(call->conn->auth_state.gensec_security, + call->conn->cli_max_recv_frag); + chunk_size -= sig_size; + chunk_size -= (chunk_size % 16); + } do { uint32_t length; @@ -978,7 +987,7 @@ _PUBLIC_ NTSTATUS dcesrv_reply(struct dcesrv_call_state *call) pkt.u.response.stub_and_verifier.data = stub.data; pkt.u.response.stub_and_verifier.length = length; - if (!dcesrv_auth_response(call, &rep->blob, &pkt)) { + if (!dcesrv_auth_response(call, &rep->blob, sig_size, &pkt)) { return dcesrv_fault(call, DCERPC_FAULT_OTHER); } diff --git a/source4/rpc_server/dcesrv_auth.c b/source4/rpc_server/dcesrv_auth.c index 64f42eea25..0aad3775d0 100644 --- a/source4/rpc_server/dcesrv_auth.c +++ b/source4/rpc_server/dcesrv_auth.c @@ -398,7 +398,8 @@ bool dcesrv_auth_request(struct dcesrv_call_state *call, DATA_BLOB *full_packet) push a signed or sealed dcerpc request packet into a blob */ bool dcesrv_auth_response(struct dcesrv_call_state *call, - DATA_BLOB *blob, struct ncacn_packet *pkt) + DATA_BLOB *blob, size_t sig_size, + struct ncacn_packet *pkt) { struct dcesrv_connection *dce_conn = call->conn; NTSTATUS status; @@ -445,9 +446,7 @@ bool dcesrv_auth_response(struct dcesrv_call_state *call, * GENSEC mech does AEAD signing of the packet * headers */ dce_conn->auth_state.auth_info->credentials - = data_blob_talloc(call, NULL, - gensec_sig_size(dce_conn->auth_state.gensec_security, - payload_length)); + = data_blob_talloc(call, NULL, sig_size); data_blob_clear(&dce_conn->auth_state.auth_info->credentials); } diff --git a/source4/rpc_server/lsa/dcesrv_lsa.c b/source4/rpc_server/lsa/dcesrv_lsa.c index f02e2325a0..f67b5dee10 100644 --- a/source4/rpc_server/lsa/dcesrv_lsa.c +++ b/source4/rpc_server/lsa/dcesrv_lsa.c @@ -23,6 +23,8 @@ #include "rpc_server/lsa/lsa.h" #include "util/util_ldb.h" #include "libcli/ldap/ldap_ndr.h" +#include "system/kerberos.h" +#include "auth/kerberos/kerberos.h" /* this type allows us to distinguish handle types @@ -95,6 +97,16 @@ static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct lsa_Delete *r) { + return NT_STATUS_NOT_SUPPORTED; +} + + +/* + lsa_DeleteObject +*/ +static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct lsa_DeleteObject *r) +{ struct dcesrv_handle *h; int ret; @@ -121,6 +133,8 @@ static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX return NT_STATUS_INVALID_HANDLE; } + ZERO_STRUCTP(r->out.handle); + return NT_STATUS_OK; } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) { struct lsa_trusted_domain_state *trusted_domain_state = h->data; @@ -131,6 +145,8 @@ static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX return NT_STATUS_INVALID_HANDLE; } + ZERO_STRUCTP(r->out.handle); + return NT_STATUS_OK; } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) { struct lsa_RightSet *rights; @@ -167,6 +183,8 @@ static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX if (!NT_STATUS_IS_OK(status)) { return status; } + + ZERO_STRUCTP(r->out.handle); } return NT_STATUS_INVALID_HANDLE; @@ -861,7 +879,7 @@ static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_cal { NTSTATUS status; struct lsa_OpenTrustedDomain open; - struct lsa_Delete delete; + struct lsa_DeleteObject delete; struct dcesrv_handle *h; open.in.handle = r->in.handle; @@ -880,7 +898,8 @@ static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_cal talloc_steal(mem_ctx, h); delete.in.handle = open.out.trustdom_handle; - status = dcesrv_lsa_Delete(dce_call, mem_ctx, &delete); + delete.out.handle = open.out.trustdom_handle; + status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &delete); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -924,6 +943,7 @@ static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_ "trustDirection", "trustType", "trustAttributes", + "msDs-supportedEncryptionTypes", NULL }; @@ -967,12 +987,19 @@ static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_ ZERO_STRUCT(r->out.info->full_info); return fill_trust_domain_ex(mem_ctx, msg, &r->out.info->full_info.info_ex); - case LSA_TRUSTED_DOMAIN_INFO_INFO_ALL: - ZERO_STRUCT(r->out.info->info_all); - return fill_trust_domain_ex(mem_ctx, msg, &r->out.info->info_all.info_ex); + case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL: + ZERO_STRUCT(r->out.info->info2_internal); + r->out.info->info2_internal.posix_offset.posix_offset + = samdb_result_uint(msg, "posixOffset", 0); + return fill_trust_domain_ex(mem_ctx, msg, &r->out.info->info2_internal.info_ex); + + case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRTYPION_TYPES: + r->out.info->enc_types.enc_types + = samdb_result_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5); + break; - case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS_INFO: - case LSA_TRUSTED_DOMAIN_INFO_11: + case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS: + case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL: /* oops, we don't want to return the info after all */ talloc_free(r->out.info); r->out.info = NULL; @@ -1986,22 +2013,14 @@ static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_ } if (!r->in.new_val) { - /* This behaviour varies depending of if this is a local, or a global secret... */ - if (secret_state->global) { - /* set old value mtime */ - if (samdb_msg_add_uint64(secret_state->sam_ldb, - mem_ctx, msg, "lastSetTime", nt_now) != 0) { - return NT_STATUS_NO_MEMORY; - } - } else { - if (samdb_msg_add_delete(secret_state->sam_ldb, - mem_ctx, msg, "currentValue")) { - return NT_STATUS_NO_MEMORY; - } - if (samdb_msg_add_delete(secret_state->sam_ldb, - mem_ctx, msg, "lastSetTime")) { - return NT_STATUS_NO_MEMORY; - } + /* set old value mtime */ + if (samdb_msg_add_uint64(secret_state->sam_ldb, + mem_ctx, msg, "lastSetTime", nt_now) != 0) { + return NT_STATUS_NO_MEMORY; + } + if (samdb_msg_add_delete(secret_state->sam_ldb, + mem_ctx, msg, "currentValue")) { + return NT_STATUS_NO_MEMORY; } } } @@ -2311,16 +2330,6 @@ static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_c /* - lsa_DeleteObject -*/ -static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, - struct lsa_DeleteObject *r) -{ - DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); -} - - -/* lsa_EnumAccountsWithUserRight */ static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call, @@ -2495,7 +2504,42 @@ static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state TALLOC_CTX *mem_ctx, struct lsa_QueryDomainInformationPolicy *r) { - DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); + r->out.info = talloc(mem_ctx, union lsa_DomainInformationPolicy); + if (!r->out.info) { + return NT_STATUS_NO_MEMORY; + } + + switch (r->in.level) { + case LSA_DOMAIN_INFO_POLICY_EFS: + talloc_free(r->out.info); + r->out.info = NULL; + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + case LSA_DOMAIN_INFO_POLICY_KERBEROS: + { + struct lsa_DomainInfoKerberos *k = &r->out.info->kerberos_info; + struct smb_krb5_context *smb_krb5_context; + int ret = smb_krb5_init_context(mem_ctx, + dce_call->event_ctx, + dce_call->conn->dce_ctx->lp_ctx, + &smb_krb5_context); + if (ret != 0) { + talloc_free(r->out.info); + r->out.info = NULL; + return NT_STATUS_INTERNAL_ERROR; + } + k->enforce_restrictions = 0; /* FIXME, details missing from MS-LSAD 2.2.53 */ + k->service_tkt_lifetime = 0; /* Need to find somewhere to store this, and query in KDC too */ + k->user_tkt_lifetime = 0; /* Need to find somewhere to store this, and query in KDC too */ + k->user_tkt_renewaltime = 0; /* Need to find somewhere to store this, and query in KDC too */ + k->clock_skew = krb5_get_max_time_skew(smb_krb5_context->krb5_context); + talloc_free(smb_krb5_context); + return NT_STATUS_OK; + } + default: + talloc_free(r->out.info); + r->out.info = NULL; + return NT_STATUS_INVALID_INFO_CLASS; + } } /* diff --git a/source4/scripting/python/samba/provision.py b/source4/scripting/python/samba/provision.py index 4f7fbfc6e6..9c2a208460 100644 --- a/source4/scripting/python/samba/provision.py +++ b/source4/scripting/python/samba/provision.py @@ -76,7 +76,9 @@ class ProvisionPaths(object): self.memberofconf = None self.fedoradsinf = None self.fedoradspartitions = None - + self.olmmron = None + self.olmmrserveridsconf = None + self.olmmrsyncreplconf = None class ProvisionNames(object): def __init__(self): @@ -241,9 +243,13 @@ def provision_paths_from_lp(lp, dnsdomain): paths.memberofconf = os.path.join(paths.ldapdir, "memberof.conf") paths.fedoradsinf = os.path.join(paths.ldapdir, - "fedorads.inf") + "fedorads.inf") paths.fedoradspartitions = os.path.join(paths.ldapdir, "fedorads-partitions.ldif") + paths.olmmrserveridsconf = os.path.join(paths.ldapdir, + "mmr_serverids.conf") + paths.olmmrsyncreplconf = os.path.join(paths.ldapdir, + "mmr_syncrepl.conf") paths.hklm = "hklm.ldb" paths.hkcr = "hkcr.ldb" paths.hkcu = "hkcu.ldb" @@ -331,7 +337,7 @@ def guess_names(lp=None, hostname=None, domain=None, dnsdomain=None, serverrole= names.hostname = hostname names.sitename = sitename names.serverdn = "CN=%s,CN=Servers,CN=%s,CN=Sites,%s" % (netbiosname, sitename, configdn) - + return names @@ -617,7 +623,17 @@ def setup_templatesdb(path, setup_path, session_info, credentials, lp): """ templates_ldb = SamDB(path, session_info=session_info, credentials=credentials, lp=lp) - templates_ldb.erase() + # Wipes the database + try: + templates_ldb.erase() + except: + os.unlink(path) + + templates_ldb.load_ldif_file_add(setup_path("provision_templates_init.ldif")) + + templates_ldb = SamDB(path, session_info=session_info, + credentials=credentials, lp=lp) + templates_ldb.load_ldif_file_add(setup_path("provision_templates.ldif")) @@ -729,12 +745,6 @@ def setup_samdb(path, setup_path, session_info, credentials, lp, samdb = SamDB(path, session_info=session_info, credentials=credentials, lp=lp) - if fill == FILL_DRS: - # We want to finish here, but setup the index before we do so - message("Setting up sam.ldb index") - samdb.load_ldif_file_add(setup_path("provision_index.ldif")) - return samdb - message("Pre-loading the Samba 4 and AD schema") samdb.set_domain_sid(domainsid) if serverrole == "domain controller": @@ -870,9 +880,6 @@ def setup_samdb(path, setup_path, session_info, credentials, lp, domainsid=domainsid, policyguid=policyguid, setup_path=setup_path) - #We want to setup the index last, as adds are faster unindexed - message("Setting up sam.ldb index") - samdb.load_ldif_file_add(setup_path("provision_index.ldif")) except: samdb.transaction_cancel() raise @@ -1141,7 +1148,8 @@ def provision_backend(setup_dir=None, message=None, smbconf=None, targetdir=None, realm=None, rootdn=None, domaindn=None, schemadn=None, configdn=None, domain=None, hostname=None, adminpass=None, root=None, serverrole=None, - ldap_backend_type=None, ldap_backend_port=None): + ldap_backend_type=None, ldap_backend_port=None, + ol_mmr_urls=None): def setup_path(file): return os.path.join(setup_dir, file) @@ -1255,7 +1263,50 @@ def provision_backend(setup_dir=None, message=None, refint_config = read_and_sub_file(setup_path("refint.conf"), { "LINK_ATTRS" : refint_attributes}) - + +# generate serverids, ldap-urls and syncrepl-blocks for mmr hosts + mmr_on_config = "" + mmr_serverids_config = "" + mmr_syncrepl_schema_config = "" + mmr_syncrepl_config_config = "" + mmr_syncrepl_user_config = "" + + if ol_mmr_urls is not None: + url_list=filter(None,ol_mmr_urls.split(' ')) + if (len(url_list) == 1): + url_list=filter(None,ol_mmr_urls.split(',')) + + + mmr_on_config = "MirrorMode On" + serverid=0 + for url in url_list: + serverid=serverid+1 + mmr_serverids_config += read_and_sub_file(setup_path("mmr_serverids.conf"), + { "SERVERID" : str(serverid), + "LDAPSERVER" : url }) + rid=serverid*10 + rid=rid+1 + mmr_syncrepl_schema_config += read_and_sub_file(setup_path("mmr_syncrepl.conf"), + { "RID" : str(rid), + "MMRDN": names.schemadn, + "LDAPSERVER" : url, + "MMR_PASSWORD": adminpass}) + + rid=rid+1 + mmr_syncrepl_config_config += read_and_sub_file(setup_path("mmr_syncrepl.conf"), + { "RID" : str(rid), + "MMRDN": names.configdn, + "LDAPSERVER" : url, + "MMR_PASSWORD": adminpass}) + + rid=rid+1 + mmr_syncrepl_user_config += read_and_sub_file(setup_path("mmr_syncrepl.conf"), + { "RID" : str(rid), + "MMRDN": names.domaindn, + "LDAPSERVER" : url, + "MMR_PASSWORD": adminpass }) + + setup_file(setup_path("slapd.conf"), paths.slapdconf, {"DNSDOMAIN": names.dnsdomain, "LDAPDIR": paths.ldapdir, @@ -1263,8 +1314,14 @@ def provision_backend(setup_dir=None, message=None, "CONFIGDN": names.configdn, "SCHEMADN": names.schemadn, "MEMBEROF_CONFIG": memberof_config, + "MIRRORMODE": mmr_on_config, + "MMR_SERVERIDS_CONFIG": mmr_serverids_config, + "MMR_SYNCREPL_SCHEMA_CONFIG": mmr_syncrepl_schema_config, + "MMR_SYNCREPL_CONFIG_CONFIG": mmr_syncrepl_config_config, + "MMR_SYNCREPL_USER_CONFIG": mmr_syncrepl_user_config, + "MMR_PASSWORD": adminpass, "REFINT_CONFIG": refint_config}) - setup_file(setup_path("modules.conf"), paths.modulesconf, + setup_file(setup_path("modules.conf"), paths.modulesconf, {"REALM": names.realm}) setup_db_config(setup_path, os.path.join(paths.ldapdir, "db", "user")) diff --git a/source4/setup/mmr_serverids.conf b/source4/setup/mmr_serverids.conf new file mode 100644 index 0000000000..c6d14010b4 --- /dev/null +++ b/source4/setup/mmr_serverids.conf @@ -0,0 +1,2 @@ +# Generated from template mmr_serverids.conf +ServerID ${SERVERID} "${LDAPSERVER}" diff --git a/source4/setup/mmr_syncrepl.conf b/source4/setup/mmr_syncrepl.conf new file mode 100644 index 0000000000..5fa8b8f8a0 --- /dev/null +++ b/source4/setup/mmr_syncrepl.conf @@ -0,0 +1,12 @@ +# Generated from template mmr_syncrepl.conf + +syncrepl rid=${RID} + provider="${LDAPSERVER}" + searchbase="${MMRDN}" + type=refreshAndPersist + retry="10 +" + bindmethod=simple + binddn="CN=Manager,${MMRDN}" + credentials="${MMR_PASSWORD}" + + diff --git a/source4/setup/provision-backend b/source4/setup/provision-backend index 845dc8679a..0943da29b6 100755 --- a/source4/setup/provision-backend +++ b/source4/setup/provision-backend @@ -64,6 +64,9 @@ parser.add_option("--server-role", type="choice", metavar="ROLE", help="Set server role to provision for (default standalone)") parser.add_option("--targetdir", type="string", metavar="DIR", help="Set target directory") +parser.add_option("--ol-mmr-urls", type="string", metavar="LDAPSERVER", + help="List of LDAP-URLS [ ldap://<FQDN>:port/ (where port != 389) ] separated with whitespaces for use with OpenLDAP-MMR") + opts = parser.parse_args()[0] @@ -99,4 +102,6 @@ provision_backend(setup_dir=setup_dir, message=message, smbconf=smbconf, targetd adminpass=opts.ldap_admin_pass, root=opts.root, serverrole=server_role, ldap_backend_type=opts.ldap_backend_type, - ldap_backend_port=opts.ldap_backend_port) + ldap_backend_port=opts.ldap_backend_port, + ol_mmr_urls=opts.ol_mmr_urls) + diff --git a/source4/setup/provision_index.ldif b/source4/setup/provision_index.ldif deleted file mode 100644 index 95970817f3..0000000000 --- a/source4/setup/provision_index.ldif +++ /dev/null @@ -1,19 +0,0 @@ -dn: @INDEXLIST -@IDXATTR: name -@IDXATTR: cn -@IDXATTR: userPrincipalName -@IDXATTR: servicePrincipalName -@IDXATTR: sAMAccountName -@IDXATTR: objectSid -@IDXATTR: objectCategory -@IDXATTR: member -@IDXATTR: uidNumber -@IDXATTR: gidNumber -@IDXATTR: unixName -@IDXATTR: privilege -@IDXATTR: nCName -@IDXATTR: lDAPDisplayName -@IDXATTR: subClassOf -@IDXATTR: dnsRoot -@IDXATTR: nETBIOSName -@IDXATTR: objectGUID diff --git a/source4/setup/provision_init.ldif b/source4/setup/provision_init.ldif index 65a12f1afa..a6c591dd51 100644 --- a/source4/setup/provision_init.ldif +++ b/source4/setup/provision_init.ldif @@ -1,3 +1,8 @@ +#These attributes are only used as far as the bootstrapping of the +# schema. After that, the attributes from the schema are used. +# +# Therefore, they must strictly match the schema + dn: @ATTRIBUTES userPrincipalName: CASE_INSENSITIVE servicePrincipalName: CASE_INSENSITIVE @@ -7,6 +12,8 @@ nETBIOSName: CASE_INSENSITIVE cn: CASE_INSENSITIVE dc: CASE_INSENSITIVE name: CASE_INSENSITIVE +lDAPDisplayName: CASE_INSENSITIVE +subClassOf: CASE_INSENSITIVE dn: CASE_INSENSITIVE sAMAccountName: CASE_INSENSITIVE objectClass: CASE_INSENSITIVE diff --git a/source4/setup/provision_templates.ldif b/source4/setup/provision_templates.ldif index 8f4ed08252..04257549d5 100644 --- a/source4/setup/provision_templates.ldif +++ b/source4/setup/provision_templates.ldif @@ -2,16 +2,6 @@ # Templates to be put in templates.ldb. Not part of main samdb any more. ### -dn: @OPTIONS -checkBaseOnSearch: TRUE - -dn: @INDEXLIST -@IDXATTR: cn - -dn: @ATTRIBUTES -cn: CASE_INSENSITIVE -dn: CASE_INSENSITIVE - dn: CN=Templates objectClass: top objectClass: container diff --git a/source4/setup/provision_templates_init.ldif b/source4/setup/provision_templates_init.ldif new file mode 100644 index 0000000000..6d6a3c228c --- /dev/null +++ b/source4/setup/provision_templates_init.ldif @@ -0,0 +1,10 @@ +dn: @OPTIONS +checkBaseOnSearch: TRUE + +dn: @INDEXLIST +@IDXATTR: cn + +dn: @ATTRIBUTES +cn: CASE_INSENSITIVE +dn: CASE_INSENSITIVE + diff --git a/source4/setup/provision_users.ldif b/source4/setup/provision_users.ldif index 641247cf22..854c42d07c 100644 --- a/source4/setup/provision_users.ldif +++ b/source4/setup/provision_users.ldif @@ -83,7 +83,7 @@ objectClass: top objectClass: group cn: Cert Publishers description: Members of this group are permitted to publish certificates to the Active Directory -groupType: 2147483652 +groupType: -2147483644 objectSid: ${DOMAINSID}-517 sAMAccountName: Cert Publishers isCriticalSystemObject: TRUE @@ -134,7 +134,7 @@ cn: RAS and IAS Servers description: Servers in this group can access remote access properties of users objectSid: ${DOMAINSID}-553 sAMAccountName: RAS and IAS Servers -groupType: 2147483652 +groupType: -2147483644 isCriticalSystemObject: TRUE dn: CN=Administrators,CN=Builtin,${DOMAINDN} @@ -149,7 +149,7 @@ objectSid: S-1-5-32-544 adminCount: 1 sAMAccountName: Administrators systemFlags: 2348810240 -groupType: 2147483653 +groupType: -2147483643 isCriticalSystemObject: TRUE privilege: SeSecurityPrivilege privilege: SeBackupPrivilege @@ -185,7 +185,7 @@ member: CN=Domain Users,CN=Users,${DOMAINDN} objectSid: S-1-5-32-545 sAMAccountName: Users systemFlags: 2348810240 -groupType: 2147483653 +groupType: -2147483643 isCriticalSystemObject: TRUE dn: CN=Guests,CN=Builtin,${DOMAINDN} @@ -198,7 +198,7 @@ member: CN=Guest,CN=Users,${DOMAINDN} objectSid: S-1-5-32-546 sAMAccountName: Guests systemFlags: 2348810240 -groupType: 2147483653 +groupType: -2147483643 isCriticalSystemObject: TRUE dn: CN=Print Operators,CN=Builtin,${DOMAINDN} @@ -210,7 +210,7 @@ objectSid: S-1-5-32-550 adminCount: 1 sAMAccountName: Print Operators systemFlags: 2348810240 -groupType: 2147483653 +groupType: -2147483643 isCriticalSystemObject: TRUE privilege: SeLoadDriverPrivilege privilege: SeShutdownPrivilege @@ -225,7 +225,7 @@ objectSid: S-1-5-32-551 adminCount: 1 sAMAccountName: Backup Operators systemFlags: 2348810240 -groupType: 2147483653 +groupType: -2147483643 isCriticalSystemObject: TRUE privilege: SeBackupPrivilege privilege: SeRestorePrivilege @@ -241,7 +241,7 @@ objectSid: S-1-5-32-552 adminCount: 1 sAMAccountName: Replicator systemFlags: 2348810240 -groupType: 2147483653 +groupType: -2147483643 isCriticalSystemObject: TRUE dn: CN=Remote Desktop Users,CN=Builtin,${DOMAINDN} @@ -252,7 +252,7 @@ description: Members in this group are granted the right to logon remotely objectSid: S-1-5-32-555 sAMAccountName: Remote Desktop Users systemFlags: 2348810240 -groupType: 2147483653 +groupType: -2147483643 isCriticalSystemObject: TRUE dn: CN=Network Configuration Operators,CN=Builtin,${DOMAINDN} @@ -263,7 +263,7 @@ description: Members in this group can have some administrative privileges to ma objectSid: S-1-5-32-556 sAMAccountName: Network Configuration Operators systemFlags: 2348810240 -groupType: 2147483653 +groupType: -2147483643 isCriticalSystemObject: TRUE dn: CN=Performance Monitor Users,CN=Builtin,${DOMAINDN} @@ -274,7 +274,7 @@ description: Members of this group have remote access to monitor this computer objectSid: S-1-5-32-558 sAMAccountName: Performance Monitor Users systemFlags: 2348810240 -groupType: 2147483653 +groupType: -2147483643 isCriticalSystemObject: TRUE dn: CN=Performance Log Users,CN=Builtin,${DOMAINDN} @@ -285,7 +285,7 @@ description: Members of this group have remote access to schedule logging of per objectSid: S-1-5-32-559 sAMAccountName: Performance Log Users systemFlags: 2348810240 -groupType: 2147483653 +groupType: -2147483643 isCriticalSystemObject: TRUE dn: CN=Server Operators,CN=Builtin,${DOMAINDN} @@ -297,7 +297,7 @@ objectSid: S-1-5-32-549 adminCount: 1 sAMAccountName: Server Operators systemFlags: 2348810240 -groupType: 2147483653 +groupType: -2147483643 isCriticalSystemObject: TRUE privilege: SeBackupPrivilege privilege: SeSystemtimePrivilege @@ -315,7 +315,7 @@ objectSid: S-1-5-32-548 adminCount: 1 sAMAccountName: Account Operators systemFlags: 2348810240 -groupType: 2147483653 +groupType: -2147483643 isCriticalSystemObject: TRUE privilege: SeInteractiveLogonRight @@ -327,7 +327,7 @@ description: A backward compatibility group which allows read access on all user objectSid: S-1-5-32-554 sAMAccountName: Pre-Windows 2000 Compatible Access systemFlags: 2348810240 -groupType: 2147483653 +groupType: -2147483643 isCriticalSystemObject: TRUE privilege: SeRemoteInteractiveLogonRight privilege: SeChangeNotifyPrivilege @@ -340,7 +340,7 @@ description: Members of this group can create incoming, one-way trusts to this f objectSid: S-1-5-32-557 sAMAccountName: Incoming Forest Trust Builders systemFlags: 2348810240 -groupType: 2147483653 +groupType: -2147483643 isCriticalSystemObject: TRUE dn: CN=Windows Authorization Access Group,CN=Builtin,${DOMAINDN} @@ -351,7 +351,7 @@ description: Members of this group have access to the computed tokenGroupsGlobal objectSid: S-1-5-32-560 sAMAccountName: Windows Authorization Access Group systemFlags: 2348810240 -groupType: 2147483653 +groupType: -2147483643 isCriticalSystemObject: TRUE dn: CN=Terminal Server License Servers,CN=Builtin,${DOMAINDN} @@ -362,7 +362,7 @@ description: Terminal Server License Servers objectSid: S-1-5-32-561 sAMAccountName: Terminal Server License Servers systemFlags: 2348810240 -groupType: 2147483653 +groupType: -2147483643 isCriticalSystemObject: TRUE dn: CN=Distributed COM Users,CN=Builtin,${DOMAINDN} @@ -373,7 +373,7 @@ description: Members are allowed to launch, activate and use Distributed COM obj objectSid: S-1-5-32-562 sAMAccountName: Distributed COM Users systemFlags: 2348810240 -groupType: 2147483653 +groupType: -2147483643 isCriticalSystemObject: TRUE dn: CN=WellKnown Security Principals,${CONFIGDN} diff --git a/source4/setup/schema-map-openldap-2.3 b/source4/setup/schema-map-openldap-2.3 index f5279616d1..7de2e67b5e 100644 --- a/source4/setup/schema-map-openldap-2.3 +++ b/source4/setup/schema-map-openldap-2.3 @@ -39,3 +39,6 @@ modifyTimeStamp:samba4ModifyTimestamp 1.2.840.113556.1.4.903:1.3.6.1.4.1.1466.115.121.1.12 #Treat Security Descriptors as binary 1.2.840.113556.1.4.907:1.3.6.1.4.1.1466.115.121.1.40 +#Treat OIDs as case insensitive strings (as otherwise ldap class and +#attribute names, declared at OIDs fail +1.3.6.1.4.1.1466.115.121.1.38:1.3.6.1.4.1.1466.115.121.1.44 diff --git a/source4/setup/schema.ldif b/source4/setup/schema.ldif index e96cf5f5fc..40ef709ac3 100644 --- a/source4/setup/schema.ldif +++ b/source4/setup/schema.ldif @@ -10376,552 +10376,3 @@ defaultObjectCategory: CN=Group-Policy-Container,${SCHEMADN} dn: CN=Aggregate,${SCHEMADN} objectClass: top objectClass: subSchema -objectClasses: ( 2.5.6.0 NAME 'top' SUP top ABSTRACT MUST ( objectClass $ objectCategory $ nTSecurityDescriptor $ instanceType ) MAY ( url $ wWWHomePage $ whenCreated $ whenChanged $ wellKnownObjects $ wbemPath $ uSNSource $ uSNLastObjRem $ USNIntersite $ uSNDSALastObjRemoved $ uSNCreated $ uSNChanged $ systemFlags $ subSchemaSubEntry $ subRefs $ structuralObjectClass $ siteObjectBL $ serverReferenceBL $ sDRightsEffective $ revision $ repsTo $ repsFrom $ directReports $ replUpToDateVector $ replPropertyMetaData $ name $ queryPolicyBL $ proxyAddresses $ proxiedObjectName $ possibleInferiors $ partialAttributeSet $ partialAttributeDeletionList $ otherWellKnownObjects $ objectVersion $ objectGUID $ distinguishedName $ nonSecurityMemberBL $ netbootSCPBL $ ownerBL $ msDS-ReplValueMetaData $ msDS-ReplAttributeMetaData $ msDS-NonMembersBL $ msDS-NCReplOutboundNeighbors $ msDS-NCReplInboundNeighbors $ msDS-NCReplCursors $ msDS-TasksForAzRoleBL $ msDS-TasksForAzTaskBL $ msDS-OperationsForAzRoleBL $ msDS-OperationsForAzTaskBL $ msDS-MembersForAzRoleBL $ msDs-masteredBy $ mS-DS-ConsistencyGuid $ mS-DS-ConsistencyChildCount $ msDS-Approx-Immed-Subordinates $ msCOM-PartitionSetLink $ msCOM-UserLink $ modifyTimeStamp $ masteredBy $ managedObjects $ lastKnownParent $ isPrivilegeHolder $ memberOf $ isDeleted $ isCriticalSystemObject $ showInAdvancedViewOnly $ fSMORoleOwner $ fRSMemberReferenceBL $ frsComputerReferenceBL $ fromEntry $ flags $ extensionName $ dSASignature $ dSCorePropagationData $ displayNamePrintable $ displayName $ description $ createTimeStamp $ cn $ canonicalName $ bridgeheadServerListBL $ allowedChildClassesEffective $ allowedChildClasses $ allowedAttributesEffective $ allowedAttributes $ adminDisplayName $ adminDescription $ msDS-ObjectReferenceBL ) ) -objectClasses: ( 1.2.840.113556.1.5.120 NAME 'ipsecISAKMPPolicy' SUP ipsecBase STRUCTURAL ) -objectClasses: ( 1.2.840.113556.1.5.67 NAME 'domainDNS' SUP domain STRUCTURAL MAY ( msDS-Behavior-Version $ msDS-AllowedDNSSuffixes $ managedBy ) ) -objectClasses: ( 1.2.840.113556.1.5.235 NAME 'msDS-AzApplication' SUP top STRUCTURAL MAY ( msDS-AzApplicationData $ msDS-AzGenerateAudits $ msDS-AzApplicationVersion $ msDS-AzClassId $ msDS-AzApplicationName $ description ) ) -objectClasses: ( 1.2.840.113556.1.5.4 NAME 'builtinDomain' SUP top STRUCTURAL ) -objectClasses: ( 1.2.840.113556.1.5.175 NAME 'infrastructureUpdate' SUP top STRUCTURAL MAY ( dNReferenceUpdate ) ) -objectClasses: ( 1.2.840.113556.1.5.12 NAME 'configuration' SUP top STRUCTURAL MUST ( cn ) MAY ( gPOptions $ gPLink ) ) -objectClasses: ( 1.2.840.113556.1.3.11 NAME 'crossRef' SUP top STRUCTURAL MUST ( nCName $ dnsRoot $ cn ) MAY ( trustParent $ superiorDNSRoot $ rootTrust $ nTMixedDomain $ nETBIOSName $ Enabled $ msDS-SDReferenceDomain $ msDS-Replication-Notify-Subsequent-DSA-Delay $ msDS-Replication-Notify-First-DSA-Delay $ msDS-NC-Replica-Locations $ msDS-DnsRootAlias $ msDS-Behavior-Version ) ) -objectClasses: ( 1.2.840.113556.1.5.83 NAME 'rIDManager' SUP top STRUCTURAL MUST ( rIDAvailablePool ) ) -objectClasses: ( 1.2.840.113556.1.5.84 NAME 'displaySpecifier' SUP top STRUCTURAL MAY ( treatAsLeaf $ shellPropertyPages $ shellContextMenu $ scopeFlags $ queryFilter $ iconPath $ extraColumns $ creationWizard $ createWizardExt $ createDialog $ contextMenu $ classDisplayName $ attributeDisplayNames $ adminPropertyPages $ adminMultiselectPropertyPages $ adminContextMenu ) ) -objectClasses: ( 1.2.840.113556.1.5.7000.56 NAME 'ipsecBase' SUP top ABSTRACT MAY ( ipsecOwnersReference $ ipsecName $ ipsecID $ ipsecDataType $ ipsecData ) ) -objectClasses: ( 1.2.840.113556.1.5.237 NAME 'msDS-AzScope' SUP top STRUCTURAL MUST ( msDS-AzScopeName ) MAY ( msDS-AzApplicationData $ description ) ) -objectClasses: ( 2.5.6.3 NAME 'locality' SUP top STRUCTURAL MUST ( l ) MAY ( street $ st $ seeAlso $ searchGuide ) ) -objectClasses: ( 1.2.840.113556.1.5.7000.53 NAME 'crossRefContainer' SUP top STRUCTURAL MAY ( msDS-SPNSuffixes $ uPNSuffixes $ msDS-UpdateScript $ msDS-ExecuteScriptPassword $ msDS-Behavior-Version ) ) -objectClasses: ( 1.2.840.113556.1.5.106 NAME 'queryPolicy' SUP top STRUCTURAL MAY ( lDAPIPDenyList $ lDAPAdminLimits ) ) -objectClasses: ( 1.2.840.113556.1.5.95 NAME 'subnetContainer' SUP top STRUCTURAL ) -objectClasses: ( 1.2.840.113556.1.5.7000.47 NAME 'nTDSDSA' SUP applicationSettings STRUCTURAL MAY ( serverReference $ msDS-RetiredReplNCSignatures $ retiredReplDSASignatures $ queryPolicyObject $ options $ networkAddress $ msDS-ReplicationEpoch $ msDS-HasInstantiatedNCs $ msDS-hasMasterNCs $ msDS-HasDomainNCs $ msDS-Behavior-Version $ managedBy $ lastBackupRestorationTime $ invocationId $ hasPartialReplicaNCs $ hasMasterNCs $ fRSRootPath $ dMDLocation ) ) -objectClasses: ( 1.2.840.113556.1.5.3 NAME 'samDomain' SUP top AUXILIARY MAY ( treeName $ rIDManagerReference $ replicaSource $ pwdProperties $ pwdHistoryLength $ privateKey $ pekList $ pekKeyChangeInterval $ nTMixedDomain $ nextRid $ nETBIOSName $ msDS-PerUserTrustTombstonesQuota $ msDS-PerUserTrustQuota $ ms-DS-MachineAccountQuota $ msDS-LogonTimeSyncInterval $ msDS-AllUsersTrustQuota $ modifiedCountAtLastProm $ minPwdLength $ minPwdAge $ maxPwdAge $ lSAModifiedCount $ lSACreationTime $ lockoutThreshold $ lockoutDuration $ lockOutObservationWindow $ gPOptions $ gPLink $ eFSPolicy $ domainPolicyObject $ desktopProfile $ description $ defaultLocalPolicyObject $ creationTime $ controlAccessRights $ cACertificate $ builtinModifiedCount $ builtinCreationTime $ auditingPolicy ) ) -objectClasses: ( 1.2.840.113556.1.5.2 NAME 'samDomainBase' SUP top AUXILIARY MAY ( uASCompat $ serverState $ serverRole $ revision $ pwdProperties $ pwdHistoryLength $ oEMInformation $ objectSid $ nTSecurityDescriptor $ nextRid $ modifiedCountAtLastProm $ modifiedCount $ minPwdLength $ minPwdAge $ maxPwdAge $ lockoutThreshold $ lockoutDuration $ lockOutObservationWindow $ forceLogoff $ domainReplica $ creationTime ) ) -objectClasses: ( 2.5.6.2 NAME 'country' SUP top MUST ( c ) MAY ( co $ searchGuide ) ) -objectClasses: ( 2.5.6.5 NAME 'organizationalUnit' SUP top STRUCTURAL MUST ( ou ) MAY ( x121Address $ userPassword $ uPNSuffixes $ co $ telexNumber $ teletexTerminalIdentifier $ telephoneNumber $ street $ st $ seeAlso $ searchGuide $ registeredAddress $ preferredDeliveryMethod $ postalCode $ postalAddress $ postOfficeBox $ physicalDeliveryOfficeName $ msCOM-UserPartitionSetLink $ managedBy $ thumbnailLogo $ l $ internationalISDNNumber $ gPOptions $ gPLink $ facsimileTelephoneNumber $ destinationIndicator $ desktopProfile $ defaultGroup $ countryCode $ c $ businessCategory ) ) -objectClasses: ( 1.2.840.113556.1.5.121 NAME 'ipsecNFA' SUP ipsecBase STRUCTURAL MAY ( ipsecNegotiationPolicyReference $ ipsecFilterReference ) ) -objectClasses: ( 1.2.840.113556.1.5.139 NAME 'lostAndFound' SUP top STRUCTURAL MAY ( moveTreeState ) ) -objectClasses: ( 2.5.6.7 NAME 'organizationalPerson' SUP person MAY ( x121Address $ comment $ title $ co $ primaryTelexNumber $ telexNumber $ teletexTerminalIdentifier $ street $ st $ registeredAddress $ preferredDeliveryMethod $ postalCode $ postalAddress $ postOfficeBox $ thumbnailPhoto $ physicalDeliveryOfficeName $ pager $ otherPager $ otherTelephone $ mobile $ otherMobile $ primaryInternationalISDNNumber $ ipPhone $ otherIpPhone $ otherHomePhone $ homePhone $ otherFacsimileTelephoneNumber $ personalTitle $ middleName $ otherMailbox $ ou $ o $ mhsORAddress $ msDS-AllowedToDelegateTo $ manager $ thumbnailLogo $ l $ internationalISDNNumber $ initials $ givenName $ generationQualifier $ facsimileTelephoneNumber $ employeeID $ mail $ division $ destinationIndicator $ department $ c $ countryCode $ company $ assistant $ streetAddress $ houseIdentifier $ msExchHouseIdentifier $ homePostalAddress ) ) -objectClasses: ( 1.2.840.113556.1.3.14 NAME 'attributeSchema' SUP top STRUCTURAL MUST ( schemaIDGUID $ oMSyntax $ lDAPDisplayName $ isSingleValued $ cn $ attributeSyntax $ attributeID ) MAY ( systemOnly $ searchFlags $ schemaFlagsEx $ rangeUpper $ rangeLower $ oMObjectClass $ msDs-Schema-Extensions $ msDS-IntId $ mAPIID $ linkID $ isMemberOfPartialAttributeSet $ isEphemeral $ isDefunct $ extendedCharsAllowed $ classDisplayName $ attributeSecurityGUID ) ) -objectClasses: ( 1.2.840.113556.1.5.72 NAME 'nTDSService' SUP top STRUCTURAL MAY ( tombstoneLifetime $ sPNMappings $ replTopologyStayOfExecution $ msDS-Other-Settings $ garbageCollPeriod $ dSHeuristics ) ) -objectClasses: ( 1.2.840.113556.1.5.7000.48 NAME 'serversContainer' SUP top STRUCTURAL ) -objectClasses: ( 1.2.840.113556.1.3.30 NAME 'computer' SUP user STRUCTURAL MAY ( volumeCount $ siteGUID $ rIDSetReferences $ policyReplicationFlags $ physicalLocationObject $ operatingSystemVersion $ operatingSystemServicePack $ operatingSystemHotfix $ operatingSystem $ networkAddress $ netbootSIFFile $ netbootMirrorDataFile $ netbootMachineFilePath $ netbootInitialization $ netbootGUID $ msDS-AdditionalSamAccountName $ msDS-AdditionalDnsHostName $ managedBy $ machineRole $ location $ localPolicyFlags $ dNSHostName $ defaultLocalPolicyObject $ cn $ catalogs ) ) -objectClasses: ( 2.5.6.6 NAME 'person' SUP top MUST ( cn ) MAY ( userPassword $ telephoneNumber $ sn $ serialNumber $ seeAlso $ attributeCertificateAttribute ) ) -objectClasses: ( 1.2.840.113556.1.5.98 NAME 'ipsecPolicy' SUP ipsecBase STRUCTURAL MAY ( ipsecNFAReference $ ipsecISAKMPReference ) ) -objectClasses: ( 1.2.840.113556.1.3.23 NAME 'container' SUP top STRUCTURAL MUST ( cn ) MAY ( schemaVersion $ defaultClassStore $ msDS-ObjectReference ) ) -objectClasses: ( 1.2.840.113556.1.5.31 NAME 'site' SUP top STRUCTURAL MAY ( notificationList $ mSMQSiteID $ mSMQSiteForeign $ mSMQNt4Stub $ mSMQInterval2 $ mSMQInterval1 $ managedBy $ location $ gPOptions $ gPLink ) ) -objectClasses: ( 2.5.6.4 NAME 'organization' SUP top STRUCTURAL MUST ( o ) MAY ( x121Address $ userPassword $ telexNumber $ teletexTerminalIdentifier $ telephoneNumber $ street $ st $ seeAlso $ searchGuide $ registeredAddress $ preferredDeliveryMethod $ postalCode $ postalAddress $ postOfficeBox $ physicalDeliveryOfficeName $ l $ internationalISDNNumber $ facsimileTelephoneNumber $ destinationIndicator $ businessCategory ) ) -objectClasses: ( 1.2.840.113556.1.5.234 NAME 'msDS-AzAdminManager' SUP top STRUCTURAL MAY ( msDS-AzMinorVersion $ msDS-AzMajorVersion $ msDS-AzApplicationData $ msDS-AzGenerateAudits $ msDS-AzScriptTimeout $ msDS-AzScriptEngineCacheMax $ msDS-AzDomainTimeout $ description ) ) -objectClasses: ( 1.2.840.113556.1.5.6 NAME 'securityPrincipal' SUP top AUXILIARY MUST ( sAMAccountName $ objectSid ) MAY ( supplementalCredentials $ sIDHistory $ securityIdentifier $ sAMAccountType $ rid $ tokenGroupsNoGCAcceptable $ tokenGroupsGlobalAndUniversal $ tokenGroups $ nTSecurityDescriptor $ msDS-KeyVersionNumber $ altSecurityIdentities $ accountNameHistory ) ) -objectClasses: ( 1.2.840.113556.1.5.7000.49 NAME 'applicationSettings' SUP top ABSTRACT MAY ( notificationList $ msDS-Settings $ applicationName ) ) -objectClasses: ( 1.2.840.113556.1.3.13 NAME 'classSchema' SUP top STRUCTURAL MUST ( subClassOf $ schemaIDGUID $ objectClassCategory $ governsID $ defaultObjectCategory $ cn ) MAY ( systemPossSuperiors $ systemOnly $ systemMustContain $ systemMayContain $ systemAuxiliaryClass $ schemaFlagsEx $ rDNAttID $ possSuperiors $ mustContain $ msDs-Schema-Extensions $ msDS-IntId $ mayContain $ lDAPDisplayName $ isDefunct $ defaultSecurityDescriptor $ defaultHidingValue $ classDisplayName $ auxiliaryClass ) ) -objectClasses: ( 1.2.840.113556.1.5.9 NAME 'user' SUP organizationalPerson STRUCTURAL MAY ( pager $ o $ mobile $ manager $ mail $ initials $ homePhone $ businessCategory $ userCertificate $ userWorkstations $ userSharedFolderOther $ userSharedFolder $ userPrincipalName $ userParameters $ userAccountControl $ unicodePwd $ terminalServer $ servicePrincipalName $ scriptPath $ pwdLastSet $ profilePath $ primaryGroupID $ preferredOU $ otherLoginWorkstations $ operatorCount $ ntPwdHistory $ networkAddress $ msRASSavedFramedRoute $ msRASSavedFramedIPAddress $ msRASSavedCallbackNumber $ msRADIUSServiceType $ msRADIUSFramedRoute $ msRADIUSFramedIPAddress $ msRADIUSCallbackNumber $ msNPSavedCallingStationID $ msNPCallingStationID $ msNPAllowDialin $ mSMQSignCertificatesMig $ mSMQSignCertificates $ mSMQDigestsMig $ mSMQDigests $ msIIS-FTPRoot $ msIIS-FTPDir $ msDS-User-Account-Control-Computed $ msDS-Site-Affinity $ mS-DS-CreatorSID $ msDS-Cached-Membership-Time-Stamp $ msDS-Cached-Membership $ msDRM-IdentityCertificate $ msCOM-UserPartitionSetLink $ maxStorage $ logonWorkstation $ logonHours $ logonCount $ lockoutTime $ localeID $ lmPwdHistory $ lastLogonTimestamp $ lastLogon $ lastLogoff $ homeDrive $ homeDirectory $ groupsToIgnore $ groupPriority $ groupMembershipSAM $ dynamicLDAPServer $ desktopProfile $ defaultClassStore $ dBCSPwd $ controlAccessRights $ codePage $ badPwdCount $ badPasswordTime $ adminCount $ aCSPolicyName $ accountExpires $ x500uniqueIdentifier $ userSMIMECertificate $ userPKCS12 $ uid $ secretary $ roomNumber $ preferredLanguage $ photo $ labeledURI $ jpegPhoto $ homePostalAddress $ givenName $ employeeType $ employeeNumber $ displayName $ departmentNumber $ carLicense $ audio ) ) -objectClasses: ( 1.2.840.113556.1.3.9 NAME 'dMD' SUP top STRUCTURAL MUST ( cn ) MAY ( schemaUpdate $ schemaInfo $ prefixMap $ msDs-Schema-Extensions $ msDS-IntId $ dmdName ) ) -objectClasses: ( 1.2.840.113556.1.5.20 NAME 'leaf' SUP top ABSTRACT ) -objectClasses: ( 1.2.840.113556.1.5.28 NAME 'secret' SUP leaf STRUCTURAL MAY ( priorValue $ priorSetTime $ lastSetTime $ currentValue ) ) -objectClasses: ( 1.2.840.113556.1.5.107 NAME 'sitesContainer' SUP top STRUCTURAL ) -objectClasses: ( 1.2.840.113556.1.5.17 NAME 'server' SUP top STRUCTURAL MAY ( mailAddress $ serverReference $ serialNumber $ managedBy $ dNSHostName $ bridgeheadTransportList ) ) -objectClasses: ( 2.5.20.1 NAME 'subSchema' SUP top STRUCTURAL MAY ( objectClasses $ modifyTimeStamp $ extendedClassInfo $ extendedAttributeInfo $ dITContentRules $ attributeTypes ) ) -objectClasses: ( 1.2.840.113556.1.5.34 NAME 'trustedDomain' SUP leaf STRUCTURAL MAY ( trustType $ trustPosixOffset $ trustPartner $ trustDirection $ trustAuthOutgoing $ trustAuthIncoming $ trustAttributes $ securityIdentifier $ msDS-TrustForestTrustInfo $ mS-DS-CreatorSID $ initialAuthOutgoing $ initialAuthIncoming $ flatName $ domainIdentifier $ domainCrossRef $ additionalTrustedServiceNames ) ) -objectClasses: ( 1.2.840.113556.1.5.66 NAME 'domain' SUP top ABSTRACT MUST ( dc ) ) -objectClasses: ( 1.2.840.113556.1.5.76 NAME 'foreignSecurityPrincipal' SUP top STRUCTURAL MUST ( objectSid ) MAY ( foreignIdentifier ) ) -objectClasses: ( 1.2.840.113556.1.5.96 NAME 'subnet' SUP top STRUCTURAL MAY ( siteObject $ physicalLocationObject $ location ) ) -objectClasses: ( 1.2.840.113556.1.3.46 NAME 'mailRecipient' SUP top AUXILIARY MUST ( cn ) MAY ( userCertificate $ userCert $ textEncodedORAddress $ telephoneNumber $ showInAddressBook $ legacyExchangeDN $ garbageCollPeriod $ info $ userSMIMECertificate $ secretary $ msExchLabeledURI $ msExchAssistantName $ labeledURI ) ) -objectClasses: ( 1.2.840.113556.1.5.8 NAME 'group' SUP top STRUCTURAL MUST ( groupType ) MAY ( primaryGroupToken $ operatorCount $ nTGroupMembers $ nonSecurityMember $ msDS-NonMembers $ msDS-AzLDAPQuery $ member $ managedBy $ groupMembershipSAM $ groupAttributes $ mail $ desktopProfile $ controlAccessRights $ adminCount ) ) -objectClasses: ( 1.2.840.113556.1.5.157 NAME 'groupPolicyContainer' SUP container STRUCTURAL MAY ( versionNumber $ gPCWQLFilter $ gPCUserExtensionNames $ gPCMachineExtensionNames $ gPCFunctionalityVersion $ gPCFileSysPath $ flags ) ) -attributeTypes: ( 1.2.840.113556.1.4.1304 NAME 'sDRightsEffective' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.104 NAME 'ownerBL' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.2.102 NAME 'memberOf' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' NO-USER-MODIFICATION ) -attributeTypes: ( 2.5.4.14 NAME 'searchGuide' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' ) -attributeTypes: ( 1.2.840.113556.1.4.1720 NAME 'msDS-ReplicationEpoch' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.202 NAME 'auditingPolicy' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.646 NAME 'otherFacsimileTelephoneNumber' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.2.256 NAME 'streetAddress' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.121 NAME 'securityIdentifier' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1782 NAME 'msDS-KeyVersionNumber' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.1307 NAME 'accountNameHistory' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 2.16.840.1.113730.3.1.39 NAME 'preferredLanguage' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.752 NAME 'userSharedFolderOther' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.751 NAME 'userSharedFolder' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.966 NAME 'mSMQDigestsMig' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' ) -attributeTypes: ( 1.2.840.113556.1.4.755 NAME 'domainIdentifier' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.655 NAME 'legacyExchangeDN' SYNTAX '1.2.840.113556.1.4.905' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.618 NAME 'wellKnownObjects' SYNTAX '1.2.840.113556.1.4.903' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.1 NAME 'name' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.531 NAME 'nonSecurityMemberBL' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.1707 NAME 'msDS-ReplAttributeMetaData' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.1242 NAME 'dNReferenceUpdate' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.892 NAME 'gPOptions' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1790 NAME 'msDS-PerUserTrustTombstonesQuota' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 0.9.2342.19200300.100.1.42 NAME 'pager' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.362 NAME 'siteGUID' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1796 NAME 'msDS-AzScriptEngineCacheMax' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1303 NAME 'tokenGroupsNoGCAcceptable' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' ) -attributeTypes: ( 1.2.840.113556.1.4.1418 NAME 'tokenGroupsGlobalAndUniversal' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' ) -attributeTypes: ( 1.2.840.113556.1.4.867 NAME 'altSecurityIdentities' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.3.6.1.4.1.250.1.57 NAME 'labeledURI' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.96 NAME 'pwdLastSet' SYNTAX '1.2.840.113556.1.4.906' SINGLE-VALUE ) -attributeTypes: ( 2.5.21.6 NAME 'objectClasses' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.470 NAME 'trustAttributes' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1702 NAME 'msDS-TrustForestTrustInfo' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.512 NAME 'siteObject' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.638 NAME 'isPrivilegeHolder' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.28 NAME 'dnsRoot' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.168 NAME 'modifiedCount' SYNTAX '1.2.840.113556.1.4.906' SINGLE-VALUE ) -attributeTypes: ( 2.5.4.25 NAME 'internationalISDNNumber' SYNTAX '1.3.6.1.4.1.1466.115.121.1.36' ) -attributeTypes: ( 2.5.4.15 NAME 'businessCategory' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 2.5.4.51 NAME 'houseIdentifier' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 2.16.840.1.113730.3.1.34 NAME 'middleName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.30 NAME 'attributeID' SYNTAX '1.3.6.1.4.1.1466.115.121.1.38' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.677 NAME 'replTopologyStayOfExecution' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.359 NAME 'netbootGUID' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.26 NAME 'rDNAttID' SYNTAX '1.3.6.1.4.1.1466.115.121.1.38' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.2.25 NAME 'mayContain' SYNTAX '1.3.6.1.4.1.1466.115.121.1.38' ) -attributeTypes: ( 1.2.840.113556.1.4.135 NAME 'trustAuthOutgoing' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1694 NAME 'gPCWQLFilter' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.516 NAME 'serverReferenceBL' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' NO-USER-MODIFICATION ) -attributeTypes: ( 2.5.18.1 NAME 'createTimeStamp' SYNTAX '1.3.6.1.4.1.1466.115.121.1.24' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.748 NAME 'attributeDisplayNames' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.614 NAME 'adminContextMenu' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.67 NAME 'lSAModifiedCount' SYNTAX '1.2.840.113556.1.4.906' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.66 NAME 'lSACreationTime' SYNTAX '1.2.840.113556.1.4.906' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.154 NAME 'serverState' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.460 NAME 'lDAPDisplayName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.125 NAME 'supplementalCredentials' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' ) -attributeTypes: ( 1.2.840.113556.1.4.1130 NAME 'msNPSavedCallingStationID' SYNTAX '1.3.6.1.4.1.1466.115.121.1.26' ) -attributeTypes: ( 1.2.840.113556.1.4.38 NAME 'flags' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.812 NAME 'createWizardExt' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.2.36 NAME 'dMDLocation' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.2.596 NAME 'msExchHouseIdentifier' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.647 NAME 'otherMobile' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 2.5.4.44 NAME 'generationQualifier' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.32 NAME 'attributeSyntax' SYNTAX '1.3.6.1.4.1.1466.115.121.1.38' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.149 NAME 'attributeSecurityGUID' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.212 NAME 'dSHeuristics' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 2.5.4.5 NAME 'serialNumber' SYNTAX '1.3.6.1.4.1.1466.115.121.1.26' ) -attributeTypes: ( 1.2.840.113556.1.4.1697 NAME 'msDS-Settings' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.144 NAME 'operatorCount' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1153 NAME 'msRADIUSFramedIPAddress' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.45 NAME 'homeDrive' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 2.5.21.5 NAME 'attributeTypes' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.540 NAME 'initialAuthOutgoing' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.141 NAME 'versionNumber' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 2.5.4.0 NAME 'objectClass' SYNTAX '1.3.6.1.4.1.1466.115.121.1.38' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.915 NAME 'possibleInferiors' SYNTAX '1.3.6.1.4.1.1466.115.121.1.38' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.1669 NAME 'msDS-Approx-Immed-Subordinates' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.1664 NAME 'msDS-Replication-Notify-Subsequent-DSA-Delay' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.810 NAME 'createDialog' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.607 NAME 'queryPolicyObject' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.487 NAME 'fRSRootPath' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 2.5.4.11 NAME 'ou' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 2.5.4.21 NAME 'telexNumber' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' ) -attributeTypes: ( 1.2.840.113556.1.2.617 NAME 'homePostalAddress' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.652 NAME 'assistant' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.361 NAME 'netbootMachineFilePath' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 2.5.4.45 NAME 'x500uniqueIdentifier' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' ) -attributeTypes: ( 1.2.840.113556.1.4.55 NAME 'dBCSPwd' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.538 NAME 'prefixMap' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.1807 NAME 'msDS-MembersForAzRoleBL' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.781 NAME 'lastKnownParent' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.369 NAME 'fSMORoleOwner' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.673 NAME 'retiredReplDSASignatures' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.2.459 NAME 'networkAddress' SYNTAX '1.2.840.113556.1.4.905' ) -attributeTypes: ( 1.2.840.113556.1.2.471 NAME 'schemaVersion' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' ) -attributeTypes: ( 1.2.840.113556.1.2.8 NAME 'possSuperiors' SYNTAX '1.3.6.1.4.1.1466.115.121.1.38' ) -attributeTypes: ( 1.2.840.113556.1.4.224 NAME 'defaultSecurityDescriptor' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 2.16.840.1.113730.3.140 NAME 'userSMIMECertificate' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' ) -attributeTypes: ( 2.16.840.1.113730.3.1.216 NAME 'userPKCS12' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' ) -attributeTypes: ( 1.2.840.113556.1.4.8 NAME 'userAccountControl' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.885 NAME 'terminalServer' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.159 NAME 'accountExpires' SYNTAX '1.2.840.113556.1.4.906' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.750 NAME 'groupType' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.89 NAME 'nTGroupMembers' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' ) -attributeTypes: ( 1.2.840.113556.1.4.749 NAME 'url' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.145 NAME 'revision' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.76 NAME 'objectVersion' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1705 NAME 'msDS-NCReplInboundNeighbors' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.1425 NAME 'msCOM-UserLink' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.1409 NAME 'masteredBy' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.916 NAME 'canonicalName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.1661 NAME 'msDS-NC-Replica-Locations' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' ) -attributeTypes: ( 1.2.840.113556.1.4.1721 NAME 'msDS-UpdateScript' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.88 NAME 'nextRid' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 2.5.4.24 NAME 'x121Address' SYNTAX '1.3.6.1.4.1.1466.115.121.1.36' ) -attributeTypes: ( 2.5.4.35 NAME 'userPassword' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' ) -attributeTypes: ( 2.5.4.20 NAME 'telephoneNumber' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.141 NAME 'department' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.639 NAME 'isMemberOfPartialAttributeSet' SYNTAX '1.3.6.1.4.1.1466.115.121.1.7' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.633 NAME 'policyReplicationFlags' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.626 NAME 'ipsecISAKMPReference' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.218 NAME 'applicationName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.196 NAME 'systemMayContain' SYNTAX '1.3.6.1.4.1.1466.115.121.1.38' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.1191 NAME 'msRASSavedFramedRoute' SYNTAX '1.3.6.1.4.1.1466.115.121.1.26' ) -attributeTypes: ( 1.2.840.113556.1.4.1189 NAME 'msRASSavedCallbackNumber' SYNTAX '1.3.6.1.4.1.1466.115.121.1.26' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.136 NAME 'trustType' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.158 NAME 'domainReplica' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.615 NAME 'personalTitle' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.651 NAME 'otherMailbox' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 0.9.2342.19200300.100.1.3 NAME 'mail' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.231 NAME 'oMSyntax' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.661 NAME 'isDefunct' SYNTAX '1.3.6.1.4.1.1466.115.121.1.7' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1621 NAME 'msDS-Other-Settings' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.71 NAME 'machineRole' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1795 NAME 'msDS-AzDomainTimeout' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.198 NAME 'systemAuxiliaryClass' SYNTAX '1.3.6.1.4.1.1466.115.121.1.38' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.98 NAME 'primaryGroupID' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.160 NAME 'lmPwdHistory' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' ) -attributeTypes: ( 1.2.840.113556.1.4.166 NAME 'groupMembershipSAM' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.133 NAME 'trustPartner' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.1 NAME 'instanceType' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.806 NAME 'treatAsLeaf' SYNTAX '1.3.6.1.4.1.1466.115.121.1.7' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.562 NAME 'adminPropertyPages' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.1799 NAME 'msDS-AzScopeName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 2.5.4.34 NAME 'seeAlso' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' ) -attributeTypes: ( 1.2.840.113556.1.4.844 NAME 'lDAPIPDenyList' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' ) -attributeTypes: ( 1.2.840.113556.1.4.1826 NAME 'msDS-RetiredReplNCSignatures' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.2.14 NAME 'hasMasterNCs' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.81 NAME 'modifiedCountAtLastProm' SYNTAX '1.2.840.113556.1.4.906' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.78 NAME 'minPwdAge' SYNTAX '1.2.840.113556.1.4.906' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.39 NAME 'forceLogoff' SYNTAX '1.2.840.113556.1.4.906' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1305 NAME 'moveTreeState' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' ) -attributeTypes: ( 1.2.840.113556.1.4.1787 NAME 'msDS-AllowedToDelegateTo' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.170 NAME 'systemOnly' SYNTAX '1.3.6.1.4.1.1466.115.121.1.7' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.1716 NAME 'msDS-IntId' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.619 NAME 'dNSHostName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1825 NAME 'msDS-AzMinorVersion' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.49 NAME 'badPasswordTime' SYNTAX '1.2.840.113556.1.4.906' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1412 NAME 'primaryGroupToken' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.2.469 NAME 'USNIntersite' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.876 NAME 'fRSMemberReferenceBL' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.1711 NAME 'msDS-SDReferenceDomain' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.621 NAME 'ipsecID' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.843 NAME 'lDAPAdminLimits' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.519 NAME 'lastBackupRestorationTime' SYNTAX '1.2.840.113556.1.4.906' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.660 NAME 'treeName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.151 NAME 'oEMInformation' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 2.5.4.42 NAME 'givenName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1347 NAME 'sPNMappings' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.364 NAME 'operatingSystemVersion' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.303 NAME 'notificationList' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1301 NAME 'tokenGroups' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' ) -attributeTypes: ( 2.16.840.1.113730.3.1.1 NAME 'carLicense' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.97 NAME 'preferredOU' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1410 NAME 'mS-DS-CreatorSID' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.1793 NAME 'msDS-NonMembers' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' ) -attributeTypes: ( 1.2.840.113556.1.4.1815 NAME 'msDS-TasksForAzRoleBL' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.2.227 NAME 'extensionName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.1663 NAME 'msDS-Replication-Notify-First-DSA-Delay' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.74 NAME 'maxPwdAge' SYNTAX '1.2.840.113556.1.4.906' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.722 NAME 'otherIpPhone' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.627 NAME 'ipsecNFAReference' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' ) -attributeTypes: ( 0.9.2342.19200300.100.1.21 NAME 'secretary' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' ) -attributeTypes: ( 1.2.840.113556.1.4.138 NAME 'userParameters' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.134 NAME 'trustPosixOffset' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.820 NAME 'bridgeheadServerListBL' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.1819 NAME 'msDS-AzApplicationData' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.866 NAME 'pekKeyChangeInterval' SYNTAX '1.2.840.113556.1.4.906' SINGLE-VALUE ) -attributeTypes: ( 2.5.4.6 NAME 'c' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 2.5.4.27 NAME 'destinationIndicator' SYNTAX '1.3.6.1.4.1.1466.115.121.1.26' ) -attributeTypes: ( 1.2.840.113556.1.4.25 NAME 'countryCode' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 0.9.2342.19200300.100.1.41 NAME 'mobile' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.148 NAME 'schemaIDGUID' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.669 NAME 'rIDSetReferences' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.2.351 NAME 'auxiliaryClass' SYNTAX '1.3.6.1.4.1.1466.115.121.1.38' ) -attributeTypes: ( 0.9.2342.19200300.100.1.1 NAME 'uid' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 2.16.840.1.113730.3.1.2 NAME 'departmentNumber' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.889 NAME 'additionalTrustedServiceNames' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.2.464 NAME 'wWWHomePage' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.896 NAME 'uSNSource' SYNTAX '1.2.840.113556.1.4.906' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1360 NAME 'mS-DS-ConsistencyGuid' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.870 NAME 'frsComputerReferenceBL' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.913 NAME 'allowedAttributes' SYNTAX '1.3.6.1.4.1.1466.115.121.1.38' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.1798 NAME 'msDS-AzApplicationName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.890 NAME 'uPNSuffixes' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.1788 NAME 'msDS-PerUserTrustQuota' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1411 NAME 'ms-DS-MachineAccountQuota' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.157 NAME 'serverRole' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 0.9.2342.19200300.100.1.20 NAME 'homePhone' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.34 NAME 'rangeLower' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.415 NAME 'operatingSystemHotfix' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1717 NAME 'msDS-AdditionalDnsHostName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.1797 NAME 'msDS-AzScriptTimeout' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.24 NAME 'mustContain' SYNTAX '1.3.6.1.4.1.1466.115.121.1.38' ) -attributeTypes: ( 2.5.4.36 NAME 'userCertificate' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' ) -attributeTypes: ( 1.2.840.113556.1.4.1124 NAME 'msNPCallingStationID' SYNTAX '1.3.6.1.4.1.1466.115.121.1.26' ) -attributeTypes: ( 1.2.840.113556.1.4.1460 NAME 'msDS-User-Account-Control-Computed' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.44 NAME 'homeDirectory' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1792 NAME 'msDS-AzLDAPQuery' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.663 NAME 'partialAttributeDeletionList' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.868 NAME 'isCriticalSystemObject' SYNTAX '1.3.6.1.4.1.1466.115.121.1.7' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.891 NAME 'gPLink' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1354 NAME 'scopeFlags' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.60 NAME 'lockoutDuration' SYNTAX '1.2.840.113556.1.4.906' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1426 NAME 'msCOM-UserPartitionSetLink' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' SINGLE-VALUE ) -attributeTypes: ( 2.16.840.1.113730.3.1.36 NAME 'thumbnailLogo' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE ) -attributeTypes: ( 2.16.840.1.113730.3.1.35 NAME 'thumbnailPhoto' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.222 NAME 'location' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.86 NAME 'userWorkstations' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.65 NAME 'logonWorkstation' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1696 NAME 'lastLogonTimestamp' SYNTAX '1.2.840.113556.1.4.906' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.100 NAME 'priorValue' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.53 NAME 'lastSetTime' SYNTAX '1.2.840.113556.1.4.906' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.2 NAME 'objectGUID' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.1811 NAME 'msDS-TasksForAzTaskBL' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.653 NAME 'managedBy' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.93 NAME 'pwdProperties' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.13 NAME 'builtinCreationTime' SYNTAX '1.2.840.113556.1.4.906' SINGLE-VALUE ) -attributeTypes: ( 2.5.4.18 NAME 'postOfficeBox' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.2.146 NAME 'company' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.675 NAME 'catalogs' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.783 NAME 'defaultObjectCategory' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1158 NAME 'msRADIUSFramedRoute' SYNTAX '1.3.6.1.4.1.1466.115.121.1.26' ) -attributeTypes: ( 1.2.840.113556.1.4.99 NAME 'priorSetTime' SYNTAX '1.2.840.113556.1.4.906' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.645 NAME 'userCert' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.530 NAME 'nonSecurityMember' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' ) -attributeTypes: ( 2.5.4.31 NAME 'member' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' ) -attributeTypes: ( 1.2.840.113556.1.4.152 NAME 'groupAttributes' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.375 NAME 'systemFlags' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.1249 NAME 'proxiedObjectName' SYNTAX '1.2.840.113556.1.4.903' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.1708 NAME 'msDS-ReplValueMetaData' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.912 NAME 'allowedChildClassesEffective' SYNTAX '1.3.6.1.4.1.1466.115.121.1.38' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.1805 NAME 'msDS-AzGenerateAudits' SYNTAX '1.3.6.1.4.1.1466.115.121.1.7' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1817 NAME 'msDS-AzApplicationVersion' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.219 NAME 'iconPath' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 2.5.4.9 NAME 'street' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1783 NAME 'msDS-ExecuteScriptPassword' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.1784 NAME 'msDS-LogonTimeSyncInterval' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.301 NAME 'garbageCollPeriod' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.967 NAME 'mSMQSignCertificatesMig' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1442 NAME 'msDS-Cached-Membership-Time-Stamp' SYNTAX '1.2.840.113556.1.4.906' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.169 NAME 'logonCount' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.58 NAME 'localeID' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' ) -attributeTypes: ( 1.2.840.113556.1.4.12 NAME 'badPwdCount' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.129 NAME 'trustAuthIncoming' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE ) -attributeTypes: ( 2.5.18.10 NAME 'subSchemaSubEntry' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' NO-USER-MODIFICATION ) -attributeTypes: ( 2.5.21.9 NAME 'structuralObjectClass' SYNTAX '1.3.6.1.4.1.1466.115.121.1.38' ) -attributeTypes: ( 1.2.840.113556.1.2.48 NAME 'isDeleted' SYNTAX '1.3.6.1.4.1.1466.115.121.1.7' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.1687 NAME 'extraColumns' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.1690 NAME 'adminMultiselectPropertyPages' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.307 NAME 'options' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.61 NAME 'lockOutObservationWindow' SYNTAX '1.2.840.113556.1.4.906' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.57 NAME 'defaultLocalPolicyObject' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.26 NAME 'creationTime' SYNTAX '1.2.840.113556.1.4.906' SINGLE-VALUE ) -attributeTypes: ( 2.5.4.26 NAME 'registeredAddress' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' ) -attributeTypes: ( 2.5.4.16 NAME 'postalAddress' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 2.5.4.43 NAME 'initials' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.33 NAME 'isSingleValued' SYNTAX '1.3.6.1.4.1.1466.115.121.1.7' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.1240 NAME 'netbootSIFFile' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.1718 NAME 'msDS-AdditionalSamAccountName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.195 NAME 'systemPossSuperiors' SYNTAX '1.3.6.1.4.1.1466.115.121.1.38' NO-USER-MODIFICATION ) -attributeTypes: ( 0.9.2342.19200300.100.1.7 NAME 'photo' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' ) -attributeTypes: ( 1.2.840.113556.1.2.610 NAME 'employeeNumber' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.662 NAME 'lockoutTime' SYNTAX '1.2.840.113556.1.4.906' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.537 NAME 'dynamicLDAPServer' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.909 NAME 'extendedAttributeInfo' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.2.444 NAME 'msExchAssistantName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1349 NAME 'gPCUserExtensionNames' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1794 NAME 'msDS-NonMembersBL' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.2.194 NAME 'adminDisplayName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.499 NAME 'contextMenu' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.2.50 NAME 'linkID' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 2.5.4.58 NAME 'attributeCertificateAttribute' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' ) -attributeTypes: ( 2.5.4.4 NAME 'sn' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.221 NAME 'sAMAccountName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.22 NAME 'governsID' SYNTAX '1.3.6.1.4.1.1466.115.121.1.38' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 0.9.2342.19200300.100.1.60 NAME 'jpegPhoto' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' ) -attributeTypes: ( 1.2.840.113556.1.4.947 NAME 'mSMQSignCertificates' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.539 NAME 'initialAuthIncoming' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.472 NAME 'domainCrossRef' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' SINGLE-VALUE ) -attributeTypes: ( 0.9.2342.19200300.100.1.2 NAME 'textEncodedORAddress' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.893 NAME 'gPCFunctionalityVersion' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.267 NAME 'uSNDSALastObjRemoved' SYNTAX '1.2.840.113556.1.4.906' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.1813 NAME 'msDS-OperationsForAzRoleBL' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.1361 NAME 'mS-DS-ConsistencyChildCount' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.74 NAME 'dSASignature' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.911 NAME 'allowedChildClasses' SYNTAX '1.3.6.1.4.1.1466.115.121.1.38' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.914 NAME 'allowedAttributesEffective' SYNTAX '1.3.6.1.4.1.1466.115.121.1.38' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.357 NAME 'nTMixedDomain' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1709 NAME 'msDS-HasInstantiatedNCs' SYNTAX '1.2.840.113556.1.4.903' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.79 NAME 'minPwdLength' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.32 NAME 'domainPolicyObject' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' SINGLE-VALUE ) -attributeTypes: ( 2.5.4.19 NAME 'physicalDeliveryOfficeName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.507 NAME 'volumeCount' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1171 NAME 'msRADIUSServiceType' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.52 NAME 'lastLogon' SYNTAX '1.2.840.113556.1.4.906' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.344 NAME 'groupsToIgnore' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.1358 NAME 'schemaInfo' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' NO-USER-MODIFICATION ) -attributeTypes: ( 0.9.2342.19200300.100.1.25 NAME 'dc' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.782 NAME 'objectCategory' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' SINGLE-VALUE ) -attributeTypes: ( 2.5.18.2 NAME 'modifyTimeStamp' SYNTAX '1.3.6.1.4.1.1466.115.121.1.24' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.2.13 NAME 'displayName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.226 NAME 'adminDescription' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1719 NAME 'msDS-DnsRootAlias' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.498 NAME 'creationWizard' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.15 NAME 'hasPartialReplicaNCs' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.200 NAME 'controlAccessRights' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' ) -attributeTypes: ( 1.2.840.113556.1.4.155 NAME 'uASCompat' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.146 NAME 'objectSid' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 2.5.4.12 NAME 'title' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.118 NAME 'otherPager' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.261 NAME 'division' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.35 NAME 'rangeUpper' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.218 NAME 'oMObjectClass' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.2.49 NAME 'mAPIID' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.302 NAME 'sAMAccountType' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.370 NAME 'objectClassCategory' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.518 NAME 'defaultHidingValue' SYNTAX '1.3.6.1.4.1.1466.115.121.1.7' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1119 NAME 'msNPAllowDialin' SYNTAX '1.3.6.1.4.1.1466.115.121.1.7' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.16 NAME 'codePage' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.150 NAME 'adminCount' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.481 NAME 'schemaUpdate' SYNTAX '1.3.6.1.4.1.1466.115.121.1.24' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.132 NAME 'trustDirection' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.557 NAME 'Enabled' SYNTAX '1.3.6.1.4.1.1466.115.121.1.7' SINGLE-VALUE ) -attributeTypes: ( 2.5.4.7 NAME 'l' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.268 NAME 'eFSPolicy' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' ) -attributeTypes: ( 1.2.840.113556.1.4.14 NAME 'builtinModifiedCount' SYNTAX '1.2.840.113556.1.4.906' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.18 NAME 'otherTelephone' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.649 NAME 'primaryInternationalISDNNumber' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.35 NAME 'employeeID' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.54 NAME 'tombstoneLifetime' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.365 NAME 'operatingSystemServicePack' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.358 NAME 'netbootInitialization' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.656 NAME 'userPrincipalName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.771 NAME 'servicePrincipalName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.91 NAME 'otherLoginWorkstations' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.1786 NAME 'msIIS-FTPDir' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1443 NAME 'msDS-Site-Affinity' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' ) -attributeTypes: ( 1.2.840.113556.1.4.76 NAME 'maxStorage' SYNTAX '1.2.840.113556.1.4.906' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.281 NAME 'nTSecurityDescriptor' SYNTAX '1.2.840.113556.1.4.907' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.513 NAME 'siteObjectBL' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.608 NAME 'queryPolicyBL' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.640 NAME 'partialAttributeSet' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 2.5.4.49 NAME 'distinguishedName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 2.5.4.13 NAME 'description' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.1816 NAME 'msDS-AzClassId' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.370 NAME 'rIDAvailablePool' SYNTAX '1.2.840.113556.1.4.906' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.563 NAME 'shellPropertyPages' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.1715 NAME 'msDS-SPNSuffixes' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.101 NAME 'privateKey' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE ) -attributeTypes: ( 2.5.4.23 NAME 'facsimileTelephoneNumber' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.334 NAME 'searchFlags' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.120 NAME 'schemaFlagsEx' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1212 NAME 'isEphemeral' SYNTAX '1.3.6.1.4.1.1466.115.121.1.7' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.960 NAME 'mSMQNt4Stub' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' ) -attributeTypes: ( 1.2.840.113556.1.4.1785 NAME 'msIIS-FTPRoot' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.345 NAME 'groupPriority' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.819 NAME 'bridgeheadTransportList' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' ) -attributeTypes: ( 1.2.840.113556.1.4.908 NAME 'extendedClassInfo' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.511 NAME 'flatName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.301 NAME 'wbemPath' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.1706 NAME 'msDS-NCReplOutboundNeighbors' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.1809 NAME 'msDS-OperationsForAzTaskBL' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.2.169 NAME 'showInAdvancedViewOnly' SYNTAX '1.3.6.1.4.1.1466.115.121.1.7' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1459 NAME 'msDS-Behavior-Version' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.1836 NAME 'msDS-hasMasterNCs' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.95 NAME 'pwdHistoryLength' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.865 NAME 'pekList' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE ) -attributeTypes: ( 2.5.4.17 NAME 'postalCode' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1241 NAME 'netbootMirrorDataFile' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.213 NAME 'defaultClassStore' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' ) -attributeTypes: ( 1.2.840.113556.1.4.953 NAME 'mSMQSiteID' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.644 NAME 'showInAddressBook' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' ) -attributeTypes: ( 1.2.840.113556.1.2.2 NAME 'whenCreated' SYNTAX '1.3.6.1.4.1.1466.115.121.1.24' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.1357 NAME 'dSCorePropagationData' SYNTAX '1.3.6.1.4.1.1466.115.121.1.24' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.2.353 NAME 'displayNamePrintable' SYNTAX '1.3.6.1.4.1.1466.115.121.1.26' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.624 NAME 'ipsecOwnersReference' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' ) -attributeTypes: ( 2.5.4.8 NAME 'st' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.515 NAME 'serverReference' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1820 NAME 'msDS-HasDomainNCs' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.2.115 NAME 'invocationId' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.109 NAME 'replicaSource' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.721 NAME 'ipPhone' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.277 NAME 'otherHomePhone' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 2.5.4.10 NAME 'o' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.2.380 NAME 'extendedCharsAllowed' SYNTAX '1.3.6.1.4.1.1466.115.121.1.7' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.363 NAME 'operatingSystem' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1840 NAME 'msDS-ObjectReference' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' ) -attributeTypes: ( 1.2.840.113556.1.4.1308 NAME 'mSMQInterval1' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.153 NAME 'rid' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.139 NAME 'profilePath' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1145 NAME 'msRADIUSCallbackNumber' SYNTAX '1.3.6.1.4.1.1466.115.121.1.26' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.772 NAME 'aCSPolicyName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.81 NAME 'info' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1841 NAME 'msDS-ObjectReferenceBL' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.2.3 NAME 'whenChanged' SYNTAX '1.3.6.1.4.1.1466.115.121.1.24' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.2.121 NAME 'uSNLastObjRem' SYNTAX '1.2.840.113556.1.4.906' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.2.83 NAME 'repsTo' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.4 NAME 'replUpToDateVector' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.864 NAME 'netbootSCPBL' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.1837 NAME 'msDs-masteredBy' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.1424 NAME 'msCOM-PartitionSetLink' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' NO-USER-MODIFICATION ) -attributeTypes: ( 2.5.4.3 NAME 'cn' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1789 NAME 'msDS-AllUsersTrustQuota' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.480 NAME 'defaultGroup' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.629 NAME 'ipsecFilterReference' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' ) -attributeTypes: ( 1.2.840.113556.1.4.156 NAME 'comment' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1440 NAME 'msDs-Schema-Extensions' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.56 NAME 'localPolicyFlags' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1309 NAME 'mSMQInterval2' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.609 NAME 'sIDHistory' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' ) -attributeTypes: ( 1.2.840.113556.1.4.90 NAME 'unicodePwd' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1190 NAME 'msRASSavedFramedIPAddress' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1843 NAME 'msDRM-IdentityCertificate' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' ) -attributeTypes: ( 1.2.840.113556.1.4.51 NAME 'lastLogoff' SYNTAX '1.2.840.113556.1.4.906' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.598 NAME 'dmdName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.593 NAME 'msExchLabeledURI' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.2.436 NAME 'directReports' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.3 NAME 'replPropertyMetaData' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.910 NAME 'fromEntry' SYNTAX '1.3.6.1.4.1.1466.115.121.1.7' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.471 NAME 'trustParent' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.622 NAME 'ipsecDataType' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.623 NAME 'ipsecData' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.368 NAME 'rIDManagerReference' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.73 NAME 'lockoutThreshold' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.346 NAME 'desktopProfile' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.131 NAME 'co' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 2.5.4.22 NAME 'teletexTerminalIdentifier' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' ) -attributeTypes: ( 1.2.840.113556.1.4.648 NAME 'primaryTelexNumber' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 0.9.2342.19200300.100.1.10 NAME 'manager' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.514 NAME 'physicalLocationObject' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1824 NAME 'msDS-AzMajorVersion' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.21 NAME 'subClassOf' SYNTAX '1.3.6.1.4.1.1466.115.121.1.38' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.197 NAME 'systemMustContain' SYNTAX '1.3.6.1.4.1.1466.115.121.1.38' NO-USER-MODIFICATION ) -attributeTypes: ( 0.9.2342.19200300.100.1.6 NAME 'roomNumber' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.2.613 NAME 'employeeType' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.27 NAME 'currentValue' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE ) -attributeTypes: ( 2.5.21.2 NAME 'dITContentRules' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.1348 NAME 'gPCMachineExtensionNames' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.19 NAME 'uSNCreated' SYNTAX '1.2.840.113556.1.4.906' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.2.7 NAME 'subRefs' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.2.210 NAME 'proxyAddresses' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.532 NAME 'superiorDNSRoot' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.674 NAME 'rootTrust' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' ) -attributeTypes: ( 1.2.840.113556.1.4.615 NAME 'shellContextMenu' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.610 NAME 'classDisplayName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.620 NAME 'ipsecName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 2.5.4.37 NAME 'cACertificate' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' ) -attributeTypes: ( 1.2.840.113556.1.4.628 NAME 'ipsecNegotiationPolicyReference' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.650 NAME 'mhsORAddress' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.94 NAME 'ntPwdHistory' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' ) -attributeTypes: ( 1.2.840.113556.1.4.786 NAME 'mailAddress' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.356 NAME 'foreignIdentifier' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.2.120 NAME 'uSNChanged' SYNTAX '1.2.840.113556.1.4.906' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.2.91 NAME 'repsFrom' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.1359 NAME 'otherWellKnownObjects' SYNTAX '1.2.840.113556.1.4.903' ) -attributeTypes: ( 1.2.840.113556.1.4.1704 NAME 'msDS-NCReplCursors' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.4.654 NAME 'managedObjects' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.1710 NAME 'msDS-AllowedDNSSuffixes' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' ) -attributeTypes: ( 1.2.840.113556.1.2.16 NAME 'nCName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' SINGLE-VALUE NO-USER-MODIFICATION ) -attributeTypes: ( 1.2.840.113556.1.4.87 NAME 'nETBIOSName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.1355 NAME 'queryFilter' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 2.5.4.28 NAME 'preferredDeliveryMethod' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' ) -attributeTypes: ( 1.2.840.113556.1.4.961 NAME 'mSMQSiteForeign' SYNTAX '1.3.6.1.4.1.1466.115.121.1.7' ) -attributeTypes: ( 0.9.2342.19200300.100.1.55 NAME 'audio' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' ) -attributeTypes: ( 1.2.840.113556.1.4.62 NAME 'scriptPath' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.948 NAME 'mSMQDigests' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' ) -attributeTypes: ( 1.2.840.113556.1.4.1441 NAME 'msDS-Cached-Membership' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.64 NAME 'logonHours' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE ) -attributeTypes: ( 1.2.840.113556.1.4.894 NAME 'gPCFileSysPath' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE ) -dITContentRules: ( 1.2.840.113556.1.5.67 NAME 'domainDNS' AUX ( samDomain ) MAY ( treeName $ rIDManagerReference $ replicaSource $ pwdProperties $ pwdHistoryLength $ privateKey $ pekList $ pekKeyChangeInterval $ nTMixedDomain $ nextRid $ nETBIOSName $ msDS-PerUserTrustTombstonesQuota $ msDS-PerUserTrustQuota $ ms-DS-MachineAccountQuota $ msDS-LogonTimeSyncInterval $ msDS-AllUsersTrustQuota $ modifiedCountAtLastProm $ minPwdLength $ minPwdAge $ maxPwdAge $ lSAModifiedCount $ lSACreationTime $ lockoutThreshold $ lockoutDuration $ lockOutObservationWindow $ gPOptions $ gPLink $ eFSPolicy $ domainPolicyObject $ desktopProfile $ description $ defaultLocalPolicyObject $ creationTime $ controlAccessRights $ cACertificate $ builtinModifiedCount $ builtinCreationTime $ auditingPolicy ) ) -dITContentRules: ( 1.2.840.113556.1.5.4 NAME 'builtinDomain' AUX ( samDomainBase ) MAY ( uASCompat $ serverState $ serverRole $ revision $ pwdProperties $ pwdHistoryLength $ oEMInformation $ objectSid $ nTSecurityDescriptor $ nextRid $ modifiedCountAtLastProm $ modifiedCount $ minPwdLength $ minPwdAge $ maxPwdAge $ lockoutThreshold $ lockoutDuration $ lockOutObservationWindow $ forceLogoff $ domainReplica $ creationTime ) ) -dITContentRules: ( 1.2.840.113556.1.5.3 NAME 'samDomain' AUX ( samDomainBase ) MAY ( uASCompat $ serverState $ serverRole $ revision $ pwdProperties $ pwdHistoryLength $ oEMInformation $ objectSid $ nTSecurityDescriptor $ nextRid $ modifiedCountAtLastProm $ modifiedCount $ minPwdLength $ minPwdAge $ maxPwdAge $ lockoutThreshold $ lockoutDuration $ lockOutObservationWindow $ forceLogoff $ domainReplica $ creationTime ) ) -dITContentRules: ( 1.2.840.113556.1.5.9 NAME 'user' AUX ( securityPrincipal $ mailRecipient ) MUST ( sAMAccountName $ objectSid $ cn ) MAY ( supplementalCredentials $ sIDHistory $ securityIdentifier $ sAMAccountType $ rid $ tokenGroupsNoGCAcceptable $ tokenGroupsGlobalAndUniversal $ tokenGroups $ nTSecurityDescriptor $ msDS-KeyVersionNumber $ altSecurityIdentities $ accountNameHistory $ userSMIMECertificate $ secretary $ msExchLabeledURI $ msExchAssistantName $ labeledURI $ userCertificate $ userCert $ textEncodedORAddress $ telephoneNumber $ showInAddressBook $ legacyExchangeDN $ garbageCollPeriod $ info $ userSMIMECertificate $ secretary $ msExchLabeledURI $ msExchAssistantName $ labeledURI ) ) -dITContentRules: ( 1.2.840.113556.1.5.8 NAME 'group' AUX ( mailRecipient $ securityPrincipal ) MUST ( cn $ sAMAccountName $ objectSid $ cn ) MAY ( userSMIMECertificate $ secretary $ msExchLabeledURI $ msExchAssistantName $ labeledURI $ userCertificate $ userCert $ textEncodedORAddress $ telephoneNumber $ showInAddressBook $ legacyExchangeDN $ garbageCollPeriod $ info $ userSMIMECertificate $ secretary $ msExchLabeledURI $ msExchAssistantName $ labeledURI $ userCertificate $ userCert $ textEncodedORAddress $ telephoneNumber $ showInAddressBook $ legacyExchangeDN $ garbageCollPeriod $ info $ userSMIMECertificate $ secretary $ msExchLabeledURI $ msExchAssistantName $ labeledURI $ supplementalCredentials $ sIDHistory $ securityIdentifier $ sAMAccountType $ rid $ tokenGroupsNoGCAcceptable $ tokenGroupsGlobalAndUniversal $ tokenGroups $ nTSecurityDescriptor $ msDS-KeyVersionNumber $ altSecurityIdentities $ accountNameHistory $ userSMIMECertificate $ secretary $ msExchLabeledURI $ msExchAssistantName $ labeledURI $ userCertificate $ userCert $ textEncodedORAddress $ telephoneNumber $ showInAddressBook $ legacyExchangeDN $ garbageCollPeriod $ info $ userSMIMECertificate $ secretary $ msExchLabeledURI $ msExchAssistantName $ labeledURI ) ) diff --git a/source4/setup/slapd.conf b/source4/setup/slapd.conf index 4dcfd2aba7..141c0cd27a 100644 --- a/source4/setup/slapd.conf +++ b/source4/setup/slapd.conf @@ -1,5 +1,10 @@ loglevel 0 +### Multimaster-ServerIDs and URLs ### + +${MMR_SERVERIDS_CONFIG} + + include ${LDAPDIR}/backend-schema.schema pidfile ${LDAPDIR}/slapd.pid @@ -52,10 +57,12 @@ suffix cn=Samba directory ${LDAPDIR}/db/samba rootdn cn=Manager,cn=Samba - +######################################## +### cn=schema ### database hdb suffix ${SCHEMADN} rootdn cn=Manager,${SCHEMADN} +rootpw "${MMR_PASSWORD}" directory ${LDAPDIR}/db/schema index objectClass eq index samAccountName eq @@ -64,16 +71,25 @@ index objectCategory eq index lDAPDisplayName eq index subClassOf eq index cn eq +index entryUUID,entryCSN eq #syncprov is stable in OpenLDAP 2.3, and available in 2.2. #We only need this for the contextCSN attribute anyway.... overlay syncprov -syncprov-checkpoint 100 10 syncprov-sessionlog 100 +# syncprov-checkpoint 100 10 + +### Multimaster-Replication of cn=schema Subcontext ### +${MMR_SYNCREPL_SCHEMA_CONFIG} +${MIRRORMODE} + +######################################### +### cn=config ### database hdb suffix ${CONFIGDN} rootdn cn=Manager,${CONFIGDN} +rootpw "${MMR_PASSWORD}" directory ${LDAPDIR}/db/config index objectClass eq index samAccountName eq @@ -85,16 +101,24 @@ index subClassOf eq index dnsRoot eq index nETBIOSName eq index cn eq +index entryUUID,entryCSN eq #syncprov is stable in OpenLDAP 2.3, and available in 2.2. #We only need this for the contextCSN attribute anyway.... overlay syncprov -syncprov-checkpoint 100 10 syncprov-sessionlog 100 +# syncprov-checkpoint 100 10 + +### Multimaster-Replication of cn=config Subcontext ### +${MMR_SYNCREPL_CONFIG_CONFIG} +${MIRRORMODE} +######################################## +### cn=users /base-dn ### database hdb suffix ${DOMAINDN} rootdn cn=Manager,${DOMAINDN} +rootpw "${MMR_PASSWORD}" directory ${LDAPDIR}/db/user index objectClass eq index samAccountName eq @@ -110,10 +134,14 @@ index subClassOf eq index dnsRoot eq index nETBIOSName eq index cn eq +index entryUUID,entryCSN eq #syncprov is stable in OpenLDAP 2.3, and available in 2.2. #We only need this for the contextCSN attribute anyway.... overlay syncprov -syncprov-checkpoint 100 10 syncprov-sessionlog 100 +# syncprov-checkpoint 100 10 +### Multimaster-Replication of cn=user/base-dn context ### +${MMR_SYNCREPL_USER_CONFIG} +${MIRRORMODE} diff --git a/source4/setup/tests/blackbox_provision-backend.sh b/source4/setup/tests/blackbox_provision-backend.sh index 312ca5c70e..04f22dbf1d 100755 --- a/source4/setup/tests/blackbox_provision-backend.sh +++ b/source4/setup/tests/blackbox_provision-backend.sh @@ -13,6 +13,7 @@ shift 1 . `dirname $0`/../../../testprogs/blackbox/subunit.sh testit "openldap-backend" $PYTHON ./setup/provision-backend --domain=FOO --realm=foo.example.com --host-name=samba --ldap-backend-type=openldap --targetdir=$PREFIX/openldap-backend +testit "openldap-mmr-backend" $PYTHON ./setup/provision-backend --domain=FOO --realm=foo.example.com --host-name=samba --ldap-backend-type=openldap --targetdir=$PREFIX/openldap-mmr-backend --ol-mmr-urls='ldap://localdc1:9000,ldap://localdc2:9000,ldap://localdc3:9000' testit "fedora-ds-backend" $PYTHON ./setup/provision-backend --domain=FOO --realm=foo.example.com --host-name=samba --ldap-backend-type=fedora-ds --targetdir=$PREFIX/fedora-ds-backend reprovision() { diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index cfd6c1d01a..1fe6f0b877 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -79,12 +79,12 @@ struct smb2srv_request *smb2srv_init_request(struct smbsrv_connection *smb_conn) NTSTATUS smb2srv_setup_reply(struct smb2srv_request *req, uint16_t body_fixed_size, bool body_dynamic_present, uint32_t body_dynamic_size) { - uint32_t flags = 0x00000001; + uint32_t flags = SMB2_HDR_FLAG_REDIRECT; uint32_t pid = IVAL(req->in.hdr, SMB2_HDR_PID); uint32_t tid = IVAL(req->in.hdr, SMB2_HDR_TID); if (req->pending_id) { - flags |= 0x00000002; + flags |= SMB2_HDR_FLAG_ASYNC; pid = req->pending_id; tid = 0; } @@ -236,7 +236,7 @@ void smb2srv_send_reply(struct smb2srv_request *req) } /* if signing is active on the session then sign the packet */ - if (req->session && req->session->smb2_signing.active) { + if (req->is_signed) { status = smb2_sign_message(&req->out, req->session->session_info->session_key); if (!NT_STATUS_IS_OK(status)) { @@ -310,12 +310,7 @@ static NTSTATUS smb2srv_reply(struct smb2srv_request *req) if (!req->session) goto nosession; - if (!req->session->smb2_signing.active) { - /* TODO: workout the correct error code */ - smb2srv_send_error(req, NT_STATUS_FOOBAR); - return NT_STATUS_OK; - } - + req->is_signed = true; status = smb2_check_signature(&req->in, req->session->session_info->session_key); if (!NT_STATUS_IS_OK(status)) { @@ -511,6 +506,8 @@ static NTSTATUS smb2srv_init_pending(struct smbsrv_connection *smb_conn) NTSTATUS smb2srv_queue_pending(struct smb2srv_request *req) { + NTSTATUS status; + bool signing_used = false; int id; if (req->pending_id) { @@ -526,10 +523,35 @@ NTSTATUS smb2srv_queue_pending(struct smb2srv_request *req) DLIST_ADD_END(req->smb_conn->requests2.list, req, struct smb2srv_request *); req->pending_id = id; + if (req->smb_conn->connection->event.fde == NULL) { + /* the socket has been destroyed - no point trying to send an error! */ + return NT_STATUS_REMOTE_DISCONNECT; + } + talloc_set_destructor(req, smb2srv_request_deny_destructor); - smb2srv_send_error(req, STATUS_PENDING); - talloc_set_destructor(req, smb2srv_request_destructor); + status = smb2srv_setup_reply(req, 8, true, 0); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + SIVAL(req->out.hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING)); + + SSVAL(req->out.body, 0x02, 0); + SIVAL(req->out.body, 0x04, 0); + + /* if the real reply will be signed set the signed flags, but don't sign */ + if (req->is_signed) { + SIVAL(req->out.hdr, SMB2_HDR_FLAGS, IVAL(req->out.hdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_SIGNED); + signing_used = req->is_signed; + req->is_signed = false; + } + + smb2srv_send_reply(req); + + req->is_signed = signing_used; + + talloc_set_destructor(req, smb2srv_request_destructor); return NT_STATUS_OK; } @@ -545,7 +567,7 @@ void smb2srv_cancel_recv(struct smb2srv_request *req) flags = IVAL(req->in.hdr, SMB2_HDR_FLAGS); pending_id = IVAL(req->in.hdr, SMB2_HDR_PID); - if (!(flags & 0x00000002)) { + if (!(flags & SMB2_HDR_FLAG_ASYNC)) { /* TODO: what to do here? */ goto done; } diff --git a/source4/smb_server/smb2/smb2_server.h b/source4/smb_server/smb2/smb2_server.h index ae4abbd71e..d45e0861af 100644 --- a/source4/smb_server/smb2/smb2_server.h +++ b/source4/smb_server/smb2/smb2_server.h @@ -62,6 +62,8 @@ struct smb2srv_request { uint8_t _chained_file_handle[16]; uint8_t *chained_file_handle; + bool is_signed; + struct smb2_request_buffer in; struct smb2_request_buffer out; }; diff --git a/source4/torture/auth/pac.c b/source4/torture/auth/pac.c index 7fdd7e58bf..4e51c66950 100644 --- a/source4/torture/auth/pac.c +++ b/source4/torture/auth/pac.c @@ -279,7 +279,7 @@ static bool torture_pac_saved_check(struct torture_context *tctx) struct auth_serversupplied_info *server_info_out; krb5_keyblock server_keyblock; - krb5_keyblock krbtgt_keyblock; + krb5_keyblock krbtgt_keyblock, *krbtgt_keyblock_p; struct samr_Password *krbtgt_bytes, *krbsrv_bytes; krb5_error_code ret; @@ -309,9 +309,13 @@ static bool torture_pac_saved_check(struct torture_context *tctx) /* The krbtgt key in use when the above PAC was generated. * This is an arcfour-hmac-md5 key, extracted with our 'net * samdump' tool. */ - krbtgt_bytes = smbpasswd_gethexpwd(mem_ctx, pac_kdc_key); - if (!krbtgt_bytes) { - torture_fail(tctx, "(saved test) Could not interpret krbtgt key"); + if (*pac_kdc_key == 0) { + krbtgt_bytes = NULL; + } else { + krbtgt_bytes = smbpasswd_gethexpwd(mem_ctx, pac_kdc_key); + if (!krbtgt_bytes) { + torture_fail(tctx, "(saved test) Could not interpret krbtgt key"); + } } krbsrv_bytes = smbpasswd_gethexpwd(mem_ctx, pac_member_key); @@ -329,18 +333,23 @@ static bool torture_pac_saved_check(struct torture_context *tctx) smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx))); - ret = krb5_keyblock_init(smb_krb5_context->krb5_context, - ENCTYPE_ARCFOUR_HMAC, - krbtgt_bytes->hash, sizeof(krbtgt_bytes->hash), - &krbtgt_keyblock); - if (ret) { - krb5_free_keyblock_contents(smb_krb5_context->krb5_context, - &server_keyblock); - torture_fail(tctx, - talloc_asprintf(tctx, - "(saved test) Server Keyblock encoding failed: %s", - smb_get_krb5_error_message(smb_krb5_context->krb5_context, - ret, mem_ctx))); + if (krbtgt_bytes) { + ret = krb5_keyblock_init(smb_krb5_context->krb5_context, + ENCTYPE_ARCFOUR_HMAC, + krbtgt_bytes->hash, sizeof(krbtgt_bytes->hash), + &krbtgt_keyblock); + if (ret) { + krb5_free_keyblock_contents(smb_krb5_context->krb5_context, + &server_keyblock); + torture_fail(tctx, + talloc_asprintf(tctx, + "(saved test) Server Keyblock encoding failed: %s", + smb_get_krb5_error_message(smb_krb5_context->krb5_context, + ret, mem_ctx))); + } + krbtgt_keyblock_p = &krbtgt_keyblock; + } else { + krbtgt_keyblock_p = NULL; } pac_file = torture_setting_string(tctx, "pac_file", NULL); @@ -363,7 +372,7 @@ static bool torture_pac_saved_check(struct torture_context *tctx) &client_principal); if (ret) { krb5_free_keyblock_contents(smb_krb5_context->krb5_context, - &krbtgt_keyblock); + krbtgt_keyblock_p); krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &server_keyblock); torture_fail(tctx, @@ -379,12 +388,12 @@ static bool torture_pac_saved_check(struct torture_context *tctx) &pac_data, tmp_blob, smb_krb5_context->krb5_context, - &krbtgt_keyblock, + krbtgt_keyblock_p, &server_keyblock, client_principal, authtime, NULL); if (!NT_STATUS_IS_OK(nt_status)) { krb5_free_keyblock_contents(smb_krb5_context->krb5_context, - &krbtgt_keyblock); + krbtgt_keyblock_p); krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &server_keyblock); krb5_free_principal(smb_krb5_context->krb5_context, client_principal); @@ -400,13 +409,13 @@ static bool torture_pac_saved_check(struct torture_context *tctx) &logon_info, tmp_blob, smb_krb5_context->krb5_context, - &krbtgt_keyblock, + krbtgt_keyblock_p, &server_keyblock, client_principal, authtime, NULL); if (!NT_STATUS_IS_OK(nt_status)) { krb5_free_keyblock_contents(smb_krb5_context->krb5_context, - &krbtgt_keyblock); + krbtgt_keyblock_p); krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &server_keyblock); krb5_free_principal(smb_krb5_context->krb5_context, client_principal); @@ -424,7 +433,7 @@ static bool torture_pac_saved_check(struct torture_context *tctx) &server_info_out); if (!NT_STATUS_IS_OK(nt_status)) { krb5_free_keyblock_contents(smb_krb5_context->krb5_context, - &krbtgt_keyblock); + krbtgt_keyblock_p); krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &server_keyblock); krb5_free_principal(smb_krb5_context->krb5_context, client_principal); @@ -440,7 +449,7 @@ static bool torture_pac_saved_check(struct torture_context *tctx) "S-1-5-21-3048156945-3961193616-3706469200-1005"), server_info_out->account_sid)) { krb5_free_keyblock_contents(smb_krb5_context->krb5_context, - &krbtgt_keyblock); + krbtgt_keyblock_p); krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &server_keyblock); krb5_free_principal(smb_krb5_context->krb5_context, client_principal); @@ -452,17 +461,25 @@ static bool torture_pac_saved_check(struct torture_context *tctx) dom_sid_string(mem_ctx, server_info_out->account_sid))); } + if (krbtgt_bytes == NULL) { + torture_comment(tctx, "skipping PAC encoding tests as non kdc key\n"); + krb5_free_keyblock_contents(smb_krb5_context->krb5_context, + &server_keyblock); + krb5_free_principal(smb_krb5_context->krb5_context, client_principal); + return true; + } + ret = kerberos_encode_pac(mem_ctx, lp_iconv_convenience(tctx->lp_ctx), pac_data, smb_krb5_context->krb5_context, - &krbtgt_keyblock, + krbtgt_keyblock_p, &server_keyblock, &validate_blob); if (ret != 0) { krb5_free_keyblock_contents(smb_krb5_context->krb5_context, - &krbtgt_keyblock); + krbtgt_keyblock_p); krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &server_keyblock); krb5_free_principal(smb_krb5_context->krb5_context, client_principal); @@ -478,7 +495,7 @@ static bool torture_pac_saved_check(struct torture_context *tctx) */ if (tmp_blob.length != validate_blob.length) { krb5_free_keyblock_contents(smb_krb5_context->krb5_context, - &krbtgt_keyblock); + krbtgt_keyblock_p); krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &server_keyblock); krb5_free_principal(smb_krb5_context->krb5_context, client_principal); @@ -491,7 +508,7 @@ static bool torture_pac_saved_check(struct torture_context *tctx) if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) { krb5_free_keyblock_contents(smb_krb5_context->krb5_context, - &krbtgt_keyblock); + krbtgt_keyblock_p); krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &server_keyblock); krb5_free_principal(smb_krb5_context->krb5_context, client_principal); @@ -508,14 +525,14 @@ static bool torture_pac_saved_check(struct torture_context *tctx) lp_iconv_convenience(tctx->lp_ctx), server_info_out, smb_krb5_context->krb5_context, - &krbtgt_keyblock, + krbtgt_keyblock_p, &server_keyblock, client_principal, authtime, &validate_blob); if (ret != 0) { krb5_free_keyblock_contents(smb_krb5_context->krb5_context, - &krbtgt_keyblock); + krbtgt_keyblock_p); krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &server_keyblock); krb5_free_principal(smb_krb5_context->krb5_context, client_principal); @@ -541,7 +558,7 @@ static bool torture_pac_saved_check(struct torture_context *tctx) NDR_PRINT_DEBUG(PAC_DATA, &pac_data2); krb5_free_keyblock_contents(smb_krb5_context->krb5_context, - &krbtgt_keyblock); + krbtgt_keyblock_p); krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &server_keyblock); krb5_free_principal(smb_krb5_context->krb5_context, client_principal); @@ -563,7 +580,7 @@ static bool torture_pac_saved_check(struct torture_context *tctx) NDR_PRINT_DEBUG(PAC_DATA, &pac_data2); krb5_free_keyblock_contents(smb_krb5_context->krb5_context, - &krbtgt_keyblock); + krbtgt_keyblock_p); krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &server_keyblock); krb5_free_principal(smb_krb5_context->krb5_context, client_principal); @@ -583,14 +600,14 @@ static bool torture_pac_saved_check(struct torture_context *tctx) &pac_data, tmp_blob, smb_krb5_context->krb5_context, - &krbtgt_keyblock, + krbtgt_keyblock_p, &server_keyblock, client_principal, authtime + 1, NULL); if (NT_STATUS_IS_OK(nt_status)) { krb5_free_keyblock_contents(smb_krb5_context->krb5_context, - &krbtgt_keyblock); + krbtgt_keyblock_p); krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &server_keyblock); krb5_free_principal(smb_krb5_context->krb5_context, client_principal); @@ -608,7 +625,7 @@ static bool torture_pac_saved_check(struct torture_context *tctx) if (ret) { krb5_free_keyblock_contents(smb_krb5_context->krb5_context, - &krbtgt_keyblock); + krbtgt_keyblock_p); krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &server_keyblock); torture_fail(tctx, talloc_asprintf(tctx, @@ -621,13 +638,13 @@ static bool torture_pac_saved_check(struct torture_context *tctx) &pac_data, tmp_blob, smb_krb5_context->krb5_context, - &krbtgt_keyblock, + krbtgt_keyblock_p, &server_keyblock, client_principal, authtime, NULL); if (NT_STATUS_IS_OK(nt_status)) { krb5_free_keyblock_contents(smb_krb5_context->krb5_context, - &krbtgt_keyblock); + krbtgt_keyblock_p); krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &server_keyblock); torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on modified principal"); @@ -641,20 +658,20 @@ static bool torture_pac_saved_check(struct torture_context *tctx) &pac_data, tmp_blob, smb_krb5_context->krb5_context, - &krbtgt_keyblock, + krbtgt_keyblock_p, &server_keyblock, client_principal, authtime, NULL); if (NT_STATUS_IS_OK(nt_status)) { krb5_free_keyblock_contents(smb_krb5_context->krb5_context, - &krbtgt_keyblock); + krbtgt_keyblock_p); krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &server_keyblock); torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on broken checksum"); } krb5_free_keyblock_contents(smb_krb5_context->krb5_context, - &krbtgt_keyblock); + krbtgt_keyblock_p); krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &server_keyblock); return true; @@ -666,9 +683,7 @@ struct torture_suite *torture_pac(TALLOC_CTX *mem_ctx) torture_suite_add_simple_test(suite, "self check", torture_pac_self_check); - torture_suite_add_simple_test(suite, "saved check", torture_pac_saved_check); - return suite; } diff --git a/source4/torture/ldap/cldap.c b/source4/torture/ldap/cldap.c index 1631297793..3730193c86 100644 --- a/source4/torture/ldap/cldap.c +++ b/source4/torture/ldap/cldap.c @@ -228,6 +228,75 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest) } /* + test cldap netlogon server type flags +*/ +static bool test_cldap_netlogon_flags(struct torture_context *tctx, + const char *dest) +{ + struct cldap_socket *cldap; + NTSTATUS status; + struct cldap_netlogon search; + struct netlogon_samlogon_response n1; + uint32_t server_type; + + cldap = cldap_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx)); + + printf("Printing out netlogon server type flags:\n"); + + ZERO_STRUCT(search); + search.in.dest_address = dest; + search.in.dest_port = lp_cldap_port(tctx->lp_ctx); + search.in.acct_control = -1; + search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX; + search.in.map_response = true; + + status = cldap_netlogon(cldap, tctx, &search); + CHECK_STATUS(status, NT_STATUS_OK); + + n1 = search.out.netlogon; + if (n1.ntver == NETLOGON_NT_VERSION_5) + server_type = n1.nt5.server_type; + else if (n1.ntver == NETLOGON_NT_VERSION_5EX) + server_type = n1.nt5_ex.server_type; + + printf("The word is: %i\n", server_type); + if (server_type & NBT_SERVER_PDC) + printf("NBT_SERVER_PDC "); + if (server_type & NBT_SERVER_GC) + printf("NBT_SERVER_GC "); + if (server_type & NBT_SERVER_LDAP) + printf("NBT_SERVER_LDAP "); + if (server_type & NBT_SERVER_DS) + printf("NBT_SERVER_DS "); + if (server_type & NBT_SERVER_KDC) + printf("NBT_SERVER_KDC "); + if (server_type & NBT_SERVER_TIMESERV) + printf("NBT_SERVER_TIMESERV "); + if (server_type & NBT_SERVER_CLOSEST) + printf("NBT_SERVER_CLOSEST "); + if (server_type & NBT_SERVER_WRITABLE) + printf("NBT_SERVER_WRITABLE "); + if (server_type & NBT_SERVER_GOOD_TIMESERV) + printf("NBT_SERVER_GOOD_TIMESERV "); + if (server_type & NBT_SERVER_NDNC) + printf("NBT_SERVER_NDNC "); + if (server_type & NBT_SERVER_SEL_SEC_DOM_6) + printf("NBT_SERVER_SEL_SEC_DOM_6 "); + if (server_type & NBT_SERVER_FUL_SEC_DOM_6) + printf("NBT_SERVER_FUL_SEC_DOM_6 "); + if (server_type & NBT_SERVER_DS_DNS_CONTR) + printf("NBT_SERVER_DS_DNS_CONTR "); + if (server_type & NBT_SERVER_DS_DNS_DOMAIN) + printf("NBT_SERVER_DS_DNS_DOMAIN "); + if (server_type & NBT_SERVER_DS_DNS_FOREST) + printf("NBT_SERVER_DS_DNS_FOREST "); + + printf("\n"); + + return true; +} + +/* convert a ldap result message to a ldb message. This allows us to use the convenient ldif dump routines in ldb to print out cldap search results @@ -266,6 +335,81 @@ static void cldap_dump_results(struct cldap_search *search) talloc_free(ldb); } + +/* + test cldap netlogon server type flag "NBT_SERVER_DS_DNS_FOREST" +*/ +static bool test_cldap_netlogon_flag_ds_dns_forest(struct torture_context *tctx, + const char *dest) +{ + struct cldap_socket *cldap; + NTSTATUS status; + struct cldap_netlogon search; + uint32_t server_type; + struct netlogon_samlogon_response n1; + + bool result = true; + + cldap = cldap_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx)); + + printf("Testing netlogon server type flag NBT_SERVER_DS_DNS_FOREST: "); + + ZERO_STRUCT(search); + search.in.dest_address = dest; + search.in.dest_port = lp_cldap_port(tctx->lp_ctx); + search.in.acct_control = -1; + search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX; + search.in.map_response = true; + + status = cldap_netlogon(cldap, tctx, &search); + CHECK_STATUS(status, NT_STATUS_OK); + + n1 = search.out.netlogon; + if (n1.ntver == NETLOGON_NT_VERSION_5) + server_type = n1.nt5.server_type; + else if (n1.ntver == NETLOGON_NT_VERSION_5EX) + server_type = n1.nt5_ex.server_type; + + if (server_type & NBT_SERVER_DS_DNS_FOREST) { + struct cldap_search search2; + const char *attrs[] = { "defaultNamingContext", "rootDomainNamingContext", + NULL }; + struct ldb_context *ldb; + struct ldb_message *msg; + + /* Trying to fetch the attributes "defaultNamingContext" and + "rootDomainNamingContext" */ + ZERO_STRUCT(search2); + search2.in.dest_address = dest; + search2.in.dest_port = lp_cldap_port(tctx->lp_ctx); + search2.in.timeout = 10; + search2.in.retries = 3; + search2.in.filter = "(objectclass=*)"; + search2.in.attributes = attrs; + + status = cldap_search(cldap, tctx, &search2); + CHECK_STATUS(status, NT_STATUS_OK); + + ldb = ldb_init(NULL, NULL); + + msg = ldap_msg_to_ldb(ldb, ldb, search2.out.response); + + /* Try to compare the two attributes */ + if (ldb_msg_element_compare(ldb_msg_find_element(msg, attrs[0]), + ldb_msg_find_element(msg, attrs[1]))) + result = false; + + talloc_free(ldb); + } + + if (result) + printf("passed\n"); + else + printf("failed\n"); + + return result; +} + /* test generic cldap operations */ @@ -343,6 +487,8 @@ bool torture_cldap(struct torture_context *torture) const char *host = torture_setting_string(torture, "host", NULL); ret &= test_cldap_netlogon(torture, host); + ret &= test_cldap_netlogon_flags(torture, host); + ret &= test_cldap_netlogon_flag_ds_dns_forest(torture, host); ret &= test_cldap_generic(torture, host); return ret; diff --git a/source4/torture/nbt/dgram.c b/source4/torture/nbt/dgram.c index 665a08bd5c..eac2b1fe30 100644 --- a/source4/torture/nbt/dgram.c +++ b/source4/torture/nbt/dgram.c @@ -291,6 +291,10 @@ static bool nbt_test_netlogon2(struct torture_context *tctx) join_ctx = torture_join_domain(tctx, TEST_NAME, ACB_WSTRUST, &machine_credentials); + torture_assert(tctx, join_ctx != NULL, + talloc_asprintf(tctx, "Failed to join domain %s as %s\n", + lp_workgroup(tctx->lp_ctx), TEST_NAME)); + dom_sid = torture_join_sid(join_ctx); /* setup (another) temporary mailslot listener for replies */ diff --git a/source4/torture/nbt/winsreplication.c b/source4/torture/nbt/winsreplication.c index ee7a1510d5..6b600bd7cd 100644 --- a/source4/torture/nbt/winsreplication.c +++ b/source4/torture/nbt/winsreplication.c @@ -6701,7 +6701,6 @@ static bool test_conflict_owned_active_vs_replica(struct torture_context *tctx, /* * unique vs. unique section */ -#if METZE_NEEDS_TO_LOOK_AT_THIS_ONE /* * unique,active vs. unique,active with same ip(s), unchecked */ @@ -6728,7 +6727,6 @@ static bool test_conflict_owned_active_vs_replica(struct torture_context *tctx, .apply_expected = true }, }, -#endif /* * unique,active vs. unique,active with different ip(s), positive response */ @@ -8967,7 +8965,6 @@ static bool test_conflict_owned_active_vs_replica(struct torture_context *tctx, .sgroup_merge = true }, }, -#if 0 /* * sgroup,active vs. sgroup,active with same ip(s) */ @@ -9157,7 +9154,6 @@ static bool test_conflict_owned_active_vs_replica(struct torture_context *tctx, .apply_expected = false }, }, -#endif }; if (!ctx->nbtsock_srv) { @@ -9543,7 +9539,9 @@ static void test_conflict_owned_active_vs_replica_handler_query(struct nbt_name_ talloc_free(rep_packet); /* make sure we push the reply to the wire */ - event_loop_once(nbtsock->event_ctx); + while (nbtsock->send_queue) { + event_loop_once(nbtsock->event_ctx); + } msleep(1000); rec->defend.timeout = 0; @@ -9598,7 +9596,9 @@ static void test_conflict_owned_active_vs_replica_handler_release( talloc_free(rep_packet); /* make sure we push the reply to the wire */ - event_loop_once(nbtsock->event_ctx); + while (nbtsock->send_queue) { + event_loop_once(nbtsock->event_ctx); + } msleep(1000); rec->defend.timeout = 0; diff --git a/source4/torture/raw/offline.c b/source4/torture/raw/offline.c index 9c66c3be9c..f2f0bf5d27 100644 --- a/source4/torture/raw/offline.c +++ b/source4/torture/raw/offline.c @@ -108,8 +108,11 @@ static void loadfile_callback(struct composite_context *ctx) } for (i=0;i<FILE_SIZE;i++) { - if (state->loadfile->out.data[i] != state->fnumber % 256) { - printf("Bad data in file %u\n", state->fnumber); + if (state->loadfile->out.data[i] != 1+(state->fnumber % 255)) { + printf("Bad data in file %u (got %u expected %u)\n", + state->fnumber, + state->loadfile->out.data[i], + 1+(state->fnumber % 255)); test_failed++; return; } @@ -253,7 +256,7 @@ static void test_offline(struct offline_state *state) state->savefile->in.fname = state->fname; state->savefile->in.data = talloc_size(state->savefile, FILE_SIZE); state->savefile->in.size = FILE_SIZE; - memset(state->savefile->in.data, state->fnumber, FILE_SIZE); + memset(state->savefile->in.data, 1+(state->fnumber%255), FILE_SIZE); ctx = smb_composite_savefile_send(state->tree, state->savefile); if (ctx == NULL) { @@ -344,12 +347,16 @@ static void report_rate(struct event_context *ev, struct timed_event *te, total_online += state[i].online_count; total_offline += state[i].offline_count; } - printf("ops/s=%4u offline=%5u online=%4u set_lat=%.1f get_lat=%.1f save_lat=%.1f load_lat=%.1f\r", + printf("ops/s=%4u offline=%5u online=%4u set_lat=%.1f/%.1f get_lat=%.1f/%.1f save_lat=%.1f/%.1f load_lat=%.1f/%.1f\n", total, total_offline, total_online, latencies[OP_SETOFFLINE], + worst_latencies[OP_SETOFFLINE], latencies[OP_GETOFFLINE], + worst_latencies[OP_GETOFFLINE], latencies[OP_SAVEFILE], - latencies[OP_LOADFILE]); + worst_latencies[OP_SAVEFILE], + latencies[OP_LOADFILE], + worst_latencies[OP_LOADFILE]); fflush(stdout); event_add_timed(ev, state, timeval_current_ofs(1, 0), report_rate, state); @@ -436,7 +443,7 @@ bool torture_test_offline(struct torture_context *torture) char buf[FILE_SIZE]; NTSTATUS status; - memset(buf, i % 256, sizeof(buf)); + memset(buf, 1+(i % 255), sizeof(buf)); fnum = smbcli_open(state[0].tree, fname, O_RDWR|O_CREAT, DENY_NONE); if (fnum == -1) { diff --git a/source4/torture/raw/open.c b/source4/torture/raw/open.c index b6979fa0d9..f3494ea3d0 100644 --- a/source4/torture/raw/open.c +++ b/source4/torture/raw/open.c @@ -844,6 +844,8 @@ static bool test_nttrans_create(struct smbcli_state *cli, struct torture_context int fnum = -1; bool ret = true; int i; + uint32_t ok_mask, not_supported_mask, invalid_parameter_mask; + uint32_t not_a_directory_mask, unexpected_mask; struct { uint32_t open_disp; bool with_file; @@ -982,6 +984,10 @@ static bool test_nttrans_create(struct smbcli_state *cli, struct torture_context } io.ntcreatex.in.create_options = create_option; status = smb_raw_open(cli->tree, tctx, &io); + if (!NT_STATUS_IS_OK(status)) { + printf("ntcreatex create option 0x%08x gave %s - should give NT_STATUS_OK\n", + create_option, nt_errstr(status)); + } CHECK_STATUS(status, NT_STATUS_OK); fnum = io.ntcreatex.out.file.fnum; @@ -999,6 +1005,44 @@ static bool test_nttrans_create(struct smbcli_state *cli, struct torture_context smbcli_close(cli->tree, fnum); } + io.ntcreatex.in.file_attr = 0; + io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF; + io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; + + /* Check for options that should return NOT_SUPPORTED, OK or INVALID_PARAMETER */ + ok_mask = 0; + not_supported_mask = 0; + invalid_parameter_mask = 0; + not_a_directory_mask = 0; + unexpected_mask = 0; + for (i=0; i < 32; i++) { + uint32_t create_option = 1<<i; + if (create_option & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) { + continue; + } + io.ntcreatex.in.create_options = create_option; + status = smb_raw_open(cli->tree, tctx, &io); + if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { + not_supported_mask |= create_option; + } else if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) { + ok_mask |= create_option; + smbcli_close(cli->tree, io.ntcreatex.out.file.fnum); + } else if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) { + invalid_parameter_mask |= create_option; + } else if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_A_DIRECTORY)) { + not_a_directory_mask |= 1<<i; + } else { + unexpected_mask |= 1<<i; + printf("create option 0x%08x returned %s\n", create_option, nt_errstr(status)); + } + } + + CHECK_VAL(ok_mask, 0x00efcfce); + CHECK_VAL(not_a_directory_mask, 0x00000001); + CHECK_VAL(not_supported_mask, 0x00002000); + CHECK_VAL(invalid_parameter_mask, 0xff100030); + CHECK_VAL(unexpected_mask, 0x00000000); + smbcli_unlink(cli->tree, fname); diff --git a/source4/torture/rpc/atsvc.c b/source4/torture/rpc/atsvc.c index 25ace8ac49..23d76ae502 100644 --- a/source4/torture/rpc/atsvc.c +++ b/source4/torture/rpc/atsvc.c @@ -65,7 +65,8 @@ static bool test_JobEnum(struct torture_context *tctx, struct dcerpc_pipe *p) NTSTATUS status; struct atsvc_JobEnum r; struct atsvc_enum_ctr ctr; - uint32_t resume_handle = 0, i; + uint32_t resume_handle = 0, i, total_entries = 0; + bool ret = true; r.in.servername = dcerpc_server_name(p); @@ -74,6 +75,7 @@ static bool test_JobEnum(struct torture_context *tctx, struct dcerpc_pipe *p) r.in.ctr = r.out.ctr = &ctr; r.in.preferred_max_len = 0xffffffff; r.in.resume_handle = r.out.resume_handle = &resume_handle; + r.out.total_entries = &total_entries; status = dcerpc_atsvc_JobEnum(p, tctx, &r); diff --git a/source4/torture/rpc/dssync.c b/source4/torture/rpc/dssync.c index 2739081246..e9346f9605 100644 --- a/source4/torture/rpc/dssync.c +++ b/source4/torture/rpc/dssync.c @@ -747,9 +747,10 @@ static bool test_FetchData(struct torture_context *tctx, struct DsSyncTest *ctx) if (ret == true && *r.out.level == 1) { out_level = 1; ctr1 = &r.out.ctr.ctr1; - } else if (ret == true && *r.out.level == 2) { + } else if (ret == true && *r.out.level == 2 && + r.out.ctr.ctr2.mszip1.ts) { out_level = 1; - ctr1 = r.out.ctr.ctr2.mszip1.ctr1; + ctr1 = &r.out.ctr.ctr2.mszip1.ts->ctr1; } if (out_level == 1) { @@ -770,14 +771,16 @@ static bool test_FetchData(struct torture_context *tctx, struct DsSyncTest *ctx) ctr6 = &r.out.ctr.ctr6; } else if (ret == true && *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) { out_level = 6; - ctr6 = r.out.ctr.ctr7.ctr.mszip6.ctr6; + ctr6 = &r.out.ctr.ctr7.ctr.mszip6.ts->ctr6; } else if (ret == true && *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) { out_level = 6; - ctr6 = r.out.ctr.ctr7.ctr.xpress6.ctr6; + ctr6 = &r.out.ctr.ctr7.ctr.xpress6.ts->ctr6; } if (out_level == 6) { diff --git a/source4/torture/rpc/lsa.c b/source4/torture/rpc/lsa.c index 4fb459ea25..ec74426ac6 100644 --- a/source4/torture/rpc/lsa.c +++ b/source4/torture/rpc/lsa.c @@ -28,7 +28,6 @@ #include "libcli/auth/libcli_auth.h" #include "torture/rpc/rpc.h" #include "param/param.h" - #define TEST_MACHINENAME "lsatestmach" static void init_lsa_String(struct lsa_String *name, const char *s) @@ -614,7 +613,8 @@ bool test_many_LookupSids(struct dcerpc_pipe *p, if (!test_LookupNames(p, mem_ctx, handle, &names)) { return false; } - } else { + } else if (p->conn->security_state.auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL && + p->conn->security_state.auth_info->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) { struct lsa_LookupSids3 r; struct lsa_TransNameArray2 names; @@ -779,6 +779,7 @@ static bool test_LookupPrivName(struct dcerpc_pipe *p, static bool test_RemovePrivilegesFromAccount(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, + struct policy_handle *handle, struct policy_handle *acct_handle, struct lsa_LUID *luid) { @@ -801,7 +802,25 @@ static bool test_RemovePrivilegesFromAccount(struct dcerpc_pipe *p, status = dcerpc_lsa_RemovePrivilegesFromAccount(p, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { - printf("RemovePrivilegesFromAccount failed - %s\n", nt_errstr(status)); + + struct lsa_LookupPrivName r_name; + + r_name.in.handle = handle; + r_name.in.luid = luid; + + status = dcerpc_lsa_LookupPrivName(p, mem_ctx, &r_name); + if (!NT_STATUS_IS_OK(status)) { + printf("\nLookupPrivName failed - %s\n", nt_errstr(status)); + return false; + } + /* Windows 2008 does not allow this to be removed */ + if (strcmp("SeAuditPrivilege", r_name.out.name->string) == 0) { + return ret; + } + + printf("RemovePrivilegesFromAccount failed to remove %s - %s\n", + r_name.out.name->string, + nt_errstr(status)); return false; } @@ -864,7 +883,7 @@ static bool test_EnumPrivsAccount(struct dcerpc_pipe *p, &r.out.privs->set[i].luid); } - ret &= test_RemovePrivilegesFromAccount(p, mem_ctx, acct_handle, + ret &= test_RemovePrivilegesFromAccount(p, mem_ctx, handle, acct_handle, &r.out.privs->set[0].luid); ret &= test_AddPrivilegesToAccount(p, mem_ctx, acct_handle, &r.out.privs->set[0].luid); @@ -884,6 +903,26 @@ static bool test_Delete(struct dcerpc_pipe *p, r.in.handle = handle; status = dcerpc_lsa_Delete(p, mem_ctx, &r); + if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { + printf("Delete should have failed NT_STATUS_NOT_SUPPORTED - %s\n", nt_errstr(status)); + return false; + } + + return true; +} + +static bool test_DeleteObject(struct dcerpc_pipe *p, + TALLOC_CTX *mem_ctx, + struct policy_handle *handle) +{ + NTSTATUS status; + struct lsa_DeleteObject r; + + printf("testing DeleteObject\n"); + + r.in.handle = handle; + r.out.handle = handle; + status = dcerpc_lsa_DeleteObject(p, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { printf("Delete failed - %s\n", nt_errstr(status)); return false; @@ -912,7 +951,19 @@ static bool test_CreateAccount(struct dcerpc_pipe *p, r.out.acct_handle = &acct_handle; status = dcerpc_lsa_CreateAccount(p, mem_ctx, &r); - if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) { + struct lsa_OpenAccount r_o; + r_o.in.handle = handle; + r_o.in.sid = newsid; + r_o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; + r_o.out.acct_handle = &acct_handle; + + status = dcerpc_lsa_OpenAccount(p, mem_ctx, &r_o); + if (!NT_STATUS_IS_OK(status)) { + printf("OpenAccount failed - %s\n", nt_errstr(status)); + return false; + } + } else if (!NT_STATUS_IS_OK(status)) { printf("CreateAccount failed - %s\n", nt_errstr(status)); return false; } @@ -921,6 +972,10 @@ static bool test_CreateAccount(struct dcerpc_pipe *p, return false; } + if (!test_DeleteObject(p, mem_ctx, &acct_handle)) { + return false; + } + return true; } @@ -948,6 +1003,10 @@ static bool test_DeleteTrustedDomain(struct dcerpc_pipe *p, return false; } + if (!test_DeleteObject(p, mem_ctx, &trustdom_handle)) { + return false; + } + return true; } @@ -986,7 +1045,7 @@ static bool test_CreateSecret(struct dcerpc_pipe *p, struct lsa_SetSecret r7; struct lsa_QuerySecret r8; struct policy_handle sec_handle, sec_handle2, sec_handle3; - struct lsa_Delete d; + struct lsa_DeleteObject d_o; struct lsa_DATA_BUF buf1; struct lsa_DATA_BUF_PTR bufp1; struct lsa_DATA_BUF_PTR bufp2; @@ -1121,7 +1180,7 @@ static bool test_CreateSecret(struct dcerpc_pipe *p, &blob1, &session_key); if (strcmp(secret1, secret2) != 0) { - printf("Returned secret '%s' doesn't match '%s'\n", + printf("Returned secret (r4) '%s' doesn't match '%s'\n", secret2, secret1); ret = false; } @@ -1136,7 +1195,9 @@ static bool test_CreateSecret(struct dcerpc_pipe *p, r5.in.new_val->data = enc_key.data; r5.in.new_val->length = enc_key.length; r5.in.new_val->size = enc_key.length; - + + + msleep(200); printf("Testing SetSecret (existing value should move to old)\n"); status = dcerpc_lsa_SetSecret(p, mem_ctx, &r5); @@ -1200,8 +1261,10 @@ static bool test_CreateSecret(struct dcerpc_pipe *p, } if (*r6.out.new_mtime == *r6.out.old_mtime) { - printf("Returned secret %s had same mtime for both secrets: %s\n", + printf("Returned secret (r6-%d) %s must not have same mtime for both secrets: %s != %s\n", + i, secname[i], + nt_time_string(mem_ctx, *r6.out.old_mtime), nt_time_string(mem_ctx, *r6.out.new_mtime)); ret = false; } @@ -1245,35 +1308,16 @@ static bool test_CreateSecret(struct dcerpc_pipe *p, if (!r8.out.new_val || !r8.out.old_val) { printf("in/out pointers not returned, despite being set on in for QuerySecret\n"); ret = false; - } else if (r8.out.new_val->buf == NULL) { - if (i != LOCAL) { - printf("NEW secret buffer not returned after GLOBAL OLD set\n"); - ret = false; - } + } else if (r8.out.new_val->buf != NULL) { + printf("NEW secret buffer must not be returned after OLD set\n"); + ret = false; } else if (r8.out.old_val->buf == NULL) { - printf("OLD secret buffer not returned after OLD set\n"); + printf("OLD secret buffer was not returned after OLD set\n"); ret = false; } else if (r8.out.new_mtime == NULL || r8.out.old_mtime == NULL) { printf("Both times not returned after OLD set\n"); ret = false; } else { - if (i == LOCAL) { - printf("NEW secret buffer should not be returned after LOCAL OLD set\n"); - ret = false; - } - blob1.data = r8.out.new_val->buf->data; - blob1.length = r8.out.new_val->buf->length; - - blob2 = data_blob_talloc(mem_ctx, NULL, blob1.length); - - secret6 = sess_decrypt_string(mem_ctx, - &blob1, &session_key); - - if (strcmp(secret3, secret4) != 0) { - printf("Returned NEW secret '%s' doesn't match '%s'\n", secret4, secret3); - ret = false; - } - blob1.data = r8.out.old_val->buf->data; blob1.length = r8.out.old_val->buf->size; @@ -1287,15 +1331,8 @@ static bool test_CreateSecret(struct dcerpc_pipe *p, ret = false; } - if (*r8.out.new_mtime == *r8.out.old_mtime) { - if (i != GLOBAL) { - printf("Returned secret %s had same mtime for both secrets: %s\n", - secname[i], - nt_time_string(mem_ctx, *r8.out.new_mtime)); - ret = false; - } - } else { - printf("Returned secret %s should have had same mtime for both secrets: %s != %s\n", + if (*r8.out.new_mtime != *r8.out.old_mtime) { + printf("Returned secret (r8) %s did not had same mtime for both secrets: %s != %s\n", secname[i], nt_time_string(mem_ctx, *r8.out.old_mtime), nt_time_string(mem_ctx, *r8.out.new_mtime)); @@ -1308,8 +1345,13 @@ static bool test_CreateSecret(struct dcerpc_pipe *p, ret = false; } - d.in.handle = &sec_handle2; - status = dcerpc_lsa_Delete(p, mem_ctx, &d); + if (!test_DeleteObject(p, mem_ctx, &sec_handle)) { + return false; + } + + d_o.in.handle = &sec_handle2; + d_o.out.handle = &sec_handle2; + status = dcerpc_lsa_DeleteObject(p, mem_ctx, &d_o); if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) { printf("Second delete expected INVALID_HANDLE - %s\n", nt_errstr(status)); ret = false; @@ -1454,9 +1496,9 @@ static bool test_EnumAccounts(struct dcerpc_pipe *p, return false; } - if (!test_LookupSids3(p, mem_ctx, &sids1)) { - return false; - } + /* Can't test lookupSids3 here, as clearly we must not + * be on schannel, or we would not be able to do the + * rest */ printf("testing all accounts\n"); for (i=0;i<sids1.num_sids;i++) { @@ -1667,8 +1709,8 @@ static bool test_query_each_TrustDom(struct dcerpc_pipe *p, struct policy_handle handle2; struct lsa_Close c; struct lsa_CloseTrustedDomainEx c_trust; - int levels [] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; - int ok[] = {1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1}; + int levels [] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}; + int ok[] = {1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1}; if (domains->domains[i].sid) { trust.in.handle = handle; @@ -1912,8 +1954,6 @@ static bool test_EnumTrustDom(struct dcerpc_pipe *p, r_ex.in.max_size, LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER, r_ex.in.max_size / LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER); - ret = false; - exit(1); } } else if (!NT_STATUS_IS_OK(enum_status)) { printf("EnumTrustedDomainEx failed - %s\n", nt_errstr(enum_status)); @@ -2015,10 +2055,6 @@ static bool test_QueryDomainInfoPolicy(struct dcerpc_pipe *p, NTSTATUS status; int i; bool ret = true; - if (torture_setting_bool(tctx, "samba4", false)) { - printf("skipping QueryDomainInformationPolicy test against Samba4\n"); - return true; - } printf("\nTesting QueryDomainInformationPolicy\n"); @@ -2030,7 +2066,10 @@ static bool test_QueryDomainInfoPolicy(struct dcerpc_pipe *p, status = dcerpc_lsa_QueryDomainInformationPolicy(p, tctx, &r); - if (!NT_STATUS_IS_OK(status)) { + /* If the server does not support EFS, then this is the correct return */ + if (i == LSA_DOMAIN_INFO_POLICY_EFS && NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { + continue; + } else if (!NT_STATUS_IS_OK(status)) { printf("QueryDomainInformationPolicy failed - %s\n", nt_errstr(status)); ret = false; continue; @@ -2311,11 +2350,9 @@ bool torture_rpc_lsa(struct torture_context *tctx) ret = false; } -#if 0 if (!test_Delete(p, tctx, handle)) { ret = false; } -#endif if (!test_many_LookupSids(p, tctx, handle)) { ret = false; diff --git a/source4/torture/smb2/create.c b/source4/torture/smb2/create.c index c23ff8b8ce..4d1b4a7ed0 100644 --- a/source4/torture/smb2/create.c +++ b/source4/torture/smb2/create.c @@ -52,7 +52,9 @@ static bool test_create_gentest(struct torture_context *torture, struct smb2_tre struct smb2_create io; NTSTATUS status; TALLOC_CTX *tmp_ctx = talloc_new(tree); - uint32_t access_mask, file_attributes, file_attributes_set, denied_mask; + uint32_t access_mask, file_attributes_set; + uint32_t ok_mask, not_supported_mask, invalid_parameter_mask; + uint32_t not_a_directory_mask, unexpected_mask; union smb_fileinfo q; ZERO_STRUCT(io); @@ -76,14 +78,6 @@ static bool test_create_gentest(struct torture_context *torture, struct smb2_tre status = smb2_create(tree, tmp_ctx, &io); CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); - io.in.create_options = 0x00100000; - status = smb2_create(tree, tmp_ctx, &io); - CHECK_STATUS(status, NT_STATUS_NOT_SUPPORTED); - - io.in.create_options = 0xF0100000; - status = smb2_create(tree, tmp_ctx, &io); - CHECK_STATUS(status, NT_STATUS_NOT_SUPPORTED); - io.in.create_options = 0; io.in.file_attributes = FILE_ATTRIBUTE_DEVICE; @@ -108,6 +102,46 @@ static bool test_create_gentest(struct torture_context *torture, struct smb2_tre status = smb2_create(tree, tmp_ctx, &io); CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); + io.in.file_attributes = 0; + io.in.create_disposition = NTCREATEX_DISP_OPEN_IF; + io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED; + ok_mask = 0; + not_supported_mask = 0; + invalid_parameter_mask = 0; + not_a_directory_mask = 0; + unexpected_mask = 0; + { + int i; + for (i=0;i<32;i++) { + io.in.create_options = 1<<i; + if (io.in.create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) { + continue; + } + status = smb2_create(tree, tmp_ctx, &io); + if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { + not_supported_mask |= 1<<i; + } else if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) { + invalid_parameter_mask |= 1<<i; + } else if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_A_DIRECTORY)) { + not_a_directory_mask |= 1<<i; + } else if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) { + ok_mask |= 1<<i; + status = smb2_util_close(tree, io.out.file.handle); + CHECK_STATUS(status, NT_STATUS_OK); + } else { + unexpected_mask |= 1<<i; + printf("create option 0x%08x returned %s\n", 1<<i, nt_errstr(status)); + } + } + } + io.in.create_options = 0; + + CHECK_EQUAL(ok_mask, 0x00efcf7e); + CHECK_EQUAL(not_a_directory_mask, 0x00000001); + CHECK_EQUAL(not_supported_mask, 0x00102080); + CHECK_EQUAL(invalid_parameter_mask, 0xff000000); + CHECK_EQUAL(unexpected_mask, 0x00000000); + io.in.create_disposition = NTCREATEX_DISP_OPEN_IF; io.in.file_attributes = 0; access_mask = 0; @@ -132,31 +166,58 @@ static bool test_create_gentest(struct torture_context *torture, struct smb2_tre io.in.create_disposition = NTCREATEX_DISP_OPEN_IF; io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED; io.in.file_attributes = 0; - file_attributes = 0; + ok_mask = 0; + invalid_parameter_mask = 0; + unexpected_mask = 0; file_attributes_set = 0; - denied_mask = 0; { int i; for (i=0;i<32;i++) { io.in.file_attributes = 1<<i; + if (io.in.file_attributes & FILE_ATTRIBUTE_ENCRYPTED) { + continue; + } smb2_deltree(tree, FNAME); status = smb2_create(tree, tmp_ctx, &io); if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) { - file_attributes |= io.in.file_attributes; - } else if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) { - denied_mask |= io.in.file_attributes; - } else { - CHECK_STATUS(status, NT_STATUS_OK); + invalid_parameter_mask |= 1<<i; + } else if (NT_STATUS_IS_OK(status)) { + uint32_t expected; + ok_mask |= 1<<i; + + expected = (io.in.file_attributes | FILE_ATTRIBUTE_ARCHIVE) & 0x00005127; + CHECK_EQUAL(io.out.file_attr, expected); + file_attributes_set |= io.out.file_attr; + status = smb2_util_close(tree, io.out.file.handle); CHECK_STATUS(status, NT_STATUS_OK); - file_attributes_set |= io.out.file_attr; + } else { + unexpected_mask |= 1<<i; + printf("file attribute 0x%08x returned %s\n", 1<<i, nt_errstr(status)); } } } - CHECK_EQUAL(file_attributes, 0xffff8048); - CHECK_EQUAL(denied_mask, 0x4000); - CHECK_EQUAL(file_attributes_set, 0x00001127); + CHECK_EQUAL(ok_mask, 0x00003fb7); + CHECK_EQUAL(invalid_parameter_mask, 0xffff8048); + CHECK_EQUAL(unexpected_mask, 0x00000000); + CHECK_EQUAL(file_attributes_set, 0x00001127); + + smb2_deltree(tree, FNAME); + + /* + * Standalone servers doesn't support encryption + */ + io.in.file_attributes = FILE_ATTRIBUTE_ENCRYPTED; + status = smb2_create(tree, tmp_ctx, &io); + if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) { + printf("FILE_ATTRIBUTE_ENCRYPTED returned %s\n", nt_errstr(status)); + } else { + CHECK_STATUS(status, NT_STATUS_OK); + CHECK_EQUAL(io.out.file_attr, (FILE_ATTRIBUTE_ENCRYPTED | FILE_ATTRIBUTE_ARCHIVE)); + status = smb2_util_close(tree, io.out.file.handle); + CHECK_STATUS(status, NT_STATUS_OK); + } smb2_deltree(tree, FNAME); diff --git a/source4/utils/ad2oLschema.c b/source4/utils/ad2oLschema.c index 51b03b8e8f..e229bd104b 100644 --- a/source4/utils/ad2oLschema.c +++ b/source4/utils/ad2oLschema.c @@ -1,7 +1,7 @@ /* ldb database library - Copyright (C) Andrew Bartlett 2006 + Copyright (C) Andrew Bartlett 2006-2008 ** NOTE! The following LGPL license applies to the ldb ** library. This does NOT imply that all of Samba is released @@ -35,7 +35,6 @@ #include "ldb_includes.h" #include "system/locale.h" #include "lib/ldb/tools/cmdline.h" -#include "utils/schema_convert.h" #include "param/param.h" #include "lib/cmdline/popt_common.h" #include "dsdb/samdb/samdb.h" @@ -45,11 +44,6 @@ struct schema_conv { int skipped; int failures; }; - -enum convert_target { - TARGET_OPENLDAP, - TARGET_FEDORA_DS -}; static void usage(void) @@ -122,15 +116,7 @@ static struct ldb_dn *find_schema_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ct } -#define IF_NULL_FAIL_RET(x) do { \ - if (!x) { \ - ret.failures++; \ - return ret; \ - } \ - } while (0) - - -static struct schema_conv process_convert(struct ldb_context *ldb, enum convert_target target, FILE *in, FILE *out) +static struct schema_conv process_convert(struct ldb_context *ldb, enum dsdb_schema_convert_target target, FILE *in, FILE *out) { /* Read list of attributes to skip, OIDs to map */ TALLOC_CTX *mem_ctx = talloc_new(ldb); @@ -152,6 +138,7 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum convert_ struct ldb_dn *schemadn; struct schema_conv ret; struct dsdb_schema *schema; + const char *seperator; char *error_string; int ldb_ret; @@ -171,7 +158,10 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum convert_ } if (isdigit(line[0])) { char *p = strchr(line, ':'); - IF_NULL_FAIL_RET(p); + if (!p) { + ret.failures++; + return ret; + } p[0] = '\0'; p++; oid_map = talloc_realloc(mem_ctx, oid_map, struct oid_map, num_oid_maps + 2); @@ -223,8 +213,10 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum convert_ switch (target) { case TARGET_OPENLDAP: + seperator = "\n "; break; case TARGET_FEDORA_DS: + seperator = "\n "; fprintf(out, "dn: cn=schema\n"); break; } @@ -234,9 +226,10 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum convert_ const char *description = attribute->adminDescription; const char *oid = attribute->attributeID_oid; const char *syntax = attribute->attributeSyntax_oid; + const char *equality = NULL, *substring = NULL; bool single_value = attribute->isSingleValued; - const struct syntax_map *map = find_syntax_map_by_ad_oid(syntax); + const struct dsdb_syntax *map = find_syntax_map_by_ad_syntax(attribute->oMSyntax); char *schema_entry = NULL; int j; @@ -254,19 +247,22 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum convert_ } } - switch (target) { - case TARGET_OPENLDAP: - schema_entry = talloc_asprintf(mem_ctx, - "attributetype (\n" - " %s\n", oid); - break; - case TARGET_FEDORA_DS: - schema_entry = talloc_asprintf(mem_ctx, - "attributeTypes: (\n" - " %s\n", oid); - break; + if (map) { + /* We might have been asked to remap this oid, + * due to a conflict, or lack of + * implementation */ + syntax = map->ldap_oid; + /* We might have been asked to remap this oid, due to a conflict */ + for (j=0; syntax && oid_map && oid_map[j].old_oid; j++) { + if (strcasecmp(syntax, oid_map[j].old_oid) == 0) { + syntax = oid_map[j].new_oid; + break; + } + } + + equality = map->equality; + substring = map->substring; } - IF_NULL_FAIL_RET(schema_entry); /* We might have been asked to remap this name, due to a conflict */ for (j=0; name && attr_map && attr_map[j].old_attr; j++) { @@ -276,60 +272,19 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum convert_ } } - schema_entry = talloc_asprintf_append(schema_entry, - " NAME '%s'\n", name); - IF_NULL_FAIL_RET(schema_entry); - - if (description) { -#if 0 /* If you want to re-enable this, you must first figure out a sane escaping of ' in the description */ - schema_entry = talloc_asprintf_append(schema_entry, - " DESC '%s'\n", description); - IF_NULL_FAIL_RET(schema_entry); -#endif - } - - if (map) { - const char *syntax_oid; - if (map->equality) { - schema_entry = talloc_asprintf_append(schema_entry, - " EQUALITY %s\n", map->equality); - IF_NULL_FAIL_RET(schema_entry); - } - if (map->substring) { - schema_entry = talloc_asprintf_append(schema_entry, - " SUBSTR %s\n", map->substring); - IF_NULL_FAIL_RET(schema_entry); - } - syntax_oid = map->Standard_OID; - /* We might have been asked to remap this oid, - * due to a conflict, or lack of - * implementation */ - for (j=0; syntax_oid && oid_map && oid_map[j].old_oid; j++) { - if (strcasecmp(syntax_oid, oid_map[j].old_oid) == 0) { - syntax_oid = oid_map[j].new_oid; - break; - } - } - schema_entry = talloc_asprintf_append(schema_entry, - " SYNTAX %s\n", syntax_oid); - IF_NULL_FAIL_RET(schema_entry); - } + schema_entry = schema_attribute_description(mem_ctx, target, seperator, oid, name, description, equality, substring, syntax, single_value, false); - if (single_value) { - schema_entry = talloc_asprintf_append(schema_entry, - " SINGLE-VALUE\n"); - IF_NULL_FAIL_RET(schema_entry); + if (schema_entry == NULL) { + ret.failures++; + return ret; } - - schema_entry = talloc_asprintf_append(schema_entry, - " )"); switch (target) { case TARGET_OPENLDAP: - fprintf(out, "%s\n\n", schema_entry); + fprintf(out, "attributetype %s\n\n", schema_entry); break; case TARGET_FEDORA_DS: - fprintf(out, "%s\n", schema_entry); + fprintf(out, "attributeTypes: %s\n", schema_entry); break; } ret.count++; @@ -350,6 +305,7 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum convert_ NULL }; int j; + int attr_idx; /* We have been asked to skip some attributes/objectClasses */ if (attrs_skip && str_list_check_ci(attrs_skip, name)) { @@ -357,10 +313,6 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum convert_ continue; } - may = dsdb_full_attribute_list(mem_ctx, schema, objectclass_name_as_list, DSDB_SCHEMA_ALL_MAY); - - must = dsdb_full_attribute_list(mem_ctx, schema, objectclass_name_as_list, DSDB_SCHEMA_ALL_MUST); - /* We might have been asked to remap this oid, due to a conflict */ for (j=0; oid_map && oid_map[j].old_oid; j++) { if (strcasecmp(oid, oid_map[j].old_oid) == 0) { @@ -369,24 +321,6 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum convert_ } } - switch (target) { - case TARGET_OPENLDAP: - schema_entry = talloc_asprintf(mem_ctx, - "objectclass (\n" - " %s\n", oid); - break; - case TARGET_FEDORA_DS: - schema_entry = talloc_asprintf(mem_ctx, - "objectClasses: (\n" - " %s\n", oid); - break; - } - IF_NULL_FAIL_RET(schema_entry); - if (!schema_entry) { - ret.failures++; - break; - } - /* We might have been asked to remap this name, due to a conflict */ for (j=0; name && attr_map && attr_map[j].old_attr; j++) { if (strcasecmp(name, attr_map[j].old_attr) == 0) { @@ -395,106 +329,51 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum convert_ } } - schema_entry = talloc_asprintf_append(schema_entry, - " NAME '%s'\n", name); - IF_NULL_FAIL_RET(schema_entry); - - if (!schema_entry) return ret; + may = dsdb_full_attribute_list(mem_ctx, schema, objectclass_name_as_list, DSDB_SCHEMA_ALL_MAY); - if (description) { - schema_entry = talloc_asprintf_append(schema_entry, - " DESC '%s'\n", description); - IF_NULL_FAIL_RET(schema_entry); + for (j=0; may && may[j]; j++) { + /* We might have been asked to remap this name, due to a conflict */ + for (attr_idx=0; attr_map && attr_map[attr_idx].old_attr; attr_idx++) { + if (strcasecmp(may[j], attr_map[attr_idx].old_attr) == 0) { + may[j] = attr_map[attr_idx].new_attr; + break; + } + } } - if (subClassOf) { - schema_entry = talloc_asprintf_append(schema_entry, - " SUP %s\n", subClassOf); - IF_NULL_FAIL_RET(schema_entry); - } - - switch (objectClassCategory) { - case 1: - schema_entry = talloc_asprintf_append(schema_entry, - " STRUCTURAL\n"); - IF_NULL_FAIL_RET(schema_entry); - break; - case 2: - schema_entry = talloc_asprintf_append(schema_entry, - " ABSTRACT\n"); - IF_NULL_FAIL_RET(schema_entry); - break; - case 3: - schema_entry = talloc_asprintf_append(schema_entry, - " AUXILIARY\n"); - IF_NULL_FAIL_RET(schema_entry); - break; - } + must = dsdb_full_attribute_list(mem_ctx, schema, objectclass_name_as_list, DSDB_SCHEMA_ALL_MUST); -#define APPEND_ATTRS(attributes) \ - do { \ - int k; \ - for (k=0; attributes && attributes[k]; k++) { \ - int attr_idx; \ - const char *attr_name = attributes[k]; \ - /* We might have been asked to remap this name, due to a conflict */ \ - for (attr_idx=0; attr_name && attr_map && attr_map[attr_idx].old_attr; attr_idx++) { \ - if (strcasecmp(attr_name, attr_map[attr_idx].old_attr) == 0) { \ - attr_name = attr_map[attr_idx].new_attr; \ - break; \ - } \ - } \ - \ - schema_entry = talloc_asprintf_append(schema_entry, \ - " %s", \ - attr_name); \ - IF_NULL_FAIL_RET(schema_entry); \ - if (attributes[k+1]) { \ - schema_entry = talloc_asprintf_append(schema_entry, \ - " $"); \ - IF_NULL_FAIL_RET(schema_entry); \ - if (target == TARGET_OPENLDAP && ((k+1)%5 == 0)) { \ - schema_entry = talloc_asprintf_append(schema_entry, \ - "\n "); \ - IF_NULL_FAIL_RET(schema_entry); \ - } \ - } \ - } \ - } while (0) - - 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, - " )\n"); - IF_NULL_FAIL_RET(schema_entry); + for (j=0; must && must[j]; j++) { + /* We might have been asked to remap this name, due to a conflict */ + for (attr_idx=0; attr_map && attr_map[attr_idx].old_attr; attr_idx++) { + if (strcasecmp(must[j], attr_map[attr_idx].old_attr) == 0) { + must[j] = attr_map[attr_idx].new_attr; + break; + } + } } - 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, - " )\n"); - IF_NULL_FAIL_RET(schema_entry); + schema_entry = schema_class_description(mem_ctx, target, + seperator, + oid, + name, + NULL, + description, + subClassOf, + objectClassCategory, + must, + may); + if (schema_entry == NULL) { + ret.failures++; + return ret; } - schema_entry = talloc_asprintf_append(schema_entry, - " )"); - switch (target) { case TARGET_OPENLDAP: - fprintf(out, "%s\n\n", schema_entry); + fprintf(out, "objectclass %s\n\n", schema_entry); break; case TARGET_FEDORA_DS: - fprintf(out, "%s\n", schema_entry); + fprintf(out, "objectClasses: %s\n", schema_entry); break; } ret.count++; @@ -512,7 +391,7 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum convert_ struct ldb_context *ldb; struct schema_conv ret; const char *target_str; - enum convert_target target; + enum dsdb_schema_convert_target target; ctx = talloc_new(NULL); ldb = ldb_init(ctx, NULL); diff --git a/source4/utils/config.mk b/source4/utils/config.mk index 61565807d2..37a19077f1 100644 --- a/source4/utils/config.mk +++ b/source4/utils/config.mk @@ -100,12 +100,12 @@ testparm_OBJ_FILES = $(utilssrcdir)/testparm.o [BINARY::oLschema2ldif] INSTALLDIR = BINDIR PRIVATE_DEPENDENCIES = \ - LIBLDB_CMDLINE + LIBLDB_CMDLINE SAMDB # End BINARY oLschema2ldif ################################################ -oLschema2ldif_OBJ_FILES = $(addprefix $(utilssrcdir)/, schema_convert.o oLschema2ldif.o) +oLschema2ldif_OBJ_FILES = $(addprefix $(utilssrcdir)/, oLschema2ldif.o) MANPAGES += $(utilssrcdir)/man/oLschema2ldif.1 @@ -118,7 +118,7 @@ PRIVATE_DEPENDENCIES = \ # End BINARY ad2oLschema ################################################ -ad2oLschema_OBJ_FILES = $(addprefix $(utilssrcdir)/, schema_convert.o ad2oLschema.o) +ad2oLschema_OBJ_FILES = $(addprefix $(utilssrcdir)/, ad2oLschema.o) MANPAGES += $(utilssrcdir)/man/ad2oLschema.1 diff --git a/source4/utils/oLschema2ldif.c b/source4/utils/oLschema2ldif.c index b501b75529..6c4e6a9c80 100644 --- a/source4/utils/oLschema2ldif.c +++ b/source4/utils/oLschema2ldif.c @@ -31,9 +31,10 @@ * Author: Simo Sorce */ +#include "includes.h" #include "ldb_includes.h" #include "tools/cmdline.h" -#include "utils/schema_convert.h" +#include "dsdb/samdb/samdb.h" #define SCHEMA_UNKNOWN 0 #define SCHEMA_NAME 1 @@ -432,12 +433,12 @@ static struct ldb_message *process_entry(TALLOC_CTX *mem_ctx, const char *entry) case SCHEMA_SYNTAX: { - const struct syntax_map *map = + const struct dsdb_syntax *map = find_syntax_map_by_standard_oid(token->value); if (!map) { break; } - MSG_ADD_STRING("attributeSyntax", map->AD_OID); + MSG_ADD_STRING("attributeSyntax", map->attributeSyntax_oid); break; } case SCHEMA_DESC: diff --git a/source4/utils/schema_convert.c b/source4/utils/schema_convert.c deleted file mode 100644 index a5d38451d4..0000000000 --- a/source4/utils/schema_convert.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - ldb database library - - Copyright (C) Simo Sorce 2005 - - ** NOTE! The following LGPL license applies to the ldb - ** library. This does NOT imply that all of Samba is released - ** under the LGPL - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ - -#include "schema_convert.h" -#include "ldb_includes.h" - -/* Shared map for converting syntax between formats */ -static const struct syntax_map syntax_map[] = { - { - .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.12", - .AD_OID = "2.5.5.1", - .equality = "distinguishedNameMatch", - .comment = "Object(DS-DN) == a DN" - }, -#if 0 - { - .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.38", - .AD_OID = "2.5.5.2", - .equality = "objectIdentifierMatch", - .comment = "OID String" - }, -#else - { - .Standard_OID = "1.2.840.113556.1.4.905", - .AD_OID = "2.5.5.2", - .equality = "caseIgnoreMatch", - .comment = "OID as a Case Insensitive String" - }, -#endif - { - .Standard_OID = "1.2.840.113556.1.4.905", - .AD_OID = "2.5.5.4", - .equality = "caseIgnoreMatch", - .substring = "caseIgnoreSubstringsMatch", - .comment = "Case Insensitive String" - }, - { - .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.26", - .AD_OID = "2.5.5.5", - .equality = "caseExactIA5Match", - .comment = "Printable String" - }, - { - .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.36", - .AD_OID = "2.5.5.6", - .equality = "numericStringMatch", - .substring = "numericStringSubstringsMatch", - .comment = "Numeric String" - }, - { - .Standard_OID = "1.2.840.113556.1.4.903", - .AD_OID = "2.5.5.7", - .equality = "distinguishedNameMatch", - .comment = "OctetString: Binary+DN" - }, - { - .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.7", - .AD_OID = "2.5.5.8", - .equality = "booleanMatch", - .comment = "Boolean" - }, - { - .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.27", - .AD_OID = "2.5.5.9", - .equality = "integerMatch", - .comment = "Integer" - }, - { - .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.40", - .AD_OID = "2.5.5.10", - .equality = "octetStringMatch", - .comment = "Octet String" - }, - { - .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.24", - .AD_OID = "2.5.5.11", - .equality = "generalizedTimeMatch", - .comment = "Generalized Time" - }, - { - .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.53", - .AD_OID = "2.5.5.11", - .equality = "generalizedTimeMatch", - .comment = "UTC Time" - }, - { - .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.15", - .AD_OID = "2.5.5.12", - .equality = "caseIgnoreMatch", - .substring = "caseIgnoreSubstringsMatch", - .comment = "Directory String" - }, - { - .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.43", - .AD_OID = "2.5.5.13", - .comment = "Presentation Address" - }, - { - .Standard_OID = "Not Found Yet", - .AD_OID = "2.5.5.14", - .equality = "distinguishedNameMatch", - .comment = "OctetString: String+DN" - }, - { - .Standard_OID = "1.2.840.113556.1.4.907", - .AD_OID = "2.5.5.15", - .equality = "octetStringMatch", - .comment = "NT Security Descriptor" - }, - { - .Standard_OID = "1.2.840.113556.1.4.906", - .AD_OID = "2.5.5.16", - .equality = "integerMatch", - .comment = "Large Integer" - }, - { - .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.40", - .AD_OID = "2.5.5.17", - .equality = "octetStringMatch", - .comment = "Octet String - Security Identifier (SID)" - }, - { - .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.26", - .AD_OID = "2.5.5.5", - .equality = "caseExactIA5Match", - .comment = "IA5 String" - }, - { .Standard_OID = NULL - } -}; - - -const struct syntax_map *find_syntax_map_by_ad_oid(const char *ad_oid) -{ - int i; - for (i=0; syntax_map[i].Standard_OID; i++) { - if (strcasecmp(ad_oid, syntax_map[i].AD_OID) == 0) { - return &syntax_map[i]; - } - } - return NULL; -} - -const struct syntax_map *find_syntax_map_by_standard_oid(const char *standard_oid) -{ - int i; - for (i=0; syntax_map[i].Standard_OID; i++) { - if (strcasecmp(standard_oid, syntax_map[i].Standard_OID) == 0) { - return &syntax_map[i]; - } - } - return NULL; -} diff --git a/source4/utils/schema_convert.h b/source4/utils/schema_convert.h deleted file mode 100644 index de379343a6..0000000000 --- a/source4/utils/schema_convert.h +++ /dev/null @@ -1,10 +0,0 @@ -struct syntax_map { - const char *Standard_OID; - const char *AD_OID; - const char *equality; - const char *substring; - const char *comment; -}; - -const struct syntax_map *find_syntax_map_by_ad_oid(const char *ad_oid); -const struct syntax_map *find_syntax_map_by_standard_oid(const char *standard_oid); |