Merge branch 'master' of ssh://git.samba.org/data/git/samba into crypto
[samba.git] / source4 / torture / rpc / lsa.c
index 98cbf12e6879958f43255dbf9547f125107c93a5..69bf33352b843e3aae74be3bb72fdfe7f980a38b 100644 (file)
 #include "torture/torture.h"
 #include "librpc/gen_ndr/ndr_lsa_c.h"
 #include "librpc/gen_ndr/netlogon.h"
+#include "librpc/gen_ndr/ndr_drsblobs.h"
 #include "lib/events/events.h"
 #include "libcli/security/security.h"
 #include "libcli/auth/libcli_auth.h"
 #include "torture/rpc/rpc.h"
 #include "param/param.h"
-
+#include "../lib/crypto/crypto.h"
 #define TEST_MACHINENAME "lsatestmach"
 
 static void init_lsa_String(struct lsa_String *name, const char *s)
@@ -780,6 +781,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)
 {
@@ -802,7 +804,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;
        }
 
@@ -865,7 +885,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);
@@ -1162,7 +1182,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;
                                }
@@ -1177,7 +1197,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);
@@ -1241,8 +1263,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;
                                }
@@ -1310,7 +1334,7 @@ static bool test_CreateSecret(struct dcerpc_pipe *p,
                                }
                                
                                if (*r8.out.new_mtime != *r8.out.old_mtime) {
-                                       printf("Returned secret %s should have had same mtime for both secrets: %s != %s\n", 
+                                       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));
@@ -1860,6 +1884,9 @@ static bool test_EnumTrustDom(struct dcerpc_pipe *p,
                return false;
        }
                
+       /* Start from the bottom again */
+       resume_handle = 0;
+
        do {
                r.in.handle = handle;
                r.in.resume_handle = &resume_handle;
@@ -1978,7 +2005,7 @@ static bool test_CreateTrustedDomain(struct dcerpc_pipe *p,
                trustinfo.sid = domsid[i];
                init_lsa_String((struct lsa_String *)&trustinfo.name, trust_name);
 
-               r.in.handle = handle;
+               r.in.policy_handle = handle;
                r.in.info = &trustinfo;
                r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
                r.out.trustdom_handle = &trustdom_handle[i];
@@ -1994,7 +2021,139 @@ static bool test_CreateTrustedDomain(struct dcerpc_pipe *p,
                } else {
                
                        q.in.trustdom_handle = &trustdom_handle[i];
-                       q.in.level = LSA_TRUSTED_DOMAIN_INFO_NAME;
+                       q.in.level = LSA_TRUSTED_DOMAIN_INFO_INFO_EX;
+                       status = dcerpc_lsa_QueryTrustedDomainInfo(p, mem_ctx, &q);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               printf("QueryTrustedDomainInfo level 1 failed - %s\n", nt_errstr(status));
+                               ret = false;
+                       } else if (!q.out.info) {
+                               ret = false;
+                       } else {
+                               if (strcmp(q.out.info->info_ex.netbios_name.string, trustinfo.name.string) != 0) {
+                                       printf("QueryTrustedDomainInfo returned inconsistant short name: %s != %s\n",
+                                              q.out.info->info_ex.netbios_name.string, trustinfo.name.string);
+                                       ret = false;
+                               }
+                               if (q.out.info->info_ex.trust_type != LSA_TRUST_TYPE_DOWNLEVEL) {
+                                       printf("QueryTrustedDomainInfo of %s returned incorrect trust type %d != %d\n", 
+                                              trust_name, q.out.info->info_ex.trust_type, LSA_TRUST_TYPE_DOWNLEVEL);
+                                       ret = false;
+                               }
+                               if (q.out.info->info_ex.trust_attributes != 0) {
+                                       printf("QueryTrustedDomainInfo of %s returned incorrect trust attributes %d != %d\n", 
+                                              trust_name, q.out.info->info_ex.trust_attributes, 0);
+                                       ret = false;
+                               }
+                               if (q.out.info->info_ex.trust_direction != LSA_TRUST_DIRECTION_OUTBOUND) {
+                                       printf("QueryTrustedDomainInfo of %s returned incorrect trust direction %d != %d\n", 
+                                              trust_name, q.out.info->info_ex.trust_direction, LSA_TRUST_DIRECTION_OUTBOUND);
+                                       ret = false;
+                               }
+                       }
+               }
+       }
+
+       /* now that we have some domains to look over, we can test the enum calls */
+       if (!test_EnumTrustDom(p, mem_ctx, handle)) {
+               ret = false;
+       }
+       
+       for (i=0; i<12; i++) {
+               if (!test_DeleteTrustedDomainBySid(p, mem_ctx, handle, domsid[i])) {
+                       ret = false;
+               }
+       }
+
+       return ret;
+}
+
+static bool test_CreateTrustedDomainEx2(struct dcerpc_pipe *p, 
+                                       struct torture_context *tctx, 
+                                       TALLOC_CTX *mem_ctx, 
+                                       struct policy_handle *handle)
+{
+       NTSTATUS status;
+       bool ret = true;
+       struct lsa_CreateTrustedDomainEx2 r;
+       struct lsa_TrustDomainInfoInfoEx trustinfo;
+       struct lsa_TrustDomainInfoAuthInfoInternal authinfo;
+       struct trustAuthInAndOutBlob auth_struct;
+       DATA_BLOB auth_blob;
+       struct dom_sid *domsid[12];
+       struct policy_handle trustdom_handle[12];
+       struct lsa_QueryTrustedDomainInfo q;
+       DATA_BLOB session_key;
+       enum ndr_err_code ndr_err;
+       int i;
+
+       printf("Testing CreateTrustedDomainEx2 for 12 domains\n");
+
+       status = dcerpc_fetch_session_key(p, &session_key);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("dcerpc_fetch_session_key failed - %s\n", nt_errstr(status));
+               return false;
+       }
+               
+       for (i=0; i< 12; i++) {
+               char *trust_name = talloc_asprintf(mem_ctx, "torturedom%02d", i);
+               char *trust_name_dns = talloc_asprintf(mem_ctx, "torturedom%02d.samba.example.com", i);
+               char *trust_sid = talloc_asprintf(mem_ctx, "S-1-5-21-97398-379795-100%02d", i);
+               
+               domsid[i] = dom_sid_parse_talloc(mem_ctx, trust_sid);
+
+               trustinfo.sid = domsid[i];
+               trustinfo.netbios_name.string = trust_name;
+               trustinfo.domain_name.string = trust_name_dns;
+
+               /* Create inbound, some outbound, and some
+                * bi-directional trusts in a repeating pattern based
+                * on i */
+
+               /* 1 == inbound, 2 == outbound, 3 == both */
+               trustinfo.trust_direction = (i % 3) + 1;
+
+               /* Try different trust types too */
+
+               /* 1 == downleven (NT4), 2 == uplevel (ADS), 3 == MIT (kerberos but not AD) */
+               trustinfo.trust_type = (((i / 3) + 1) % 3) + 1;
+
+               trustinfo.trust_attributes = LSA_TRUST_ATTRIBUTE_USES_RC4_ENCRYPTION;
+
+               generate_random_buffer(auth_struct.confounder, sizeof(auth_struct.confounder));
+
+               auth_struct.outgoing.count = 0;
+               auth_struct.incoming.count = 0;
+
+               ndr_err = ndr_push_struct_blob(&auth_blob, mem_ctx, lp_iconv_convenience(tctx->lp_ctx), &auth_struct,
+                                              (ndr_push_flags_fn_t)ndr_push_trustAuthInAndOutBlob);
+               if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+                       printf("ndr_push_struct_blob of trustAuthInAndOutBlob structure failed");
+                       ret = false;
+               }
+
+               arcfour_crypt_blob(auth_blob.data, auth_blob.length, &session_key);
+
+               authinfo.auth_blob.size = auth_blob.length;
+               authinfo.auth_blob.data = auth_blob.data;
+
+               r.in.policy_handle = handle;
+               r.in.info = &trustinfo;
+               r.in.auth_info = &authinfo;
+               r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+               r.out.trustdom_handle = &trustdom_handle[i];
+               
+               status = dcerpc_lsa_CreateTrustedDomainEx2(p, mem_ctx, &r);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
+                       test_DeleteTrustedDomain(p, mem_ctx, handle, trustinfo.netbios_name);
+                       status = dcerpc_lsa_CreateTrustedDomainEx2(p, mem_ctx, &r);
+               }
+               if (!NT_STATUS_IS_OK(status)) {
+                       printf("CreateTrustedDomainEx failed2 - %s\n", nt_errstr(status));
+                       ret = false;
+               } else {
+               
+                       q.in.trustdom_handle = &trustdom_handle[i];
+                       q.in.level = LSA_TRUSTED_DOMAIN_INFO_INFO_EX;
                        status = dcerpc_lsa_QueryTrustedDomainInfo(p, mem_ctx, &q);
                        if (!NT_STATUS_IS_OK(status)) {
                                printf("QueryTrustedDomainInfo level 1 failed - %s\n", nt_errstr(status));
@@ -2002,9 +2161,24 @@ static bool test_CreateTrustedDomain(struct dcerpc_pipe *p,
                        } else if (!q.out.info) {
                                ret = false;
                        } else {
-                               if (strcmp(q.out.info->name.netbios_name.string, trustinfo.name.string) != 0) {
+                               if (strcmp(q.out.info->info_ex.netbios_name.string, trustinfo.netbios_name.string) != 0) {
                                        printf("QueryTrustedDomainInfo returned inconsistant short name: %s != %s\n",
-                                              q.out.info->name.netbios_name.string, trustinfo.name.string);
+                                              q.out.info->info_ex.netbios_name.string, trustinfo.netbios_name.string);
+                                       ret = false;
+                               }
+                               if (q.out.info->info_ex.trust_type != trustinfo.trust_type) {
+                                       printf("QueryTrustedDomainInfo of %s returned incorrect trust type %d != %d\n", 
+                                              trust_name, q.out.info->info_ex.trust_type, trustinfo.trust_type);
+                                       ret = false;
+                               }
+                               if (q.out.info->info_ex.trust_attributes != LSA_TRUST_ATTRIBUTE_USES_RC4_ENCRYPTION) {
+                                       printf("QueryTrustedDomainInfo of %s returned incorrect trust attributes %d != %d\n", 
+                                              trust_name, q.out.info->info_ex.trust_attributes, LSA_TRUST_ATTRIBUTE_USES_RC4_ENCRYPTION);
+                                       ret = false;
+                               }
+                               if (q.out.info->info_ex.trust_direction != trustinfo.trust_direction) {
+                                       printf("QueryTrustedDomainInfo of %s returned incorrect trust direction %d != %d\n", 
+                                              trust_name, q.out.info->info_ex.trust_direction, trustinfo.trust_direction);
                                        ret = false;
                                }
                        }
@@ -2033,10 +2207,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");
 
@@ -2048,7 +2218,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;
@@ -2312,7 +2485,11 @@ bool torture_rpc_lsa(struct torture_context *tctx)
                if (!test_CreateTrustedDomain(p, tctx, handle)) {
                        ret = false;
                }
-               
+
+               if (!test_CreateTrustedDomainEx2(p, tctx, tctx, handle)) {
+                       ret = false;
+               }
+
                if (!test_EnumAccounts(p, tctx, handle)) {
                        ret = false;
                }