Merge branch 'v4-0-test' of git://git.samba.org/samba into 4-0-local
authorAndrew Bartlett <abartlet@samba.org>
Wed, 27 Feb 2008 23:33:54 +0000 (10:33 +1100)
committerAndrew Bartlett <abartlet@samba.org>
Wed, 27 Feb 2008 23:33:54 +0000 (10:33 +1100)
(This used to be commit ba864cfd7ce4b69179431131cac9661cbf48bf32)

15 files changed:
source4/auth/auth_sam.c
source4/auth/sam.c
source4/dsdb/common/util.c
source4/dsdb/samdb/ldb_modules/samldb.c
source4/lib/ldb/modules/rdn_name.c
source4/rpc_server/netlogon/dcerpc_netlogon.c
source4/rpc_server/samr/dcesrv_samr.c
source4/scripting/python/samba/provision.py
source4/setup/provision_self_join.ldif
source4/setup/provision_templates.ldif
source4/setup/provision_users.ldif
source4/torture/libnet/libnet_user.c
source4/torture/libnet/userman.c
source4/torture/rpc/samr.c
testprogs/ejs/ldap.js

index 918964015039951f11f605e394f1bce25eec40d2..4cb8d2b304f20661091d6d424d70a57e5e7d3c4f 100644 (file)
@@ -226,7 +226,9 @@ static NTSTATUS authsam_authenticate(struct auth_context *auth_context,
 {
        struct samr_Password *lm_pwd, *nt_pwd;
        NTSTATUS nt_status;
-       uint16_t acct_flags = samdb_result_acct_flags(msgs[0], "userAccountControl");
+       struct ldb_dn *domain_dn = samdb_result_dn(sam_ctx, mem_ctx, msgs_domain_ref[0], "nCName", NULL);
+
+       uint16_t acct_flags = samdb_result_acct_flags(sam_ctx, mem_ctx, msgs[0], domain_dn);
        
        /* Quit if the account was locked out. */
        if (acct_flags & ACB_AUTOLOCK) {
index fdd7de7c7103084805b63c7e18a1bb628e91e0fb..abcb72f292927540dce874ac2c9ee3c9847ec909 100644 (file)
@@ -156,7 +156,7 @@ _PUBLIC_ NTSTATUS authsam_account_ok(TALLOC_CTX *mem_ctx,
        NTTIME now;
        DEBUG(4,("authsam_account_ok: Checking SMB password for user %s\n", name_for_logs));
 
-       acct_flags = samdb_result_acct_flags(msg, "userAccountControl");
+       acct_flags = samdb_result_acct_flags(sam_ctx, mem_ctx, msg, domain_dn);
        
        acct_expiry = samdb_result_nttime(msg, "accountExpires", 0);
        must_change_time = samdb_result_force_password_change(sam_ctx, mem_ctx, 
@@ -186,22 +186,20 @@ _PUBLIC_ NTSTATUS authsam_account_ok(TALLOC_CTX *mem_ctx,
                return NT_STATUS_ACCOUNT_EXPIRED;
        }
 
-       if (!(acct_flags & ACB_PWNOEXP)) {
-               /* check for immediate expiry "must change at next logon" */
-               if (must_change_time == 0 && last_set_time != 0) {
-                       DEBUG(1,("sam_account_ok: Account for user '%s' password must change!.\n", 
-                                name_for_logs));
-                       return NT_STATUS_PASSWORD_MUST_CHANGE;
-               }
+       /* check for immediate expiry "must change at next logon" */
+       if (!(acct_flags & ACB_PWNOEXP) && (must_change_time == 0 && last_set_time != 0)) {
+               DEBUG(1,("sam_account_ok: Account for user '%s' password must change!.\n", 
+                        name_for_logs));
+               return NT_STATUS_PASSWORD_MUST_CHANGE;
+       }
 
-               /* check for expired password */
-               if ((must_change_time != 0) && (must_change_time < now)) {
-                       DEBUG(1,("sam_account_ok: Account for user '%s' password expired!.\n", 
-                                name_for_logs));
-                       DEBUG(1,("sam_account_ok: Password expired at '%s' unix time.\n", 
-                                nt_time_string(mem_ctx, must_change_time)));
-                       return NT_STATUS_PASSWORD_EXPIRED;
-               }
+       /* check for expired password (dynamicly gnerated in samdb_result_acct_flags) */
+       if (acct_flags & ACB_PW_EXPIRED) {
+               DEBUG(1,("sam_account_ok: Account for user '%s' password expired!.\n", 
+                        name_for_logs));
+               DEBUG(1,("sam_account_ok: Password expired at '%s' unix time.\n", 
+                        nt_time_string(mem_ctx, must_change_time)));
+               return NT_STATUS_PASSWORD_EXPIRED;
        }
 
        /* Test workstation. Workstation list is comma separated. */
@@ -267,6 +265,7 @@ _PUBLIC_ NTSTATUS authsam_make_server_info(TALLOC_CTX *mem_ctx, struct ldb_conte
        struct dom_sid **groupSIDs = NULL;
        struct dom_sid *account_sid;
        struct dom_sid *primary_group_sid;
+       struct ldb_dn *domain_dn;
        const char *str;
        struct ldb_dn *ncname;
        int i;
@@ -368,7 +367,10 @@ _PUBLIC_ NTSTATUS authsam_make_server_info(TALLOC_CTX *mem_ctx, struct ldb_conte
        server_info->logon_count = samdb_result_uint(msg, "logonCount", 0);
        server_info->bad_password_count = samdb_result_uint(msg, "badPwdCount", 0);
 
-       server_info->acct_flags = samdb_result_acct_flags(msg, "userAccountControl");
+       domain_dn = samdb_result_dn(sam_ctx, mem_ctx, msg_domain_ref, "nCName", NULL);
+
+       server_info->acct_flags = samdb_result_acct_flags(sam_ctx, mem_ctx, 
+                                                         msg, domain_dn);
 
        server_info->user_session_key = user_sess_key;
        server_info->lm_session_key = lm_sess_key;
index bee1eac480b3993d25aa652d2bb1e3894d6882e8..c9c0285604d705cb36583ba67af7953d07160609 100644 (file)
@@ -596,11 +596,37 @@ struct samr_LogonHours samdb_result_logon_hours(TALLOC_CTX *mem_ctx, struct ldb_
 
 /*
   pull a set of account_flags from a result set. 
+
+  This requires that the attributes: 
+   pwdLastSet
+   userAccountControl
+  be included in 'msg'
 */
-uint16_t samdb_result_acct_flags(struct ldb_message *msg, const char *attr)
-{
-       uint_t userAccountControl = ldb_msg_find_attr_as_uint(msg, attr, 0);
-       return samdb_uf2acb(userAccountControl);
+uint32_t samdb_result_acct_flags(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, 
+                                struct ldb_message *msg, struct ldb_dn *domain_dn)
+{
+       uint32_t userAccountControl = ldb_msg_find_attr_as_uint(msg, "userAccountControl", 0);
+       uint32_t acct_flags = samdb_uf2acb(userAccountControl); 
+       if ((userAccountControl & UF_NORMAL_ACCOUNT) && !(userAccountControl & UF_DONT_EXPIRE_PASSWD)) {
+               NTTIME must_change_time;
+               NTTIME pwdLastSet = samdb_result_nttime(msg, "pwdLastSet", 0);
+               if (pwdLastSet == 0) {
+                       acct_flags |= ACB_PW_EXPIRED;
+               } else {
+                       NTTIME now;
+                       
+                       must_change_time = samdb_result_force_password_change(sam_ctx, mem_ctx, 
+                                                                             domain_dn, msg);
+                       
+                       /* Test account expire time */
+                       unix_to_nt_time(&now, time(NULL));
+                       /* check for expired password */
+                       if ((must_change_time != 0) && (must_change_time < now)) {
+                               acct_flags |= ACB_PW_EXPIRED;
+                       }
+               }
+       }
+       return acct_flags;
 }
 
 
index 178149a8865d335db6252c9f2344519e73590ca8..905cd4a995d5916a8d81e2eea32b487886e3f3a1 100644 (file)
@@ -396,6 +396,7 @@ static int samldb_fill_group_object(struct ldb_module *module, const struct ldb_
                                                    struct ldb_message **ret_msg)
 {
        int ret;
+       unsigned int group_type;
        char *name;
        struct ldb_message *msg2;
        struct ldb_dn *dom_dn;
@@ -452,6 +453,26 @@ static int samldb_fill_group_object(struct ldb_module *module, const struct ldb_
                }
        }
        
+       if (ldb_msg_find_element(msg2, "sAMAccountType") != NULL) {
+               ldb_asprintf_errstring(module->ldb, "sAMAccountType must not be specified");
+               talloc_free(mem_ctx);
+               return LDB_ERR_UNWILLING_TO_PERFORM;
+       }
+       group_type = samdb_result_uint(msg2, "groupType", 0);
+       if (group_type == 0) {
+               ldb_asprintf_errstring(module->ldb, "groupType invalid");
+               talloc_free(mem_ctx);
+               return LDB_ERR_UNWILLING_TO_PERFORM;
+       } else {
+               unsigned int account_type = samdb_gtype2atype(group_type);
+               ret = samdb_msg_add_uint(module->ldb, msg2, msg2,
+                                        "sAMAccountType",
+                                        account_type);
+               if (ret != LDB_SUCCESS) {
+                       return ret;
+               }
+       }
+
        /* Manage SID allocation, conflicts etc */
        ret = samldb_handle_sid(module, mem_ctx, msg2, dom_dn); 
 
@@ -473,6 +494,7 @@ static int samldb_fill_user_or_computer_object(struct ldb_module *module, const
        const char *rdn_name;
        TALLOC_CTX *mem_ctx = talloc_new(msg);
        const char *errstr;
+       unsigned int user_account_control;
        if (!mem_ctx) {
                return LDB_ERR_OPERATIONS_ERROR;
        }
@@ -485,36 +507,15 @@ static int samldb_fill_user_or_computer_object(struct ldb_module *module, const
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
-       if (samdb_find_attribute(module->ldb, msg, "objectclass", "computer") != NULL) {
-
-               ret = samdb_copy_template(module->ldb, msg2, 
-                                         "computer",
-                                         &errstr);
-               if (ret) {
-                       ldb_asprintf_errstring(module->ldb, 
-                                              "samldb_fill_user_or_computer_object: "
-                                              "Error copying computer template: %s",
-                                              errstr);
-                       talloc_free(mem_ctx);
-                       return ret;
-               }
-       } else {
-               ret = samdb_copy_template(module->ldb, msg2, 
-                                         "user",
-                                         &errstr);
-               if (ret) {
-                       ldb_asprintf_errstring(module->ldb, 
-                                              "samldb_fill_user_or_computer_object: Error copying user template: %s\n",
-                                              errstr);
-                       talloc_free(mem_ctx);
-                       return ret;
-               }
-               /* readd user objectclass */
-               ret = samdb_find_or_add_value(module->ldb, msg2, "objectclass", "user");
-               if (ret) {
-                       talloc_free(mem_ctx);
-                       return ret;
-               }
+       ret = samdb_copy_template(module->ldb, msg2, 
+                                 "user",
+                                 &errstr);
+       if (ret) {
+               ldb_asprintf_errstring(module->ldb, 
+                                      "samldb_fill_user_or_computer_object: Error copying user template: %s\n",
+                                      errstr);
+               talloc_free(mem_ctx);
+               return ret;
        }
 
        rdn_name = ldb_dn_get_rdn_name(msg2->dn);
@@ -545,14 +546,30 @@ static int samldb_fill_user_or_computer_object(struct ldb_module *module, const
                }
        }
 
-       /*
-         TODO: useraccountcontrol: setting value 0 gives 0x200 for users
-       */
+       if (ldb_msg_find_element(msg2, "sAMAccountType") != NULL) {
+               ldb_asprintf_errstring(module->ldb, "sAMAccountType must not be specified");
+               talloc_free(mem_ctx);
+               return LDB_ERR_UNWILLING_TO_PERFORM;
+       }
+       user_account_control = samdb_result_uint(msg2, "userAccountControl", 0);
+       if (user_account_control == 0) {
+               ldb_asprintf_errstring(module->ldb, "userAccountControl invalid");
+               talloc_free(mem_ctx);
+               return LDB_ERR_UNWILLING_TO_PERFORM;
+       } else {
+               unsigned int account_type = samdb_uf2atype(user_account_control);
+               ret = samdb_msg_add_uint(module->ldb, msg2, msg2,
+                                        "sAMAccountType",
+                                        account_type);
+               if (ret != LDB_SUCCESS) {
+                       return ret;
+               }
+       }
 
        /* Manage SID allocation, conflicts etc */
        ret = samldb_handle_sid(module, mem_ctx, msg2, dom_dn); 
 
-       /* TODO: objectCategory, userAccountControl, badPwdCount, codePage, countryCode, badPasswordTime, lastLogoff, lastLogon, pwdLastSet, primaryGroupID, accountExpires, logonCount */
+       /* TODO: userAccountControl, badPwdCount, codePage, countryCode, badPasswordTime, lastLogoff, lastLogon, pwdLastSet, primaryGroupID, accountExpires, logonCount */
 
        if (ret == 0) {
                *ret_msg = msg2;
@@ -689,7 +706,7 @@ static int samldb_add(struct ldb_module *module, struct ldb_request *req)
        }
 
        /* is user or computer? */
-       if ((samdb_find_attribute(module->ldb, msg, "objectclass", "user") != NULL) ||
+       if ((samdb_find_attribute(module->ldb, msg, "objectclass", "user") != NULL) || 
            (samdb_find_attribute(module->ldb, msg, "objectclass", "computer") != NULL)) {
                /*  add all relevant missing objects */
                ret = samldb_fill_user_or_computer_object(module, msg, &msg2);
@@ -745,6 +762,53 @@ static int samldb_add(struct ldb_module *module, struct ldb_request *req)
        return ret;
 }
 
+/* modify */
+static int samldb_modify(struct ldb_module *module, struct ldb_request *req)
+{
+       struct ldb_message *msg;
+       struct ldb_message_element *el, *el2;
+       int ret;
+       unsigned int group_type, user_account_control, account_type;
+       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;
+       }
+
+       el = ldb_msg_find_element(req->op.mod.message, "groupType");
+       if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
+               req->op.mod.message = msg = ldb_msg_copy_shallow(req, req->op.mod.message);
+
+               group_type = strtoul((const char *)el->values[0].data, NULL, 0);
+               account_type =  samdb_gtype2atype(group_type);
+               ret = samdb_msg_add_uint(module->ldb, msg, msg,
+                                        "sAMAccountType",
+                                        account_type);
+               if (ret != LDB_SUCCESS) {
+                       return ret;
+               }
+               el2 = ldb_msg_find_element(msg, "sAMAccountType");
+               el2->flags = LDB_FLAG_MOD_REPLACE;
+       }
+
+       el = ldb_msg_find_element(req->op.mod.message, "userAccountControl");
+       if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
+               req->op.mod.message = msg = ldb_msg_copy_shallow(req, req->op.mod.message);
+
+               user_account_control = strtoul((const char *)el->values[0].data, NULL, 0);
+               account_type = samdb_uf2atype(user_account_control);
+               ret = samdb_msg_add_uint(module->ldb, msg, msg,
+                                        "sAMAccountType",
+                                        account_type);
+               if (ret != LDB_SUCCESS) {
+                       return ret;
+               }
+               el2 = ldb_msg_find_element(msg, "sAMAccountType");
+               el2->flags = LDB_FLAG_MOD_REPLACE;
+       }
+       return ldb_next_request(module, req);
+}
+
+
 static int samldb_init(struct ldb_module *module)
 {
        return ldb_next_init(module);
@@ -754,4 +818,5 @@ _PUBLIC_ const struct ldb_module_ops ldb_samldb_module_ops = {
        .name          = "samldb",
        .init_context  = samldb_init,
        .add           = samldb_add,
+       .modify        = samldb_modify
 };
index c4de8e8da8b376ee5dd4f1127c3962d76e543db6..65c044c0f4127c2ef0cf230854904adbc69660e2 100644 (file)
@@ -119,7 +119,8 @@ static int rdn_name_add(struct ldb_module *module, struct ldb_request *req)
                                      "RDN mismatch on %s: %s (%s)", 
                                      ldb_dn_get_linearized(msg->dn), rdn_name, rdn_val.data);
                        talloc_free(down_req);
-                       return LDB_ERR_OPERATIONS_ERROR;
+                       /* Match AD's error here */
+                       return LDB_ERR_INVALID_DN_SYNTAX;
                }
        }
 
index 4d38dc069e9f7f338f564b8875a325a765b647be..37e6351864093e818895bb788c04837791f28514 100644 (file)
@@ -27,6 +27,7 @@
 #include "auth/auth.h"
 #include "auth/auth_sam_reply.h"
 #include "dsdb/samdb/samdb.h"
+#include "dsdb/common/flags.h"
 #include "rpc_server/samr/proto.h"
 #include "util/util_ldb.h"
 #include "libcli/auth/libcli_auth.h"
@@ -76,7 +77,7 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca
        struct creds_CredentialState *creds;
        void *sam_ctx;
        struct samr_Password *mach_pwd;
-       uint16_t acct_flags;
+       uint32_t user_account_control;
        int num_records;
        struct ldb_message **msgs;
        NTSTATUS nt_status;
@@ -113,27 +114,28 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
        }
 
-       acct_flags = samdb_result_acct_flags(msgs[0], 
-                                            "userAccountControl");
+       
+       user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
 
-       if (acct_flags & ACB_DISABLED) {
+       if (user_account_control & UF_ACCOUNTDISABLE) {
                DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
                return NT_STATUS_ACCESS_DENIED;
        }
 
        if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
-               if (!(acct_flags & ACB_WSTRUST)) {
-                       DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", acct_flags));
+               if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
+                       DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
                        return NT_STATUS_ACCESS_DENIED;
                }
        } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN) {
-               if (!(acct_flags & ACB_DOMTRUST)) {
-                       DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", acct_flags));
+               if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
+                       DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
+                       
                        return NT_STATUS_ACCESS_DENIED;
                }
        } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
-               if (!(acct_flags & ACB_SVRTRUST)) {
-                       DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", acct_flags));
+               if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
+                       DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
                        return NT_STATUS_ACCESS_DENIED;
                }
        } else {
index 760d774f2ea6ebc46a8bcebaf199bb077f8e894f..8193e0a882abc5bb3234bb7d39100b10c1de9b31 100644 (file)
@@ -56,7 +56,7 @@
 #define QUERY_LHOURS(msg, field, attr) \
        r->out.info->field = samdb_result_logon_hours(mem_ctx, msg, attr);
 #define QUERY_AFLAGS(msg, field, attr) \
-       r->out.info->field = samdb_result_acct_flags(msg, attr);
+       r->out.info->field = samdb_result_acct_flags(sam_ctx, mem_ctx, msg, a_state->domain_state->domain_dn);
 
 
 /* these are used to make the Set[User|Group]Info code easier to follow */
         set_el = ldb_msg_find_element(msg, attr);                      \
        set_el->flags = LDB_FLAG_MOD_REPLACE;                           \
 } while (0)                                                            
-                                                                       
+
+#define CHECK_FOR_MULTIPLES(value, flag, poss_flags)   \
+       do { \
+               if ((value & flag) && ((value & flag) != (value & (poss_flags)))) { \
+                       return NT_STATUS_INVALID_PARAMETER;             \
+               }                                                       \
+       } while (0)                                                     \
+       
+/* Set account flags, discarding flags that cannot be set with SAMR */                                                         
 #define SET_AFLAGS(msg, field, attr) do {                              \
        struct ldb_message_element *set_el;                             \
-       if (samdb_msg_add_acct_flags(sam_ctx, mem_ctx, msg, attr, r->in.info->field) != 0) { \
+       if ((r->in.info->field & (ACB_NORMAL | ACB_DOMTRUST | ACB_WSTRUST | ACB_SVRTRUST)) == 0) { \
+               return NT_STATUS_INVALID_PARAMETER; \
+       }                                                               \
+       CHECK_FOR_MULTIPLES(r->in.info->field, ACB_NORMAL, ACB_NORMAL | ACB_DOMTRUST | ACB_WSTRUST | ACB_SVRTRUST); \
+       CHECK_FOR_MULTIPLES(r->in.info->field, ACB_DOMTRUST, ACB_NORMAL | ACB_DOMTRUST | ACB_WSTRUST | ACB_SVRTRUST); \
+       CHECK_FOR_MULTIPLES(r->in.info->field, ACB_WSTRUST, ACB_NORMAL | ACB_DOMTRUST | ACB_WSTRUST | ACB_SVRTRUST); \
+       CHECK_FOR_MULTIPLES(r->in.info->field, ACB_SVRTRUST, ACB_NORMAL | ACB_DOMTRUST | ACB_WSTRUST | ACB_SVRTRUST); \
+       if (samdb_msg_add_acct_flags(sam_ctx, mem_ctx, msg, attr, (r->in.info->field & ~(ACB_AUTOLOCK|ACB_PW_EXPIRED))) != 0) { \
                return NT_STATUS_NO_MEMORY;                             \
        }                                                               \
         set_el = ldb_msg_find_element(msg, attr);                      \
@@ -1484,8 +1499,8 @@ static NTSTATUS dcesrv_samr_EnumDomainUsers(struct dcesrv_call_state *dce_call,
        for (i=0;i<count;i++) {
                /* Check if a mask has been requested */
                if (r->in.acct_flags
-                   && ((samdb_result_acct_flags(res[i], 
-                                                "userAccountControl") & r->in.acct_flags) == 0)) {
+                   && ((samdb_result_acct_flags(d_state->sam_ctx, mem_ctx, res[i], 
+                                                d_state->domain_dn) & r->in.acct_flags) == 0)) {
                        continue;
                }
                entries[num_filtered_entries].idx = samdb_result_rid_from_sid(mem_ctx, res[i], "objectSid", 0);
@@ -3066,7 +3081,7 @@ static NTSTATUS dcesrv_samr_QueryUserInfo(struct dcesrv_call_state *dce_call, TA
        }
        case 16:
        {
-               static const char * const attrs2[] = {"userAccountControl", NULL};
+               static const char * const attrs2[] = {"userAccountControl", "pwdLastSet", NULL};
                attrs = attrs2;
                break;
        }
@@ -3613,7 +3628,7 @@ static NTSTATUS dcesrv_samr_QueryDisplayInfo(struct dcesrv_call_state *dce_call,
        struct ldb_message **res;
        int ldb_cnt, count, i;
        const char * const attrs[] = { "objectSid", "sAMAccountName", "displayName",
-                                       "description", "userAccountControl", NULL };
+                                      "description", "userAccountControl", "pwdLastSet", NULL };
        struct samr_DispEntryFull *entriesFull = NULL;
        struct samr_DispEntryFullGroup *entriesFullGroup = NULL;
        struct samr_DispEntryAscii *entriesAscii = NULL;
@@ -3702,8 +3717,9 @@ static NTSTATUS dcesrv_samr_QueryDisplayInfo(struct dcesrv_call_state *dce_call,
                        entriesGeneral[count].rid = 
                                objectsid->sub_auths[objectsid->num_auths-1];
                        entriesGeneral[count].acct_flags =
-                               samdb_result_acct_flags(res[i], 
-                                                       "userAccountControl");
+                               samdb_result_acct_flags(d_state->sam_ctx, mem_ctx,
+                                                       res[i], 
+                                                       d_state->domain_dn);
                        entriesGeneral[count].account_name.string =
                                samdb_result_string(res[i],
                                                    "sAMAccountName", "");
@@ -3719,8 +3735,9 @@ static NTSTATUS dcesrv_samr_QueryDisplayInfo(struct dcesrv_call_state *dce_call,
 
                        /* No idea why we need to or in ACB_NORMAL here, but this is what Win2k3 seems to do... */
                        entriesFull[count].acct_flags =
-                               samdb_result_acct_flags(res[i], 
-                                                       "userAccountControl") | ACB_NORMAL;
+                               samdb_result_acct_flags(d_state->sam_ctx, mem_ctx,
+                                                       res[i], 
+                                                       d_state->domain_dn) | ACB_NORMAL;
                        entriesFull[count].account_name.string =
                                samdb_result_string(res[i], "sAMAccountName",
                                                    "");
@@ -3731,9 +3748,6 @@ static NTSTATUS dcesrv_samr_QueryDisplayInfo(struct dcesrv_call_state *dce_call,
                        entriesFullGroup[count].idx = count + 1;
                        entriesFullGroup[count].rid =
                                objectsid->sub_auths[objectsid->num_auths-1];
-                       entriesFullGroup[count].acct_flags =
-                               samdb_result_acct_flags(res[i], 
-                                                       "userAccountControl");
                        /* We get a "7" here for groups */
                        entriesFullGroup[count].acct_flags
                                = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED;
index e3c47ff4a2c902e07be025047d56e96bbab7c075..55935b0037cb3fac81fb20a7e1d604ba1a24a93a 100644 (file)
@@ -313,9 +313,9 @@ def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info,
                     "server_sort",
                     "extended_dn",
                     "asq",
-                    "samldb",
                     "rdn_name",
                     "objectclass",
+                    "samldb",
                     "kludge_acl",
                     "operational"]
     tdb_modules_list = [
index 58669660f4d339b2f8f195b1bc00965a7271919c..503656a9bff00b894e4db98179b72b50e75b7132 100644 (file)
@@ -8,7 +8,6 @@ localPolicyFlags: 0
 primaryGroupID: 516
 accountExpires: 9223372036854775807
 sAMAccountName: ${NETBIOSNAME}$
-sAMAccountType: 805306369
 operatingSystem: Samba
 operatingSystemVersion: 4.0
 dNSHostName: ${DNSNAME}
@@ -33,7 +32,6 @@ description: DNS Service Account
 userAccountControl: 514
 accountExpires: 9223372036854775807
 sAMAccountName: dns
-sAMAccountType: 805306368
 servicePrincipalName: DNS/${DNSDOMAIN}
 isCriticalSystemObject: TRUE
 sambaPassword:: ${DNSPASS_B64}
index fafedc6966925160a9f07d492facf710caee4f09..cc0ab212cdc6c96433e190542c48156784f31753 100644 (file)
@@ -18,7 +18,7 @@ objectClass: container
 description: Container for SAM account templates
 
 dn: CN=TemplateUser,CN=Templates
-userAccountControl: 514
+userAccountControl: 546
 badPwdCount: 0
 codePage: 0
 countryCode: 0
@@ -29,21 +29,6 @@ pwdLastSet: 0
 primaryGroupID: 513
 accountExpires: -1
 logonCount: 0
-sAMAccountType: 805306368
-
-dn: CN=TemplateComputer,CN=Templates
-userAccountControl: 4098
-badPwdCount: 0
-codePage: 0
-countryCode: 0
-badPasswordTime: 0
-lastLogoff: 0
-lastLogon: 0
-pwdLastSet: 0
-primaryGroupID: 513
-accountExpires: -1
-logonCount: 0
-sAMAccountType: 805306369
 
 dn: CN=TemplateTrustingDomain,CN=Templates
 userAccountControl: 2080
@@ -56,18 +41,9 @@ lastLogon: 0
 primaryGroupID: 513
 accountExpires: -1
 logonCount: 0
-sAMAccountType: 805306370
 
 dn: CN=TemplateGroup,CN=Templates
 groupType: -2147483646
-sAMAccountType: 268435456
-
-# Currently this isn't used, we don't have a way to detect it different from an incoming alias
-#
-# dn: CN=TemplateAlias,CN=Templates
-# cn: TemplateAlias
-# groupType: -2147483644
-# sAMAccountType: 268435456
 
 dn: CN=TemplateForeignSecurityPrincipal,CN=Templates
 
index 05fde1597405e2999510f94a3d82db11daee4569..4b053d916635b76451d05b7d18762b69722f774d 100644 (file)
@@ -44,7 +44,6 @@ objectSid: ${DOMAINSID}-502
 adminCount: 1
 accountExpires: 9223372036854775807
 sAMAccountName: krbtgt
-sAMAccountType: 805306368
 servicePrincipalName: kadmin/changepw
 isCriticalSystemObject: TRUE
 sambaPassword:: ${KRBTGTPASS_B64}
@@ -85,7 +84,6 @@ objectClass: group
 cn: Cert Publishers
 description: Members of this group are permitted to publish certificates to the Active Directory
 groupType: 2147483652
-sAMAccountType: 536870912
 objectSid: ${DOMAINSID}-517
 sAMAccountName: Cert Publishers
 isCriticalSystemObject: TRUE
@@ -136,7 +134,6 @@ 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
-sAMAccountType: 536870912
 groupType: 2147483652
 isCriticalSystemObject: TRUE
 
@@ -151,7 +148,6 @@ member: CN=Administrator,CN=Users,${DOMAINDN}
 objectSid: S-1-5-32-544
 adminCount: 1
 sAMAccountName: Administrators
-sAMAccountType: 536870912
 systemFlags: 2348810240
 groupType: 2147483653
 isCriticalSystemObject: TRUE
@@ -188,7 +184,6 @@ description: Users are prevented from making accidental or intentional system-wi
 member: CN=Domain Users,CN=Users,${DOMAINDN}
 objectSid: S-1-5-32-545
 sAMAccountName: Users
-sAMAccountType: 536870912
 systemFlags: 2348810240
 groupType: 2147483653
 isCriticalSystemObject: TRUE
@@ -202,7 +197,6 @@ member: CN=Domain Guests,CN=Users,${DOMAINDN}
 member: CN=Guest,CN=Users,${DOMAINDN}
 objectSid: S-1-5-32-546
 sAMAccountName: Guests
-sAMAccountType: 536870912
 systemFlags: 2348810240
 groupType: 2147483653
 isCriticalSystemObject: TRUE
@@ -215,7 +209,6 @@ description: Members can administer domain printers
 objectSid: S-1-5-32-550
 adminCount: 1
 sAMAccountName: Print Operators
-sAMAccountType: 536870912
 systemFlags: 2348810240
 groupType: 2147483653
 isCriticalSystemObject: TRUE
@@ -231,7 +224,6 @@ description: Backup Operators can override security restrictions for the sole pu
 objectSid: S-1-5-32-551
 adminCount: 1
 sAMAccountName: Backup Operators
-sAMAccountType: 536870912
 systemFlags: 2348810240
 groupType: 2147483653
 isCriticalSystemObject: TRUE
@@ -248,7 +240,6 @@ description: Supports file replication in a domain
 objectSid: S-1-5-32-552
 adminCount: 1
 sAMAccountName: Replicator
-sAMAccountType: 536870912
 systemFlags: 2348810240
 groupType: 2147483653
 isCriticalSystemObject: TRUE
@@ -260,7 +251,6 @@ cn: Remote Desktop Users
 description: Members in this group are granted the right to logon remotely
 objectSid: S-1-5-32-555
 sAMAccountName: Remote Desktop Users
-sAMAccountType: 536870912
 systemFlags: 2348810240
 groupType: 2147483653
 isCriticalSystemObject: TRUE
@@ -272,7 +262,6 @@ cn: Network Configuration Operators
 description: Members in this group can have some administrative privileges to manage configuration of networking features
 objectSid: S-1-5-32-556
 sAMAccountName: Network Configuration Operators
-sAMAccountType: 536870912
 systemFlags: 2348810240
 groupType: 2147483653
 isCriticalSystemObject: TRUE
@@ -284,7 +273,6 @@ cn: Performance Monitor Users
 description: Members of this group have remote access to monitor this computer
 objectSid: S-1-5-32-558
 sAMAccountName: Performance Monitor Users
-sAMAccountType: 536870912
 systemFlags: 2348810240
 groupType: 2147483653
 isCriticalSystemObject: TRUE
@@ -296,7 +284,6 @@ cn: Performance Log Users
 description: Members of this group have remote access to schedule logging of performance counters on this computer
 objectSid: S-1-5-32-559
 sAMAccountName: Performance Log Users
-sAMAccountType: 536870912
 systemFlags: 2348810240
 groupType: 2147483653
 isCriticalSystemObject: TRUE
@@ -309,7 +296,6 @@ description: Members can administer domain servers
 objectSid: S-1-5-32-549
 adminCount: 1
 sAMAccountName: Server Operators
-sAMAccountType: 536870912
 systemFlags: 2348810240
 groupType: 2147483653
 isCriticalSystemObject: TRUE
@@ -328,7 +314,6 @@ description: Members can administer domain user and group accounts
 objectSid: S-1-5-32-548
 adminCount: 1
 sAMAccountName: Account Operators
-sAMAccountType: 536870912
 systemFlags: 2348810240
 groupType: 2147483653
 isCriticalSystemObject: TRUE
@@ -341,7 +326,6 @@ cn: Pre-Windows 2000 Compatible Access
 description: A backward compatibility group which allows read access on all users and groups in the domain
 objectSid: S-1-5-32-554
 sAMAccountName: Pre-Windows 2000 Compatible Access
-sAMAccountType: 536870912
 systemFlags: 2348810240
 groupType: 2147483653
 isCriticalSystemObject: TRUE
@@ -355,7 +339,6 @@ cn: Incoming Forest Trust Builders
 description: Members of this group can create incoming, one-way trusts to this forest
 objectSid: S-1-5-32-557
 sAMAccountName: Incoming Forest Trust Builders
-sAMAccountType: 536870912
 systemFlags: 2348810240
 groupType: 2147483653
 isCriticalSystemObject: TRUE
@@ -367,7 +350,6 @@ cn: Windows Authorization Access Group
 description: Members of this group have access to the computed tokenGroupsGlobalAndUniversal attribute on User objects
 objectSid: S-1-5-32-560
 sAMAccountName: Windows Authorization Access Group
-sAMAccountType: 536870912
 systemFlags: 2348810240
 groupType: 2147483653
 isCriticalSystemObject: TRUE
@@ -379,7 +361,6 @@ cn: Terminal Server License Servers
 description: Terminal Server License Servers
 objectSid: S-1-5-32-561
 sAMAccountName: Terminal Server License Servers
-sAMAccountType: 536870912
 systemFlags: 2348810240
 groupType: 2147483653
 isCriticalSystemObject: TRUE
@@ -391,7 +372,6 @@ cn: Distributed COM Users
 description: Members are allowed to launch, activate and use Distributed COM objects on this machine.
 objectSid: S-1-5-32-562
 sAMAccountName: Distributed COM Users
-sAMAccountType: 536870912
 systemFlags: 2348810240
 groupType: 2147483653
 isCriticalSystemObject: TRUE
index 6ea670629e92e216496eb16b2118dafd95b959d1..31300a793774606eb9d1781a7e1de348d74d495c 100644 (file)
@@ -339,12 +339,13 @@ static void set_test_changes(TALLOC_CTX *mem_ctx, struct libnet_ModifyUser *r,
        const char* logon_scripts[] = { "start_login.cmd", "login.bat", "start.cmd" };
        const char* home_dirs[] = { "\\\\srv\\home", "\\\\homesrv\\home\\user", "\\\\pdcsrv\\domain" };
        const char* home_drives[] = { "H:", "z:", "I:", "J:", "n:" };
+       const uint32_t flags[] = { (ACB_DISABLED | ACB_NORMAL),
+                                  (ACB_NORMAL | ACB_PWNOEXP),
+                                  (ACB_NORMAL) };
        const char *homedir, *homedrive, *logonscript;
        struct timeval now;
        int i, testfld;
 
-       srandom((unsigned)time(NULL));
-
        printf("Fields to change: [");
 
        for (i = 0; i < num_changes && i < FIELDS_NUM; i++) {
@@ -382,14 +383,14 @@ static void set_test_changes(TALLOC_CTX *mem_ctx, struct libnet_ModifyUser *r,
 
                case home_directory:
                        continue_if_field_set(r->in.home_directory);
-                       homedir = home_dirs[random() % (sizeof(home_dirs)/sizeof(char*))];
+                       homedir = home_dirs[random() % ARRAY_SIZE(home_dirs)];
                        r->in.home_directory = talloc_strdup(mem_ctx, homedir);
                        fldname = "home_dir";
                        break;
 
                case home_drive:
                        continue_if_field_set(r->in.home_drive);
-                       homedrive = home_drives[random() % (sizeof(home_drives)/sizeof(char*))];
+                       homedrive = home_drives[random() % ARRAY_SIZE(home_drives)];
                        r->in.home_drive = talloc_strdup(mem_ctx, homedrive);
                        fldname = "home_drive";
                        break;
@@ -403,7 +404,7 @@ static void set_test_changes(TALLOC_CTX *mem_ctx, struct libnet_ModifyUser *r,
 
                case logon_script:
                        continue_if_field_set(r->in.logon_script);
-                       logonscript = logon_scripts[random() % (sizeof(logon_scripts)/sizeof(char*))];
+                       logonscript = logon_scripts[random() % ARRAY_SIZE(logon_scripts)];
                        r->in.logon_script = talloc_strdup(mem_ctx, logonscript);
                        fldname = "logon_script";
                        break;
@@ -422,6 +423,12 @@ static void set_test_changes(TALLOC_CTX *mem_ctx, struct libnet_ModifyUser *r,
                        fldname = "acct_expiry";
                        break;
 
+               case acct_flags:
+                       continue_if_field_set(r->in.acct_flags);
+                       r->in.acct_flags = flags[random() % ARRAY_SIZE(flags)];
+                       fldname = "acct_flags";
+                       break;
+
                default:
                        fldname = "unknown_field";
                }
index 0d08284a9f955e2220bd1ac36221093fd3b84023..1d630e5ecdb3c08ea86a17a9e7a8076ac33e2f22 100644 (file)
@@ -189,7 +189,7 @@ static bool test_usermod(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 
                case acct_flags:
                        continue_if_field_set(mod->in.change.acct_flags);
-                       mod->in.change.acct_flags = flags[random() % (sizeof(flags)/sizeof(uint32_t))];
+                       mod->in.change.acct_flags = flags[random() % ARRAY_SIZE(flags)];
                        mod->in.change.fields |= USERMOD_FIELD_ACCT_FLAGS;
                        fldname = "acct_flags";
                        break;
index 9d6c73891b883e53b1f506c3b60ab5c6c524635e..1d6ec4339987e3cd0fb60e828efa35f67df2649f 100644 (file)
@@ -416,11 +416,6 @@ static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx
        TEST_USERINFO_INT(21, logon_hours.bits[3], 21, logon_hours.bits[3], 4, 
                          SAMR_FIELD_LOGON_HOURS);
 
-       if (torture_setting_bool(tctx, "samba4", false)) {
-               printf("skipping Set Account Flag tests against Samba4\n");
-               return ret;
-       }
-
        TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags, 
                              (base_acct_flags  | ACB_DISABLED | ACB_HOMDIRREQ), 
                              (base_acct_flags  | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags), 
@@ -1989,9 +1984,12 @@ static bool test_user_ops(struct dcerpc_pipe *p,
                          const char *base_acct_name, enum torture_samr_choice which_ops)
 {
        char *password = NULL;
+       struct samr_QueryUserInfo q;
+       NTSTATUS status;
 
        bool ret = true;
        int i;
+       uint32_t rid;
        const uint32_t password_fields[] = {
                SAMR_FIELD_PASSWORD,
                SAMR_FIELD_PASSWORD2,
@@ -1999,6 +1997,11 @@ static bool test_user_ops(struct dcerpc_pipe *p,
                0
        };
        
+       status = test_LookupName(p, tctx, domain_handle, base_acct_name, &rid);
+       if (!NT_STATUS_IS_OK(status)) {
+               ret = false;
+       }
+
        switch (which_ops) {
        case TORTURE_SAMR_USER_ATTRIBUTES:
                if (!test_QuerySecurity(p, tctx, user_handle)) {
@@ -2091,6 +2094,29 @@ static bool test_user_ops(struct dcerpc_pipe *p,
                        ret = false;
                }       
 
+               q.in.user_handle = user_handle;
+               q.in.level = 5;
+               
+               status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
+               if (!NT_STATUS_IS_OK(status)) {
+                       printf("QueryUserInfo level %u failed - %s\n", 
+                              q.in.level, nt_errstr(status));
+                       ret = false;
+               } else {
+                       uint32_t expected_flags = (base_acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
+                       if ((q.out.info->info5.acct_flags) != expected_flags) {
+                               printf("QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
+                                      q.out.info->info5.acct_flags, 
+                                      expected_flags);
+                               ret = false;
+                       }
+                       if (q.out.info->info5.rid != rid) {
+                               printf("QuerUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
+                                      q.out.info->info5.rid, rid);
+
+                       }
+               }
+
                break;
        case TORTURE_SAMR_OTHER:
                /* We just need the account to exist */
@@ -2667,10 +2693,14 @@ static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx
                                       q.in.level, nt_errstr(status));
                                ret = false;
                        } else {
-                               if ((q.out.info->info5.acct_flags & acct_flags) != acct_flags) {
+                               uint32_t expected_flags = (acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
+                               if (acct_flags == ACB_NORMAL) {
+                                       expected_flags |= ACB_PW_EXPIRED;
+                               }
+                               if ((q.out.info->info5.acct_flags) != expected_flags) {
                                        printf("QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
                                               q.out.info->info5.acct_flags, 
-                                              acct_flags);
+                                              expected_flags);
                                        ret = false;
                                } 
                                switch (acct_flags) {
@@ -3887,7 +3917,6 @@ static bool test_GroupList(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                        for (j=0; j<num_names; j++) {
                                if (names[j] == NULL)
                                        continue;
-                               /* Hmm. No strequal in samba4 */
                                if (strequal(names[j], name)) {
                                        names[j] = NULL;
                                        found = true;
index 090f93b6ca7e291d165e9e7e68c481eb86c62160..c30f29e2495738862c5685d2e9999154d8216908 100755 (executable)
@@ -29,14 +29,19 @@ function basic_tests(ldb, gc_ldb, base_dn, configuration_dn, schema_dn)
 {
        println("Running basic tests");
 
+       ldb.del("cn=ldaptestcomputer,cn=computers," + base_dn);
+       ldb.del("cn=ldaptestcomputer3,cn=computers," + base_dn);
+       ldb.del("cn=ldaptest2computer,cn=computers," + base_dn);
        ldb.del("cn=ldaptestuser,cn=users," + base_dn);
        ldb.del("cn=ldaptestuser2,cn=users," + base_dn);
        ldb.del("cn=ldaptestuser3,cn=users," + base_dn);
        ldb.del("cn=ldaptestuser4,cn=users," + base_dn);
        ldb.del("cn=ldaptestuser5,cn=users," + base_dn);
        ldb.del("CN=ldaptestuser4,CN=ldaptestcontainer2," + base_dn);
+       ldb.del("cn=ldaptestuser7,cn=users," + base_dn);
        ldb.del("CN=ldaptestcontainer2," + base_dn);
        ldb.del("cn=ldaptestgroup,cn=users," + base_dn);
+       ldb.del("cn=ldaptestgroup2,cn=users," + base_dn);
 
        println("Testing group add with invalid member");
        var ok = ldb.add("
@@ -127,7 +132,7 @@ displayname: ldap testy
                ok = ldb.del("cn=ldaptest2computer,cn=computers," + base_dn);
                if (ok.error != 0) {
                        println(ok.errstr);
-                       assert(ok.error == 0);
+               //      assert(ok.error == 0);
                }
                ok = ldb.add("
 dn: cn=ldaptest2computer,cn=computers," + base_dn + "
@@ -142,6 +147,113 @@ displayname: ldap testy
                }
        }
 
+       var ok = ldb.add("
+dn: cn=ldaptestcomputer3,cn=computers," + base_dn + "
+objectClass: computer
+cn: LDAPtest2COMPUTER
+");
+       if (ok.error != 34) {
+               println("Did not reject invalid RDN compared with DN: " + ok.errstr);
+               assert(ok.error == 34);
+       }
+
+       var ok = ldb.add("
+dn: cn=ldaptestcomputer3,cn=computers," + base_dn + "
+objectClass: computer
+cn: LDAPtestCOMPUTER3
+sAMAccountType: 805306368
+");
+
+       if (ok.error != 53) {
+               println("Did not reject invalid 'sAMAccountType: 805306368': " + ok.errstr);
+               assert(ok.error == 53);
+       }
+
+       var ok = ldb.add("
+dn: cn=ldaptestcomputer3,cn=computers," + base_dn + "
+objectClass: computer
+cn: LDAPtestCOMPUTER3
+userAccountControl: 0
+");
+
+       if (ok.error != 53) {
+               println("Did not reject invalid 'userAccountControl: 0': " + ok.errstr);
+               assert(ok.error == 53);
+       }
+
+       var ok = ldb.add("
+dn: cn=ldaptestuser7,cn=users," + base_dn + "
+objectClass: user
+cn: LDAPtestuser7
+userAccountControl: 0
+");
+
+       if (ok.error != 53) {
+               println("Did not reject invalid 'userAccountControl: 0': " + ok.errstr);
+               assert(ok.error == 53);
+       }
+
+       var ok = ldb.add("
+dn: cn=ldaptestuser7,cn=users," + base_dn + "
+objectClass: user
+cn: LDAPtestuser7
+userAccountControl: 2
+");
+
+       if (ok.error != 0) {
+               println("Did not accept 'userAccountControl: 2': " + ok.errstr);
+               assert(ok.error == 0);
+       }
+
+           ldb.del("cn=ldaptestuser7,cn=users," + base_dn);
+
+       var ok = ldb.add("
+dn: cn=ldaptestcomputer3,cn=computers," + base_dn + "
+objectclass: computer
+cN: LDAPtestCOMPUTER3
+");
+       if (ok.error != 0) {
+               ok = ldb.del("cn=ldaptestcomputer3,cn=computers," + base_dn);
+               if (ok.error != 0) {
+                       println(ok.errstr);
+                       assert(ok.error == 0);
+               }
+               ok = ldb.add("
+dn: cn=ldaptestcomputer3,cn=computers," + base_dn + "
+objectClass: computer
+cn: LDAPtestCOMPUTER3
+");
+               if (ok.error != 0) {
+                       println(ok.errstr);
+                       assert(ok.error == 0);
+               }
+       }
+
+       println("Testing ldb.search for (&(cn=ldaptestcomputer3)(objectClass=user))");
+       var res = ldb.search("(&(cn=ldaptestcomputer3)(objectClass=user))");
+       if (res.error != 0 || res.msgs.length != 1) {
+               println("Could not find (&(cn=ldaptestcomputer3)(objectClass=user))");
+               assert(res.error == 0);
+               assert(res.msgs.length == 1);
+       }
+
+       assert(res.msgs[0].dn == ("CN=ldaptestcomputer3,CN=Computers," + base_dn));
+       assert(res.msgs[0].cn == "ldaptestcomputer3");
+       assert(res.msgs[0].name == "ldaptestcomputer3");
+       assert(res.msgs[0].objectClass[0] == "top");
+       assert(res.msgs[0].objectClass[1] == "person");
+       assert(res.msgs[0].objectClass[2] == "organizationalPerson");
+       assert(res.msgs[0].objectClass[3] == "user");
+       assert(res.msgs[0].objectClass[4] == "computer");
+       assert(res.msgs[0].objectGUID != undefined);
+       assert(res.msgs[0].whenCreated != undefined);
+       assert(res.msgs[0].objectCategory == ("CN=Computer,CN=Schema,CN=Configuration," + base_dn));
+       assert(res.msgs[0].primaryGroupID == 513);
+       assert(res.msgs[0].sAMAccountType == 805306368);
+       assert(res.msgs[0].userAccountControl == 546);
+
+           ldb.del(res.msgs[0].dn);
+
            println("Testing attribute or value exists behaviour");
            ok = ldb.modify("
 dn: cn=ldaptest2computer,cn=computers," + base_dn + "
@@ -374,6 +486,13 @@ sn: ldap user2
                assert(res.msgs.length == 2);
        }
 
+       var res = ldb.search("(&(anr=testy ldap)(objectClass=user))");
+       if (res.error != 0 || res.msgs.length != 2) {
+               println("Found only " + res.msgs.length + " for (&(anr=\"testy ldap\")(objectClass=user))");
+               assert(res.error == 0);
+               assert(res.msgs.length == 2);
+       }
+
 // Testing ldb.search for (&(anr=ldap)(objectClass=user))
        var res = ldb.search("(&(anr=ldap)(objectClass=user))");
        if (res.error != 0 || res.msgs.length != 4) {
@@ -547,6 +666,38 @@ member: cn=ldaptestuser3,cn=users," + base_dn + "
        assert(res.msgs[0].cn == "ldaptestUSER3");
        assert(res.msgs[0].name == "ldaptestUSER3");
 
+       println("Testing ldb.search for (&(&(cn=ldaptestuser3)(userAccountControl=*))(objectClass=user))");
+       var res = ldb.search("(&(&(cn=ldaptestuser3)(userAccountControl=*))(objectClass=user))");
+       if (res.error != 0 || res.msgs.length != 1) {
+               println("Could not find (&(cn=ldaptestuser3)(objectClass=user))");
+               assert(res.error == 0);
+               assert(res.msgs.length == 1);
+       }
+
+       assert(res.msgs[0].dn == ("CN=ldaptestUSER3,CN=Users," + base_dn));
+       assert(res.msgs[0].cn == "ldaptestUSER3");
+       assert(res.msgs[0].name == "ldaptestUSER3");
+
+       println("Testing ldb.search for (&(&(cn=ldaptestuser3)(userAccountControl=546))(objectClass=user))");
+       var res = ldb.search("(&(&(cn=ldaptestuser3)(userAccountControl=546))(objectClass=user))");
+       if (res.error != 0 || res.msgs.length != 1) {
+               println("Could not find (&(&(cn=ldaptestuser3)(userAccountControl=546))(objectClass=user))");
+               assert(res.error == 0);
+               assert(res.msgs.length == 1);
+       }
+
+       assert(res.msgs[0].dn == ("CN=ldaptestUSER3,CN=Users," + base_dn));
+       assert(res.msgs[0].cn == "ldaptestUSER3");
+       assert(res.msgs[0].name == "ldaptestUSER3");
+
+       println("Testing ldb.search for (&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))");
+       var res = ldb.search("(&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))");
+       if (res.error != 0 || res.msgs.length != 0) {
+               println("Should not find (&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))");
+               assert(res.error == 0);
+               assert(res.msgs.length == 0);
+       }
+
 // This is a Samba special, and does not exist in real AD
 //     println("Testing ldb.search for (dn=CN=ldaptestUSER3,CN=Users," + base_dn + ")");
 //     var res = ldb.search("(dn=CN=ldaptestUSER3,CN=Users," + base_dn + ")");
@@ -840,7 +991,7 @@ objectClass: user
        assert(res.msgs[0].whenCreated != undefined);
        assert(res.msgs[0].objectCategory == ("CN=Person,CN=Schema,CN=Configuration," + base_dn));
        assert(res.msgs[0].sAMAccountType == 805306368);
-//     assert(res[0].userAccountControl == 546);
+       assert(res.msgs[0].userAccountControl == 546);
        assert(res.msgs[0].memberOf[0] == ("CN=ldaptestgroup2,CN=Users," + base_dn));
        assert(res.msgs[0].memberOf.length == 1);
  
@@ -901,7 +1052,7 @@ objectClass: user
        println("Testing ldb.search for (&(cn=ldaptestcomputer)(objectClass=user))");
        var res = ldb.search("(&(cn=ldaptestcomputer)(objectClass=user))");
        if (res.error != 0 || res.msgs.length != 1) {
-               println("Could not find (&(cn=ldaptestuser)(objectClass=user))");
+               println("Could not find (&(cn=ldaptestcomputer)(objectClass=user))");
                assert(res.error == 0);
                assert(res.msgs.length == 1);
        }
@@ -916,12 +1067,9 @@ objectClass: user
        assert(res.msgs[0].objectClass[4] == "computer");
        assert(res.msgs[0].objectGUID != undefined);
        assert(res.msgs[0].whenCreated != undefined);
-       assert(res.msgs[0].objectCategory == ("CN=Computer,CN=Schema,CN=Configuration," + base_dn));
-       assert(res.msgs[0].primaryGroupID == 513);
-//     assert(res.msgs[0].sAMAccountType == 805306368);
-//     assert(res.msgs[0].userAccountControl == 546);
-       assert(res.msgs[0].memberOf[0] == ("CN=ldaptestgroup2,CN=Users," + base_dn));
-       assert(res.msgs[0].memberOf.length == 1);
+       assert(res.msgs[0].objectCategory == "cn=Computer,cn=Schema,cn=Configuration," + base_dn);
+       assert(res.msgs[0].sAMAccountType == 805306368);
+       assert(res.msgs[0].userAccountControl == 546);
 
        println("Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + base_dn + "))");
        var res2 = ldb.search("(&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + base_dn + "))");
@@ -1023,7 +1171,7 @@ objectClass: user
        assert(res.msgs[0].whenCreated != undefined);
        assert(res.msgs[0].objectCategory == "cn=Computer,cn=Schema,cn=Configuration," + base_dn);
        assert(res.msgs[0].sAMAccountType == 805306369);
-//     assert(res.msgs[0].userAccountControl == 4098);
+       assert(res.msgs[0].userAccountControl == 4096);
 
 
        ok = ldb.del(res.msgs[0].dn);