CVE-2022-2031 s4:kpasswd: Require an initial ticket
authorJoseph Sutton <josephsutton@catalyst.net.nz>
Wed, 18 May 2022 04:52:41 +0000 (16:52 +1200)
committerJule Anger <janger@samba.org>
Sun, 24 Jul 2022 09:55:51 +0000 (11:55 +0200)
Ensure that for password changes the client uses an AS-REQ to get the
ticket to kpasswd, and not a TGS-REQ.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049

Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Reviewed-by: Andreas Schneider <asn@samba.org>
[jsutton@samba.org Removed MIT KDC 1.20-specific knownfails]

selftest/knownfail_heimdal_kdc
selftest/knownfail_mit_kdc
source4/kdc/kpasswd-service-heimdal.c
source4/kdc/kpasswd-service-mit.c
source4/kdc/wscript_build

index cb4f190d75f3b9977210b09a6a98f0c1d9bc80b1..ab7230060ab52578f53490e3f757d78984f2a477 100644 (file)
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize.ad_dc
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_non_initial.ad_dc
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc
index 41a793ae082cf639feaa872f068c8cee67941baa..0389672e5d9aafe301ec0e16845ae3ac4cac0a6b 100644 (file)
@@ -546,7 +546,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
 #
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_non_initial.ad_dc
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc
index c804852c3a76e32e6b3be350eac283bdda541b14..1a6c2b60d03f9feb71675c7a085b7848b2e0f6c2 100644 (file)
@@ -24,6 +24,7 @@
 #include "param/param.h"
 #include "auth/auth.h"
 #include "auth/gensec/gensec.h"
+#include "gensec_krb5_helpers.h"
 #include "kdc/kdc-server.h"
 #include "kdc/kpasswd_glue.h"
 #include "kdc/kpasswd-service.h"
@@ -31,6 +32,7 @@
 
 static krb5_error_code kpasswd_change_password(struct kdc_server *kdc,
                                               TALLOC_CTX *mem_ctx,
+                                              const struct gensec_security *gensec_security,
                                               struct auth_session_info *session_info,
                                               DATA_BLOB *password,
                                               DATA_BLOB *kpasswd_reply,
@@ -42,6 +44,17 @@ static krb5_error_code kpasswd_change_password(struct kdc_server *kdc,
        const char *reject_string = NULL;
        struct samr_DomInfo1 *dominfo;
        bool ok;
+       int ret;
+
+       /*
+        * We're doing a password change (rather than a password set), so check
+        * that we were given an initial ticket.
+        */
+       ret = gensec_krb5_initial_ticket(gensec_security);
+       if (ret != 1) {
+               *error_string = "Expected an initial ticket";
+               return KRB5_KPASSWD_INITIAL_FLAG_NEEDED;
+       }
 
        status = samdb_kpasswd_change_password(mem_ctx,
                                               kdc->task->lp_ctx,
@@ -81,6 +94,7 @@ static krb5_error_code kpasswd_change_password(struct kdc_server *kdc,
 
 static krb5_error_code kpasswd_set_password(struct kdc_server *kdc,
                                            TALLOC_CTX *mem_ctx,
+                                           const struct gensec_security *gensec_security,
                                            struct auth_session_info *session_info,
                                            DATA_BLOB *decoded_data,
                                            DATA_BLOB *kpasswd_reply,
@@ -173,6 +187,7 @@ static krb5_error_code kpasswd_set_password(struct kdc_server *kdc,
                free_ChangePasswdDataMS(&chpw);
                return kpasswd_change_password(kdc,
                                               mem_ctx,
+                                              gensec_security,
                                               session_info,
                                               &password,
                                               kpasswd_reply,
@@ -272,6 +287,7 @@ krb5_error_code kpasswd_handle_request(struct kdc_server *kdc,
 
                return kpasswd_change_password(kdc,
                                               mem_ctx,
+                                              gensec_security,
                                               session_info,
                                               &password,
                                               kpasswd_reply,
@@ -280,6 +296,7 @@ krb5_error_code kpasswd_handle_request(struct kdc_server *kdc,
        case KRB5_KPASSWD_VERS_SETPW: {
                return kpasswd_set_password(kdc,
                                            mem_ctx,
+                                           gensec_security,
                                            session_info,
                                            decoded_data,
                                            kpasswd_reply,
index 9c4d280166978ce0581fa91d06a5f590f0748b87..de4c6f3f622af3b523f5fef60f8a52b443a10b1a 100644 (file)
@@ -24,6 +24,7 @@
 #include "param/param.h"
 #include "auth/auth.h"
 #include "auth/gensec/gensec.h"
+#include "gensec_krb5_helpers.h"
 #include "kdc/kdc-server.h"
 #include "kdc/kpasswd_glue.h"
 #include "kdc/kpasswd-service.h"
@@ -84,6 +85,7 @@ out:
 
 static krb5_error_code kpasswd_change_password(struct kdc_server *kdc,
                                               TALLOC_CTX *mem_ctx,
+                                              const struct gensec_security *gensec_security,
                                               struct auth_session_info *session_info,
                                               DATA_BLOB *password,
                                               DATA_BLOB *kpasswd_reply,
@@ -95,6 +97,17 @@ static krb5_error_code kpasswd_change_password(struct kdc_server *kdc,
        const char *reject_string = NULL;
        struct samr_DomInfo1 *dominfo;
        bool ok;
+       int ret;
+
+       /*
+        * We're doing a password change (rather than a password set), so check
+        * that we were given an initial ticket.
+        */
+       ret = gensec_krb5_initial_ticket(gensec_security);
+       if (ret != 1) {
+               *error_string = "Expected an initial ticket";
+               return KRB5_KPASSWD_INITIAL_FLAG_NEEDED;
+       }
 
        status = samdb_kpasswd_change_password(mem_ctx,
                                               kdc->task->lp_ctx,
@@ -134,6 +147,7 @@ static krb5_error_code kpasswd_change_password(struct kdc_server *kdc,
 
 static krb5_error_code kpasswd_set_password(struct kdc_server *kdc,
                                            TALLOC_CTX *mem_ctx,
+                                           const struct gensec_security *gensec_security,
                                            struct auth_session_info *session_info,
                                            DATA_BLOB *decoded_data,
                                            DATA_BLOB *kpasswd_reply,
@@ -250,6 +264,7 @@ static krb5_error_code kpasswd_set_password(struct kdc_server *kdc,
 
                return kpasswd_change_password(kdc,
                                               mem_ctx,
+                                              gensec_security,
                                               session_info,
                                               &password,
                                               kpasswd_reply,
@@ -350,6 +365,7 @@ krb5_error_code kpasswd_handle_request(struct kdc_server *kdc,
 
                return kpasswd_change_password(kdc,
                                               mem_ctx,
+                                              gensec_security,
                                               session_info,
                                               &password,
                                               kpasswd_reply,
@@ -358,6 +374,7 @@ krb5_error_code kpasswd_handle_request(struct kdc_server *kdc,
        case RFC3244_VERSION: {
                return kpasswd_set_password(kdc,
                                            mem_ctx,
+                                           gensec_security,
                                            session_info,
                                            decoded_data,
                                            kpasswd_reply,
index 0edca94e75fdb16e21ad5057271ea659a45bbd9f..13ba3947cf6226e6d4a0acab03399ca950d187cf 100644 (file)
@@ -88,6 +88,7 @@ bld.SAMBA_SUBSYSTEM('KPASSWD-SERVICE',
                          krb5samba
                          samba_server_gensec
                          KPASSWD_GLUE
+                         gensec_krb5_helpers
                          ''')
 
 bld.SAMBA_SUBSYSTEM('KDC-GLUE',