]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
CVE-2021-20251: s4:auth: fix use after free in authsam_logon_success_accounting()
authorStefan Metzmacher <metze@samba.org>
Mon, 7 Nov 2022 16:21:44 +0000 (17:21 +0100)
committerStefan Metzmacher <metze@samba.org>
Thu, 24 Nov 2022 11:01:37 +0000 (11:01 +0000)
This fixes a use after free problem introduced by
commit 7b8e32efc336fb728e0c7e3dd6fbe2ed54122124,
which has msg = current; which means the lifetime
of the 'msg' memory is no longer in the scope of th
caller.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14611
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15253

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
source4/auth/ntlm/auth_sam.c
source4/auth/ntlm/auth_winbind.c
source4/auth/sam.c
source4/auth/tests/sam.c
source4/kdc/hdb-samba4.c
source4/kdc/mit_samba.c

index 80a3c066158517c02e3af2a479f3e4dfe82fd066..3e2cf16b9e4e6517563a491a0d7e67bade7de1c1 100644 (file)
@@ -787,6 +787,7 @@ static NTSTATUS authsam_authenticate(struct auth4_context *auth_context,
        nt_status = authsam_logon_success_accounting(auth_context->sam_ctx,
                                                     msg, domain_dn,
                                                     interactive,
+                                                    tmp_ctx,
                                                     &send_to_sam);
 
        if (send_to_sam != NULL) {
index 6381f866667e6737599209706196bd4376e43deb..719d877a1703a8b8f055b442dfab2a99049461b6 100644 (file)
@@ -256,7 +256,7 @@ static void winbind_check_password_done(struct tevent_req *subreq)
                                ctx->auth_ctx->sam_ctx, msg,
                                domain_dn,
                                user_info->flags & USER_INFO_INTERACTIVE_LOGON,
-                               NULL);
+                               NULL, NULL);
                        if (tevent_req_nterror(req, status)) {
                                return;
                        }
index 219ee10d5bd3f3262701e5d3acb22274e82cc2ee..f2e5ced6caf84e7b5d055bba3476f217e88ffdb5 100644 (file)
@@ -1396,6 +1396,7 @@ NTSTATUS authsam_logon_success_accounting(struct ldb_context *sam_ctx,
                                          const struct ldb_message *msg,
                                          struct ldb_dn *domain_dn,
                                          bool interactive_or_kerberos,
+                                         TALLOC_CTX *send_to_sam_mem_ctx,
                                          struct netr_SendToSamBase **send_to_sam)
 {
        int ret;
@@ -1612,7 +1613,13 @@ get_transaction:
                if (dbBadPwdCount != 0 && send_to_sam != NULL) {
                        struct netr_SendToSamBase *base_msg;
                        struct GUID guid = samdb_result_guid(msg, "objectGUID");
-                       base_msg = talloc_zero(msg, struct netr_SendToSamBase);
+
+                       base_msg = talloc_zero(send_to_sam_mem_ctx,
+                                              struct netr_SendToSamBase);
+                       if (base_msg == NULL) {
+                               status = NT_STATUS_NO_MEMORY;
+                               goto error;
+                       }
 
                        base_msg->message_type = SendToSamResetBadPasswordCount;
                        base_msg->message_size = 16;
index b39408c3699a15901b4739be40eb6b2c4b3d9480..e1e2c69b86302713527a7ec43dd861affee0e251 100644 (file)
@@ -1446,7 +1446,7 @@ static void test_success_accounting_start_txn_failed(void **state) {
        ldb_transaction_start_ret = LDB_ERR_OPERATIONS_ERROR;
 
        status = authsam_logon_success_accounting(
-               ldb, msg, domain_dn, true, NULL);
+               ldb, msg, domain_dn, true, NULL, NULL);
        assert_true(NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR));
 
        /*
@@ -1502,7 +1502,7 @@ static void test_success_accounting_reread_failed(void **state) {
        will_return(__wrap_dsdb_search_dn, LDB_ERR_NO_SUCH_OBJECT);
 
        status = authsam_logon_success_accounting(
-               ldb, msg, domain_dn, true, NULL);
+               ldb, msg, domain_dn, true, NULL, NULL);
        assert_true(NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR));
        assert_true(transaction_cancelled);
 
@@ -1561,7 +1561,7 @@ static void test_success_accounting_ldb_msg_new_failed(void **state) {
        ldb_msg_new_fail = true;
 
        status = authsam_logon_success_accounting(
-               ldb, msg, domain_dn, true, NULL);
+               ldb, msg, domain_dn, true, NULL, NULL);
        assert_true(NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY));
        assert_true(transaction_cancelled);
 
@@ -1612,7 +1612,7 @@ static void test_success_accounting_samdb_rodc_failed(void **state) {
        samdb_rodc_ret = LDB_ERR_OPERATIONS_ERROR;
 
        status = authsam_logon_success_accounting(
-               ldb, msg, domain_dn, true, NULL);
+               ldb, msg, domain_dn, true, NULL, NULL);
        assert_true(NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR));
        assert_false(in_transaction);
        assert_false(transaction_cancelled);
@@ -1675,7 +1675,7 @@ static void test_success_accounting_update_lastlogon_failed(void **state) {
        will_return(__wrap_samdb_msg_add_int64, LDB_ERR_OPERATIONS_ERROR);
 
        status = authsam_logon_success_accounting(
-               ldb, msg, domain_dn, true, NULL);
+               ldb, msg, domain_dn, true, NULL, NULL);
        assert_true(NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY));
        assert_true(transaction_cancelled);
 
@@ -1737,7 +1737,7 @@ static void test_success_accounting_build_mod_req_failed(void **state) {
        will_return(__wrap_samdb_msg_add_int64, LDB_SUCCESS);
 
        status = authsam_logon_success_accounting(
-               ldb, msg, domain_dn, true, NULL);
+               ldb, msg, domain_dn, true, NULL, NULL);
        assert_true(NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR));
        assert_true(transaction_cancelled);
 
@@ -1800,7 +1800,7 @@ static void test_success_accounting_add_control_failed(void **state) {
        will_return(__wrap_samdb_msg_add_int64, LDB_SUCCESS);
 
        status = authsam_logon_success_accounting(
-               ldb, msg, domain_dn, true, NULL);
+               ldb, msg, domain_dn, true, NULL, NULL);
        assert_true(NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR));
        assert_true(transaction_cancelled);
 
@@ -1863,7 +1863,7 @@ static void test_success_accounting_ldb_request_failed(void **state) {
        will_return(__wrap_samdb_msg_add_int64, LDB_SUCCESS);
 
        status = authsam_logon_success_accounting(
-               ldb, msg, domain_dn, true, NULL);
+               ldb, msg, domain_dn, true, NULL, NULL);
        assert_true(NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR));
        assert_true(transaction_cancelled);
 
@@ -1926,7 +1926,7 @@ static void test_success_accounting_ldb_wait_failed(void **state) {
        will_return(__wrap_samdb_msg_add_int64, LDB_SUCCESS);
 
        status = authsam_logon_success_accounting(
-               ldb, msg, domain_dn, true, NULL);
+               ldb, msg, domain_dn, true, NULL, NULL);
        assert_true(NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR));
        assert_true(transaction_cancelled);
 
@@ -1989,7 +1989,7 @@ static void test_success_accounting_commit_failed(void **state) {
        will_return(__wrap_samdb_msg_add_int64, LDB_SUCCESS);
 
        status = authsam_logon_success_accounting(
-               ldb, msg, domain_dn, true, NULL);
+               ldb, msg, domain_dn, true, NULL, NULL);
        assert_true(NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR));
        assert_true(in_transaction);
        assert_false(transaction_cancelled);
@@ -2055,7 +2055,7 @@ static void test_success_accounting_rollback_failed(void **state) {
        will_return(__wrap_samdb_msg_add_int64, LDB_SUCCESS);
 
        status = authsam_logon_success_accounting(
-               ldb, msg, domain_dn, true, NULL);
+               ldb, msg, domain_dn, true, NULL, NULL);
        assert_true(NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR));
        assert_true(in_transaction);
        assert_false(transaction_cancelled);
@@ -2124,7 +2124,7 @@ static void test_success_accounting_spurious_bad_pwd_indicator(void **state) {
        ldb_build_mod_req_res = talloc_zero(ctx, struct ldb_request);
 
        status = authsam_logon_success_accounting(
-               ldb, msg, domain_dn, true, NULL);
+               ldb, msg, domain_dn, true, NULL, NULL);
        assert_true(NT_STATUS_EQUAL(status, NT_STATUS_OK));
        assert_false(in_transaction);
        assert_false(transaction_cancelled);
index 699ef9a577cc8fd4db8d38033624f7f488031a35..527fa6b627b2c71005c33631b1e438c6f4e956b9 100644 (file)
@@ -653,7 +653,7 @@ static krb5_error_code hdb_samba4_audit(krb5_context context,
                         * in the PAC here or re-calculate it.
                         */
                        status = authsam_logon_success_accounting(kdc_db_ctx->samdb, p->msg,
-                                                                 domain_dn, true, &send_to_sam);
+                                                                 domain_dn, true, frame, &send_to_sam);
                        if (NT_STATUS_EQUAL(status, NT_STATUS_ACCOUNT_LOCKED_OUT)) {
                                final_ret = KRB5KDC_ERR_CLIENT_REVOKED;
                                r->error_code = final_ret;
index cd4a107154bfad0cfd86f64896f51ef6dad846f5..54d308d35e8d6c5c1c4f8d4dd0dc17a28e319d81 100644 (file)
@@ -1035,7 +1035,7 @@ out:
 
 void mit_samba_zero_bad_password_count(krb5_db_entry *db_entry)
 {
-       struct netr_SendToSamBase *send_to_sam = NULL;
+       /* struct netr_SendToSamBase *send_to_sam = NULL; */
        struct samba_kdc_entry *p =
                talloc_get_type_abort(db_entry->e_data, struct samba_kdc_entry);
        struct ldb_dn *domain_dn;
@@ -1046,7 +1046,7 @@ void mit_samba_zero_bad_password_count(krb5_db_entry *db_entry)
                                         p->msg,
                                         domain_dn,
                                         true,
-                                        &send_to_sam);
+                                        NULL, NULL);
        /* TODO: RODC support */
 }