The branch, master has been updated
       via  e16a2a1fa941511a8eeefd05b397dd934a77c9f6 (commit)
       via  84dca625cab96f72123308d80a5aeed5fc42f0c5 (commit)
       via  bc354fb1a6fd524629434c199e2ca260a8400bb4 (commit)
       via  271b5af92e9aada36adc648a6dd43a13c5aed340 (commit)
       via  ba58edd0bc2d77c6ed1b6a76f33787da9031db5b (commit)
       via  d6c44a704e9a138dba8398f45e9af2601826f659 (commit)
      from  48a07321479c14a6618bb21302d27fd9606efbdd (commit)

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit e16a2a1fa941511a8eeefd05b397dd934a77c9f6
Author: Andrew Bartlett <abart...@samba.org>
Date:   Thu Jul 16 08:29:43 2009 +1000

    s4:gensec Rework gensec_krb5 mutual authentication defaults
    
    When emulating Samba3 (which we do to ensure we don't break
    compatability), don't do mutual authentication by default, as it
    breaks the session key with AES and isn't what Samba3 does anyway.
    
    Andrew Bartlett

commit 84dca625cab96f72123308d80a5aeed5fc42f0c5
Author: Andrew Bartlett <abart...@samba.org>
Date:   Tue Jul 14 13:22:38 2009 +1000

    s4:heimdal The implied GSS_C_MUTUAL_FLAG depends on AP_OPTS_MUTUAL_REQUIRED
    
    We had previously assumed it was unconditional.  Samba3 didn't mind
    very much, but Samba4's samba3-like client did, and the behaviour
    differed to Win2008 behaviour.
    
    Andrew Bartlett

commit bc354fb1a6fd524629434c199e2ca260a8400bb4
Author: Andrew Bartlett <abart...@samba.org>
Date:   Tue Jul 14 10:19:16 2009 +1000

    s4:gensec Allow mutual auth to be turned off in 'fake_gssapi_krb5'
    
    This allows the older 'like Samba3' GENSEC krb5 implementation to work
    against Windows 2008.  I'm using this to track down interop issues in
    this area.
    
    Andrew Bartlett

commit 271b5af92e9aada36adc648a6dd43a13c5aed340
Author: Andrew Bartlett <abart...@samba.org>
Date:   Tue Jul 14 08:15:50 2009 +1000

    s4:dsdb Handle dc/domain/forest functional levels properly
    
    Rather than have the functional levels scattered in 4 different,
    unconnected locations, the provision script now sets it, and the
    rootdse module maintains it's copy only as a cached view onto the
    original values.
    
    We also use the functional level to determine if we should store AES
    Kerberos keys.
    
    Andrew Bartlett

commit ba58edd0bc2d77c6ed1b6a76f33787da9031db5b
Author: Andrew Bartlett <abart...@samba.org>
Date:   Tue Jul 14 08:00:09 2009 +1000

    Add a way to set an opaque integer onto a samdb
    
    This will allow us to set some more flags into ldb during the provision.

commit d6c44a704e9a138dba8398f45e9af2601826f659
Author: Timur I. Bakeyev <ti...@freebsd.org>
Date:   Sun Jul 12 23:36:08 2009 +0000

    Add ad-schema/*.txt and utils to the installmisc.sh
    
    Install other useful scripts from the setup/ directory, not only
    provisioning ones.
    
    Also install setup/ad-schema/*.txt files to the SETUPDIR. These are
    necessary for 'provision' to work properly.

-----------------------------------------------------------------------

Summary of changes:
 source4/auth/gensec/gensec_krb5.c                  |   68 ++++++----
 source4/dsdb/samdb/ldb_modules/password_hash.c     |    7 +-
 source4/dsdb/samdb/ldb_modules/rootdse.c           |  140 +++++++++++++++++++-
 .../heimdal/lib/gssapi/krb5/accept_sec_context.c   |    5 +-
 source4/script/installmisc.sh                      |   10 +-
 source4/scripting/python/pyglue.c                  |   65 +++++++++
 source4/scripting/python/samba/__init__.py         |    5 +
 source4/scripting/python/samba/provision.py        |   24 +++-
 source4/scripting/python/samba/samdb.py            |    8 +
 source4/setup/provision_basedn_modify.ldif         |    4 +-
 source4/setup/provision_configuration.ldif         |    2 +-
 source4/setup/provision_rootdse_add.ldif           |    3 -
 source4/setup/provision_self_join.ldif             |    4 +-
 13 files changed, 293 insertions(+), 52 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source4/auth/gensec/gensec_krb5.c 
b/source4/auth/gensec/gensec_krb5.c
index 09bdec5..f4ef36a 100644
--- a/source4/auth/gensec/gensec_krb5.c
+++ b/source4/auth/gensec/gensec_krb5.c
@@ -57,6 +57,7 @@ struct gensec_krb5_state {
        krb5_keyblock *keyblock;
        krb5_ticket *ticket;
        bool gssapi;
+       krb5_flags ap_req_options;
 };
 
 static int gensec_krb5_destroy(struct gensec_krb5_state *gensec_krb5_state)
@@ -88,7 +89,7 @@ static int gensec_krb5_destroy(struct gensec_krb5_state 
*gensec_krb5_state)
        return 0;
 }
 
-static NTSTATUS gensec_krb5_start(struct gensec_security *gensec_security)
+static NTSTATUS gensec_krb5_start(struct gensec_security *gensec_security, 
bool gssapi)
 {
        krb5_error_code ret;
        struct gensec_krb5_state *gensec_krb5_state;
@@ -114,7 +115,7 @@ static NTSTATUS gensec_krb5_start(struct gensec_security 
*gensec_security)
        gensec_krb5_state->keyblock = NULL;
        gensec_krb5_state->session_key = data_blob(NULL, 0);
        gensec_krb5_state->pac = data_blob(NULL, 0);
-       gensec_krb5_state->gssapi = false;
+       gensec_krb5_state->gssapi = gssapi;
 
        talloc_set_destructor(gensec_krb5_state, gensec_krb5_destroy); 
 
@@ -186,12 +187,12 @@ static NTSTATUS gensec_krb5_start(struct gensec_security 
*gensec_security)
        return NT_STATUS_OK;
 }
 
-static NTSTATUS gensec_krb5_server_start(struct gensec_security 
*gensec_security)
+static NTSTATUS gensec_krb5_common_server_start(struct gensec_security 
*gensec_security, bool gssapi)
 {
        NTSTATUS nt_status;
        struct gensec_krb5_state *gensec_krb5_state;
 
-       nt_status = gensec_krb5_start(gensec_security);
+       nt_status = gensec_krb5_start(gensec_security, gssapi);
        if (!NT_STATUS_IS_OK(nt_status)) {
                return nt_status;
        }
@@ -202,26 +203,23 @@ static NTSTATUS gensec_krb5_server_start(struct 
gensec_security *gensec_security
        return NT_STATUS_OK;
 }
 
-static NTSTATUS gensec_fake_gssapi_krb5_server_start(struct gensec_security 
*gensec_security)
+static NTSTATUS gensec_krb5_server_start(struct gensec_security 
*gensec_security)
 {
-       NTSTATUS nt_status = gensec_krb5_server_start(gensec_security);
+       return gensec_krb5_common_server_start(gensec_security, false);
+}
 
-       if (NT_STATUS_IS_OK(nt_status)) {
-               struct gensec_krb5_state *gensec_krb5_state;
-               gensec_krb5_state = (struct gensec_krb5_state 
*)gensec_security->private_data;
-               gensec_krb5_state->gssapi = true;
-       }
-       return nt_status;
+static NTSTATUS gensec_fake_gssapi_krb5_server_start(struct gensec_security 
*gensec_security)
+{
+       return gensec_krb5_common_server_start(gensec_security, true);
 }
 
-static NTSTATUS gensec_krb5_client_start(struct gensec_security 
*gensec_security)
+static NTSTATUS gensec_krb5_common_client_start(struct gensec_security 
*gensec_security, bool gssapi)
 {
        struct gensec_krb5_state *gensec_krb5_state;
        krb5_error_code ret;
        NTSTATUS nt_status;
        struct ccache_container *ccache_container;
        const char *hostname;
-       krb5_flags ap_req_options = AP_OPTS_USE_SUBKEY | 
AP_OPTS_MUTUAL_REQUIRED;
 
        const char *principal;
        krb5_data in_data;
@@ -240,13 +238,26 @@ static NTSTATUS gensec_krb5_client_start(struct 
gensec_security *gensec_security
                return NT_STATUS_INVALID_PARAMETER;
        }
                        
-       nt_status = gensec_krb5_start(gensec_security);
+       nt_status = gensec_krb5_start(gensec_security, gssapi);
        if (!NT_STATUS_IS_OK(nt_status)) {
                return nt_status;
        }
 
        gensec_krb5_state = (struct gensec_krb5_state 
*)gensec_security->private_data;
        gensec_krb5_state->state_position = GENSEC_KRB5_CLIENT_START;
+       gensec_krb5_state->ap_req_options = AP_OPTS_USE_SUBKEY;
+
+       if (gensec_krb5_state->gssapi) {
+               /* The Fake GSSAPI modal emulates Samba3, which does not do 
mutual authentication */
+               if (gensec_setting_bool(gensec_security->settings, 
"gensec_fake_gssapi_krb5", "mutual", false)) {
+                       gensec_krb5_state->ap_req_options |= 
AP_OPTS_MUTUAL_REQUIRED;
+               }
+       } else {
+               /* The wrapping for KPASSWD (a user of the raw KRB5 API) should 
be mutually authenticated */
+               if (gensec_setting_bool(gensec_security->settings, 
"gensec_krb5", "mutual", true)) {
+                       gensec_krb5_state->ap_req_options |= 
AP_OPTS_MUTUAL_REQUIRED;
+               }
+       }
 
        principal = gensec_get_target_principal(gensec_security);
 
@@ -274,7 +285,7 @@ static NTSTATUS gensec_krb5_client_start(struct 
gensec_security *gensec_security
                if (ret == 0) {
                        ret = 
krb5_mk_req_exact(gensec_krb5_state->smb_krb5_context->krb5_context, 
                                                
&gensec_krb5_state->auth_context,
-                                               ap_req_options, 
+                                               
gensec_krb5_state->ap_req_options, 
                                                target_principal,
                                                &in_data, 
ccache_container->ccache, 
                                                &gensec_krb5_state->enc_ticket);
@@ -284,7 +295,7 @@ static NTSTATUS gensec_krb5_client_start(struct 
gensec_security *gensec_security
        } else {
                ret = 
krb5_mk_req(gensec_krb5_state->smb_krb5_context->krb5_context, 
                                  &gensec_krb5_state->auth_context,
-                                 ap_req_options,
+                                 gensec_krb5_state->ap_req_options,
                                  gensec_get_target_service(gensec_security),
                                  hostname,
                                  &in_data, ccache_container->ccache, 
@@ -328,16 +339,14 @@ static NTSTATUS gensec_krb5_client_start(struct 
gensec_security *gensec_security
        }
 }
 
-static NTSTATUS gensec_fake_gssapi_krb5_client_start(struct gensec_security 
*gensec_security)
+static NTSTATUS gensec_krb5_client_start(struct gensec_security 
*gensec_security)
 {
-       NTSTATUS nt_status = gensec_krb5_client_start(gensec_security);
+       return gensec_krb5_common_client_start(gensec_security, false);
+}
 
-       if (NT_STATUS_IS_OK(nt_status)) {
-               struct gensec_krb5_state *gensec_krb5_state;
-               gensec_krb5_state = (struct gensec_krb5_state 
*)gensec_security->private_data;
-               gensec_krb5_state->gssapi = true;
-       }
-       return nt_status;
+static NTSTATUS gensec_fake_gssapi_krb5_client_start(struct gensec_security 
*gensec_security)
+{
+       return gensec_krb5_common_client_start(gensec_security, true);
 }
 
 /**
@@ -392,8 +401,13 @@ static NTSTATUS gensec_krb5_update(struct gensec_security 
*gensec_security,
                } else {
                        *out = data_blob_talloc(out_mem_ctx, 
gensec_krb5_state->enc_ticket.data, gensec_krb5_state->enc_ticket.length);
                }
-               gensec_krb5_state->state_position = 
GENSEC_KRB5_CLIENT_MUTUAL_AUTH;
-               nt_status = NT_STATUS_MORE_PROCESSING_REQUIRED;
+               if (gensec_krb5_state->ap_req_options & 
AP_OPTS_MUTUAL_REQUIRED) {
+                       gensec_krb5_state->state_position = 
GENSEC_KRB5_CLIENT_MUTUAL_AUTH;
+                       nt_status = NT_STATUS_MORE_PROCESSING_REQUIRED;
+               } else {
+                       gensec_krb5_state->state_position = GENSEC_KRB5_DONE;
+                       nt_status = NT_STATUS_OK;
+               }
                return nt_status;
        }
                
diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c 
b/source4/dsdb/samdb/ldb_modules/password_hash.c
index a28ca1d..ef641ac 100644
--- a/source4/dsdb/samdb/ldb_modules/password_hash.c
+++ b/source4/dsdb/samdb/ldb_modules/password_hash.c
@@ -1026,6 +1026,7 @@ static int setup_supplemental_field(struct 
setup_password_fields_io *io)
        uint8_t zero16[16];
        bool do_newer_keys = false;
        bool do_cleartext = false;
+       int *domainFunctionality;
 
        ZERO_STRUCT(zero16);
        ZERO_STRUCT(names);
@@ -1064,10 +1065,10 @@ static int setup_supplemental_field(struct 
setup_password_fields_io *io)
                                               _old_scb.sub.signature, 
SUPPLEMENTAL_CREDENTIALS_SIGNATURE);
                }
        }
+       /* Per MS-SAMR 3.1.1.8.11.6 we create AES keys if our domain 
functionality level is 2008 or higher */
+       domainFunctionality = talloc_get_type(ldb_get_opaque(ldb, 
"domainFunctionality"), int);
 
-       /* TODO: do the correct check for this, it maybe depends on the 
functional level? */
-       do_newer_keys = lp_parm_bool(ldb_get_opaque(ldb, "loadparm"),
-                                    NULL, "password_hash", "create_aes_key", 
false);
+       do_newer_keys = *domainFunctionality && (*domainFunctionality >= 
DS_BEHAVIOR_WIN2008);
 
        if (io->domain->store_cleartext &&
            (io->u.user_account_control & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED)) {
diff --git a/source4/dsdb/samdb/ldb_modules/rootdse.c 
b/source4/dsdb/samdb/ldb_modules/rootdse.c
index 7080fb6..59ea51d 100644
--- a/source4/dsdb/samdb/ldb_modules/rootdse.c
+++ b/source4/dsdb/samdb/ldb_modules/rootdse.c
@@ -59,6 +59,7 @@ static int rootdse_add_dynamic(struct ldb_module *module, 
struct ldb_message *ms
        struct private_data *priv = 
talloc_get_type(ldb_module_get_private(module), struct private_data);
        char **server_sasl;
        const struct dsdb_schema *schema;
+       int *val;
 
        ldb = ldb_module_get_ctx(module);
        schema = dsdb_get_schema(ldb);
@@ -77,7 +78,7 @@ static int rootdse_add_dynamic(struct ldb_module *module, 
struct ldb_message *ms
                }
        }
 
-       if (do_attribute(attrs, "supportedControl")) {
+       if (priv && do_attribute(attrs, "supportedControl")) {
                int i;
                for (i = 0; i < priv->num_controls; i++) {
                        char *control = talloc_strdup(msg, priv->controls[i]);
@@ -91,7 +92,7 @@ static int rootdse_add_dynamic(struct ldb_module *module, 
struct ldb_message *ms
                }
        }
 
-       if (do_attribute(attrs, "namingContexts")) {
+       if (priv && do_attribute(attrs, "namingContexts")) {
                int i;
                for (i = 0; i < priv->num_partitions; i++) {
                        struct ldb_dn *dn = priv->partitions[i];
@@ -201,13 +202,37 @@ static int rootdse_add_dynamic(struct ldb_module *module, 
struct ldb_message *ms
                }
        }
 
-       if (schema && do_attribute_explicit(attrs, "vendorVersion")) {
+       if (do_attribute_explicit(attrs, "vendorVersion")) {
                if (ldb_msg_add_fmt(msg, "vendorVersion", 
                                    "%s", SAMBA_VERSION_STRING) != 0) {
                        goto failed;
                }
        }
 
+       if (priv && do_attribute(attrs, "domainFunctionality")
+           && (val = talloc_get_type(ldb_get_opaque(ldb, 
"domainFunctionality"), int))) {
+               if (ldb_msg_add_fmt(msg, "domainFunctionality", 
+                                   "%d", *val) != 0) {
+                       goto failed;
+               }
+       }
+
+       if (priv && do_attribute(attrs, "forestFunctionality")
+           && (val = talloc_get_type(ldb_get_opaque(ldb, 
"forestFunctionality"), int))) {
+               if (ldb_msg_add_fmt(msg, "forestFunctionality", 
+                                   "%d", *val) != 0) {
+                       goto failed;
+               }
+       }
+
+       if (priv && do_attribute(attrs, "domainControllerFunctionality")
+           && (val = talloc_get_type(ldb_get_opaque(ldb, 
"domainControllerFunctionality"), int))) {
+               if (ldb_msg_add_fmt(msg, "domainControllerFunctionality", 
+                                   "%d", *val) != 0) {
+                       goto failed;
+               }
+       }
+
        /* TODO: lots more dynamic attributes should be added here */
 
        return LDB_SUCCESS;
@@ -394,12 +419,17 @@ static int rootdse_request(struct ldb_module *module, 
struct ldb_request *req)
 
 static int rootdse_init(struct ldb_module *module)
 {
+       int ret;
        struct ldb_context *ldb;
+       struct ldb_result *res;
        struct private_data *data;
+       const char *attrs[] = { "msDS-Behavior-Version", NULL };
+       const char *ds_attrs[] = { "dsServiceName", NULL };
+       TALLOC_CTX *mem_ctx;
 
        ldb = ldb_module_get_ctx(module);
 
-       data = talloc(module, struct private_data);
+       data = talloc_zero(module, struct private_data);
        if (data == NULL) {
                return -1;
        }
@@ -412,7 +442,107 @@ static int rootdse_init(struct ldb_module *module)
 
        ldb_set_default_dns(ldb);
 
-       return ldb_next_init(module);
+       ret = ldb_next_init(module);
+
+       if (ret) {
+               return ret;
+       }
+
+       mem_ctx = talloc_new(data);
+       if (!mem_ctx) {
+               ldb_oom(ldb);
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       /* Now that the partitions are set up, do a search for:
+          - domainControllerFunctionality
+          - domainFunctionality
+          - forestFunctionality
+
+          Then stuff these values into an opaque
+       */
+       ret = ldb_search(ldb, mem_ctx, &res,
+                        ldb_get_default_basedn(ldb),
+                        LDB_SCOPE_BASE, attrs, NULL);
+       if (ret == LDB_SUCCESS && res->count == 1) {
+               int domain_behaviour_version
+                       = ldb_msg_find_attr_as_int(res->msgs[0], 
+                                                  "msDS-Behavior-Version", -1);
+               if (domain_behaviour_version != -1) {
+                       int *val = talloc(ldb, int);
+                       if (!val) {
+                               ldb_oom(ldb);
+                               talloc_free(mem_ctx);
+                               return LDB_ERR_OPERATIONS_ERROR;
+                       }
+                       *val = domain_behaviour_version;
+                       ret = ldb_set_opaque(ldb, "domainFunctionality", val);
+                       if (ret != LDB_SUCCESS) {
+                               talloc_free(mem_ctx);
+                               return ret;
+                       }
+               }
+       }
+
+       ret = ldb_search(ldb, mem_ctx, &res,
+                        samdb_partitions_dn(ldb, mem_ctx),
+                        LDB_SCOPE_BASE, attrs, NULL);
+       if (ret == LDB_SUCCESS && res->count == 1) {
+               int forest_behaviour_version
+                       = ldb_msg_find_attr_as_int(res->msgs[0], 
+                                                  "msDS-Behavior-Version", -1);
+               if (forest_behaviour_version != -1) {
+                       int *val = talloc(ldb, int);
+                       if (!val) {
+                               ldb_oom(ldb);
+                               talloc_free(mem_ctx);
+                               return LDB_ERR_OPERATIONS_ERROR;
+                       }
+                       *val = forest_behaviour_version;
+                       ret = ldb_set_opaque(ldb, "forestFunctionality", val);
+                       if (ret != LDB_SUCCESS) {
+                               talloc_free(mem_ctx);
+                               return ret;
+                       }
+               }
+       }
+
+       ret = ldb_search(ldb, mem_ctx, &res,
+                        ldb_dn_new(mem_ctx, ldb, ""),
+                        LDB_SCOPE_BASE, ds_attrs, NULL);
+       if (ret == LDB_SUCCESS && res->count == 1) {
+               struct ldb_dn *ds_dn
+                       = ldb_msg_find_attr_as_dn(ldb, mem_ctx, res->msgs[0], 
+                                                 "dsServiceName");
+               if (ds_dn) {
+                       ret = ldb_search(ldb, mem_ctx, &res, ds_dn, 
+                                        LDB_SCOPE_BASE, attrs, NULL);
+                       if (ret == LDB_SUCCESS && res->count == 1) {
+                               int domain_controller_behaviour_version
+                                       = 
ldb_msg_find_attr_as_int(res->msgs[0], 
+                                                                  
"msDS-Behavior-Version", -1);
+                               if (domain_controller_behaviour_version != -1) {
+                                       int *val = talloc(ldb, int);
+                                       if (!val) {
+                                               ldb_oom(ldb);
+                                               talloc_free(mem_ctx);
+                                       return LDB_ERR_OPERATIONS_ERROR;
+                                       }
+                                       *val = 
domain_controller_behaviour_version;
+                                       ret = ldb_set_opaque(ldb, 
+                                                            
"domainControllerFunctionality", val);
+                                       if (ret != LDB_SUCCESS) {
+                                               talloc_free(mem_ctx);
+                                               return ret;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       talloc_free(mem_ctx);
+       
+       return LDB_SUCCESS;
 }
 
 static int rootdse_modify(struct ldb_module *module, struct ldb_request *req)
diff --git a/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c 
b/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c
index e094485..8ead2bd 100644
--- a/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c
+++ b/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c
@@ -522,7 +522,10 @@ gsskrb5_acceptor_start(OM_uint32 * minor_status,
             * Samba style get some flags (but not DCE-STYLE)
             */
            ctx->flags =
-               GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG;
+               GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG;
+           if (ap_options & AP_OPTS_MUTUAL_REQUIRED) {
+                   ctx->flags |= GSS_C_MUTUAL_FLAG;
+           }
         }
     }
 
diff --git a/source4/script/installmisc.sh b/source4/script/installmisc.sh
index 2bd34b1..0666ae1 100755
--- a/source4/script/installmisc.sh
+++ b/source4/script/installmisc.sh
@@ -8,11 +8,15 @@ cd $SRCDIR || exit 1
 
 echo "Installing setup templates"
 mkdir -p $SETUPDIR || exit 1
+mkdir -p $SETUPDIR/ad-schema || exit 1
+cp setup/ad-schema/*.txt $SETUPDIR/ad-schema || exit 1
+for p in enableaccount newuser provision provision-backend setexpiry 
setpassword
+do
+       chmod 0555 setup/$p
+       cp setup/$p $SETUPDIR || exit 1
+done
 cp setup/schema-map-* $SETUPDIR || exit 1
 cp setup/DB_CONFIG $SETUPDIR || exit 1
-cp setup/provision-backend $SETUPDIR || exit 1
-cp setup/provision $SETUPDIR || exit 1
-cp setup/newuser $SETUPDIR || exit 1
 cp setup/*.inf $SETUPDIR || exit 1
 cp setup/*.ldif $SETUPDIR || exit 1
 cp setup/*.reg $SETUPDIR || exit 1
diff --git a/source4/scripting/python/pyglue.c 
b/source4/scripting/python/pyglue.c
index 5816d96..c6b731c 100644
--- a/source4/scripting/python/pyglue.c
+++ b/source4/scripting/python/pyglue.c
@@ -204,6 +204,63 @@ static PyObject *py_dsdb_set_ntds_invocation_id(PyObject 
*self, PyObject *args)
        Py_RETURN_NONE;
 }
 
+static PyObject *py_dsdb_set_opaque_integer(PyObject *self, PyObject *args)
+{
+       PyObject *py_ldb;
+       int value;
+       int *old_val, *new_val;
+       char *py_opaque_name, *opaque_name_talloc;
+       struct ldb_context *ldb;
+       TALLOC_CTX *tmp_ctx;
+
+       if (!PyArg_ParseTuple(args, "Osi", &py_ldb, &py_opaque_name, &value))
+               return NULL;
+
+       PyErr_LDB_OR_RAISE(py_ldb, ldb);
+
+       /* see if we have a cached copy */
+       old_val = (int *)ldb_get_opaque(ldb, 
+                                       py_opaque_name);
+
+       if (old_val) {
+               *old_val = value;
+               Py_RETURN_NONE;
+       } 
+
+       tmp_ctx = talloc_new(ldb);
+       if (tmp_ctx == NULL) {
+               goto failed;
+       }
+       
+       new_val = talloc(tmp_ctx, int);
+       if (!new_val) {
+               goto failed;
+       }
+       
+       opaque_name_talloc = talloc_strdup(tmp_ctx, py_opaque_name);
+       if (!opaque_name_talloc) {
+               goto failed;
+       }
+       
+       *new_val = value;
+
+       /* cache the domain_sid in the ldb */
+       if (ldb_set_opaque(ldb, opaque_name_talloc, new_val) != LDB_SUCCESS) {
+               goto failed;
+       }
+
+       talloc_steal(ldb, new_val);
+       talloc_steal(ldb, opaque_name_talloc);
+       talloc_free(tmp_ctx);
+
+       Py_RETURN_NONE;
+
+failed:
+       talloc_free(tmp_ctx);
+       PyErr_SetString(PyExc_RuntimeError, "Failed to set opaque integer into 
the ldb!\n");
+       return NULL;
+}
+
 static PyObject *py_dsdb_set_global_schema(PyObject *self, PyObject *args)
 {
        PyObject *py_ldb;
@@ -284,6 +341,8 @@ static PyMethodDef py_misc_methods[] = {
                "Register Samba-specific LDB modules and schemas." },
        { "dsdb_set_ntds_invocation_id", 
(PyCFunction)py_dsdb_set_ntds_invocation_id, METH_VARARGS,
                NULL },
+       { "dsdb_set_opaque_integer", (PyCFunction)py_dsdb_set_opaque_integer, 
METH_VARARGS,
+               NULL },


-- 
Samba Shared Repository

Reply via email to