s4:torture: Implement lsa_OpenPolicy3 tests
authorAndreas Schneider <asn@samba.org>
Thu, 13 Jul 2023 19:19:37 +0000 (21:19 +0200)
committerAndreas Schneider <asn@cryptomilk.org>
Tue, 21 Nov 2023 11:16:37 +0000 (11:16 +0000)
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
source4/torture/rpc/lsa.c

index 221b8ab8cc6e21a24a5001bf6226133ee5a5cfb9..c2190e55da3792890f095fdb7c4b0f13638bd09c 100644 (file)
@@ -279,6 +279,174 @@ static bool test_OpenPolicy2_fail(struct dcerpc_binding_handle *b,
        return false;
 }
 
+bool test_lsa_OpenPolicy3_ex(struct dcerpc_binding_handle *b,
+                            struct torture_context *tctx,
+                            struct policy_handle **handle,
+                            NTSTATUS expected_status,
+                            NTSTATUS expected_status2)
+{
+       struct lsa_QosInfo qos = {
+               .impersonation_level = 2,
+               .context_mode = 1,
+       };
+       struct lsa_ObjectAttribute attr = {
+               .len = 0,
+               .sec_qos = &qos,
+       };
+       struct lsa_revision_info1 in_rinfo1 = {
+               .revision = 1,
+               .supported_features = 0,
+       };
+       union lsa_revision_info in_rinfo = {
+               .info1 = in_rinfo1,
+       };
+       struct lsa_revision_info1 out_rinfo1 = {
+               .revision = 0,
+       };
+       union lsa_revision_info out_rinfo = {
+               .info1 = out_rinfo1,
+       };
+       uint32_t out_version = 0;
+       struct lsa_OpenPolicy3 r = {
+               .in.system_name = "\\",
+               .in.attr = &attr,
+               .in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED,
+               .in.in_version = 1,
+               .in.in_revision_info = &in_rinfo,
+               .out.out_version = &out_version,
+               .out.out_revision_info = &out_rinfo,
+       };
+       NTSTATUS status;
+
+       torture_comment(tctx, "\nTesting OpenPolicy3\n");
+
+       *handle = talloc(tctx, struct policy_handle);
+       torture_assert(tctx,
+                      *handle != NULL,
+                      "talloc(tctx, struct policy_handle)");
+       r.out.handle = *handle;
+
+       status = dcerpc_lsa_OpenPolicy3_r(b, tctx, &r);
+
+       /* Allow two possible failure status codes */
+       if (!NT_STATUS_EQUAL(status, expected_status2)) {
+               torture_assert_ntstatus_equal(tctx,
+                                             status,
+                                             expected_status,
+                                             "OpenPolicy3 failed");
+       }
+       if (!NT_STATUS_IS_OK(expected_status) ||
+           !NT_STATUS_IS_OK(expected_status2)) {
+               return true;
+       }
+
+       torture_assert_ntstatus_ok(tctx, r.out.result, "OpenPolicy3 failed");
+       torture_assert_int_equal(tctx, out_version, 1, "Invalid out_version");
+       torture_assert_int_equal(tctx,
+                                out_rinfo1.revision,
+                                1,
+                                "Invalid revision");
+#if 0 /* TODO: Enable as soon as it is supported */
+       torture_assert_int_equal(tctx,
+                                out_rinfo1.supported_features,
+                                LSA_FEATURE_TDO_AUTH_INFO_AES_CIPHER,
+                                "Invalid supported feature set");
+#endif
+
+       return true;
+}
+
+bool test_lsa_OpenPolicy3(struct dcerpc_binding_handle *b,
+                         struct torture_context *tctx,
+                         struct policy_handle **handle)
+{
+       return test_lsa_OpenPolicy3_ex(b,
+                                      tctx,
+                                      handle,
+                                      NT_STATUS_OK,
+                                      NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE);
+}
+
+static bool test_OpenPolicy3_fail(struct dcerpc_binding_handle *b,
+                                 struct torture_context *tctx)
+{
+       struct policy_handle handle = {
+               .handle_type = 0,
+       };
+       struct lsa_QosInfo qos = {
+               .impersonation_level = 2,
+               .context_mode = 1,
+       };
+       struct lsa_ObjectAttribute attr = {
+               .len = 0,
+               .sec_qos = &qos,
+       };
+       struct lsa_revision_info1 in_rinfo1 = {
+               .revision = 0,
+               .supported_features = 0,
+       };
+       union lsa_revision_info in_rinfo = {
+               .info1 = in_rinfo1,
+       };
+       struct lsa_revision_info1 out_rinfo1 = {
+               .revision = 0,
+       };
+       union lsa_revision_info out_rinfo = {
+               .info1 = out_rinfo1,
+       };
+       uint32_t out_version = 0;
+       struct lsa_OpenPolicy3 r = {
+               .in.system_name = "\\",
+               .in.attr = &attr,
+               .in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED,
+               .in.in_version = 1,
+               .in.in_revision_info = &in_rinfo,
+               .out.out_version = &out_version,
+               .out.out_revision_info = &out_rinfo,
+               .out.handle = &handle,
+       };
+       NTSTATUS status;
+
+       torture_comment(tctx, "\nTesting OpenPolicy3_fail\n");
+
+       status = dcerpc_lsa_OpenPolicy3_r(b, tctx, &r);
+       if (!NT_STATUS_IS_OK(status)) {
+               if (NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_DISCONNECTED) ||
+                   NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
+                   NT_STATUS_EQUAL(status,
+                                   NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
+                       torture_comment(tctx,
+                                       "OpenPolicy3 correctly returned with "
+                                       "status: %s\n",
+                                       nt_errstr(status));
+                       return true;
+               }
+
+               torture_assert_ntstatus_equal(tctx,
+                                             status,
+                                             NT_STATUS_ACCESS_DENIED,
+                                             "OpenPolicy3 return value should "
+                                             "be ACCESS_DENIED or CONNECTION_DISCONNECTED");
+               return true;
+       }
+
+       if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED) ||
+           NT_STATUS_EQUAL(r.out.result,
+                           NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED)) {
+               torture_comment(tctx,
+                               "OpenPolicy3 correctly returned with "
+                               "result: %s\n",
+                               nt_errstr(r.out.result));
+               return true;
+       }
+
+       torture_fail(tctx,
+                    "OpenPolicy3 return value should be "
+                    "ACCESS_DENIED or RPC_PROTSEQ_NOT_SUPPORTED");
+
+       return false;
+}
+
 static bool test_LookupNames(struct dcerpc_binding_handle *b,
                             struct torture_context *tctx,
                             struct policy_handle *handle,
@@ -5152,6 +5320,10 @@ bool torture_rpc_lsa(struct torture_context *tctx)
                        ret = false;
                }
 
+               if (!test_OpenPolicy3_fail(b, tctx)) {
+                       ret = false;
+               }
+
                if (!test_many_LookupSids(p, tctx, handle, LSA_LOOKUP_NAMES_ALL)) {
                        ret = false;
                }
@@ -5167,6 +5339,10 @@ bool torture_rpc_lsa(struct torture_context *tctx)
                ret = false;
        }
 
+       if (!test_lsa_OpenPolicy3(b, tctx, &handle)) {
+               ret = false;
+       }
+
        if (handle) {
                join = torture_join_domain(tctx, TEST_MACHINENAME, ACB_WSTRUST, &machine_creds);
                if (!join) {