Heimdal provides Kerberos PAC parsing routines. Use them.
[kai/samba.git] / source4 / torture / auth / pac.c
index 68bbd3483a20627091f5931f331e90112e58d866..42901f1eff155d9fdaf48920c92d6810f316d885 100644 (file)
@@ -28,6 +28,7 @@
 #include "samba3/samba3.h"
 #include "libcli/security/security.h"
 #include "torture/torture.h"
+#include "auth/session_proto.h"
 
 static bool torture_pac_self_check(struct torture_context *tctx)
 {
@@ -138,7 +139,7 @@ static bool torture_pac_self_check(struct torture_context *tctx)
 
        dump_data(10,tmp_blob.data,tmp_blob.length);
 
-       /* Now check that we can read it back */
+       /* Now check that we can read it back (using full decode and validate) */
        nt_status = kerberos_decode_pac(mem_ctx, 
                                        lp_iconv_convenience(tctx->lp_ctx),
                                        &pac_data,
@@ -162,7 +163,31 @@ static bool torture_pac_self_check(struct torture_context *tctx)
                                                   nt_errstr(nt_status)));
        }
 
-       /* Now check that we can read it back */
+       /* Now check we can read it back (using Heimdal's pac parsing) */
+       nt_status = kerberos_pac_blob_to_server_info(mem_ctx, 
+                                                    lp_iconv_convenience(tctx->lp_ctx),
+                                                    tmp_blob, 
+                                                    smb_krb5_context->krb5_context,
+                                                    &server_info_out);
+
+       if (!dom_sid_equal(server_info->account_sid, 
+                          server_info_out->account_sid)) {
+               krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
+                                           &krbtgt_keyblock);
+               krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
+                                           &server_keyblock);
+               krb5_free_principal(smb_krb5_context->krb5_context, 
+                                   client_principal);
+
+               torture_fail(tctx,  
+                            talloc_asprintf(tctx, 
+                                            "(self test) PAC Decode resulted in *different* domain SID: %s != %s",
+                                            dom_sid_string(mem_ctx, server_info->account_sid), 
+                                            dom_sid_string(mem_ctx, server_info_out->account_sid)));
+       }
+       talloc_free(server_info_out);
+
+       /* Now check that we can read it back (yet again) */
        nt_status = kerberos_pac_logon_info(mem_ctx, 
                                            lp_iconv_convenience(tctx->lp_ctx),
                                            &logon_info,
@@ -195,6 +220,7 @@ static bool torture_pac_self_check(struct torture_context *tctx)
        krb5_free_principal(smb_krb5_context->krb5_context, 
                            client_principal);
 
+       /* And make a server info from the samba-parsed PAC */
        validation.sam3 = &logon_info->info3;
        nt_status = make_server_info_netlogon_validation(mem_ctx,
                                                         "",
@@ -278,7 +304,7 @@ static bool torture_pac_saved_check(struct torture_context *tctx)
        struct auth_serversupplied_info *server_info_out;
 
        krb5_keyblock server_keyblock;
-       krb5_keyblock krbtgt_keyblock;
+       krb5_keyblock krbtgt_keyblock, *krbtgt_keyblock_p;
        struct samr_Password *krbtgt_bytes, *krbsrv_bytes;
        
        krb5_error_code ret;
@@ -308,9 +334,13 @@ static bool torture_pac_saved_check(struct torture_context *tctx)
        /* The krbtgt key in use when the above PAC was generated.
         * This is an arcfour-hmac-md5 key, extracted with our 'net
         * samdump' tool. */
-       krbtgt_bytes = smbpasswd_gethexpwd(mem_ctx, pac_kdc_key);
-       if (!krbtgt_bytes) {
-               torture_fail(tctx, "(saved test) Could not interpret krbtgt key");
+       if (*pac_kdc_key == 0) {
+               krbtgt_bytes = NULL;
+       } else {
+               krbtgt_bytes = smbpasswd_gethexpwd(mem_ctx, pac_kdc_key);
+               if (!krbtgt_bytes) {
+                       torture_fail(tctx, "(saved test) Could not interpret krbtgt key");
+               }
        }
 
        krbsrv_bytes = smbpasswd_gethexpwd(mem_ctx, pac_member_key);
@@ -328,18 +358,23 @@ static bool torture_pac_saved_check(struct torture_context *tctx)
                                       smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
                                                                  ret, mem_ctx)));
 
-       ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
-                                ENCTYPE_ARCFOUR_HMAC,
-                                krbtgt_bytes->hash, sizeof(krbtgt_bytes->hash),
-                                &krbtgt_keyblock);
-       if (ret) {
-               krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
-                                           &server_keyblock);
-               torture_fail(tctx, 
-                            talloc_asprintf(tctx, 
-                                            "(saved test) Server Keyblock encoding failed: %s", 
-                                            smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
-                                                                       ret, mem_ctx)));
+       if (krbtgt_bytes) {
+               ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
+                                        ENCTYPE_ARCFOUR_HMAC,
+                                        krbtgt_bytes->hash, sizeof(krbtgt_bytes->hash),
+                                        &krbtgt_keyblock);
+               if (ret) {
+                       krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
+                                                   &server_keyblock);
+                       torture_fail(tctx, 
+                                    talloc_asprintf(tctx, 
+                                                    "(saved test) Server Keyblock encoding failed: %s", 
+                                                    smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
+                                                                               ret, mem_ctx)));
+               }
+               krbtgt_keyblock_p = &krbtgt_keyblock;
+       } else {
+               krbtgt_keyblock_p = NULL;
        }
 
        pac_file = torture_setting_string(tctx, "pac_file", NULL);
@@ -362,7 +397,7 @@ static bool torture_pac_saved_check(struct torture_context *tctx)
                              &client_principal);
        if (ret) {
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
-                                           &krbtgt_keyblock);
+                                           krbtgt_keyblock_p);
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                            &server_keyblock);
                torture_fail(tctx,  
@@ -378,12 +413,12 @@ static bool torture_pac_saved_check(struct torture_context *tctx)
                                        &pac_data,
                                        tmp_blob,
                                        smb_krb5_context->krb5_context,
-                                       &krbtgt_keyblock,
+                                       krbtgt_keyblock_p,
                                        &server_keyblock, 
                                        client_principal, authtime, NULL);
        if (!NT_STATUS_IS_OK(nt_status)) {
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
-                                           &krbtgt_keyblock);
+                                           krbtgt_keyblock_p);
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                            &server_keyblock);
                krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
@@ -393,19 +428,57 @@ static bool torture_pac_saved_check(struct torture_context *tctx)
                                                   nt_errstr(nt_status)));
        }
 
-       /* Parse the PAC again, for the logon info this time */
+       /* Now check we can read it back (using Heimdal's pac parsing) */
+       nt_status = kerberos_pac_blob_to_server_info(mem_ctx, 
+                                                    lp_iconv_convenience(tctx->lp_ctx),
+                                                    tmp_blob, 
+                                                    smb_krb5_context->krb5_context,
+                                                    &server_info_out);
+
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
+                                           krbtgt_keyblock_p);
+               krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
+                                           &server_keyblock);
+               krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
+               
+               torture_fail(tctx, talloc_asprintf(tctx, 
+                                                  "(saved test) Heimdal PAC decoding failed: %s", 
+                                                  nt_errstr(nt_status)));
+       }
+
+       if (!pac_file &&
+           !dom_sid_equal(dom_sid_parse_talloc(mem_ctx, 
+                                               "S-1-5-21-3048156945-3961193616-3706469200-1005"), 
+                          server_info_out->account_sid)) {
+               krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
+                                           krbtgt_keyblock_p);
+               krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
+                                           &server_keyblock);
+               krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
+
+               torture_fail(tctx,  
+                            talloc_asprintf(tctx, 
+                                            "(saved test) Heimdal PAC Decode resulted in *different* domain SID: %s != %s",
+                                            "S-1-5-21-3048156945-3961193616-3706469200-1005", 
+                                            dom_sid_string(mem_ctx, server_info_out->account_sid)));
+       }
+
+       talloc_free(server_info_out);
+
+       /* Parse the PAC again, for the logon info this time (using Samba4's parsing) */
        nt_status = kerberos_pac_logon_info(mem_ctx, 
                                            lp_iconv_convenience(tctx->lp_ctx),
                                            &logon_info,
                                            tmp_blob,
                                            smb_krb5_context->krb5_context,
-                                           &krbtgt_keyblock,
+                                           krbtgt_keyblock_p,
                                            &server_keyblock,
                                            client_principal, authtime, NULL);
 
        if (!NT_STATUS_IS_OK(nt_status)) {
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
-                                           &krbtgt_keyblock);
+                                           krbtgt_keyblock_p);
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                            &server_keyblock);
                krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
@@ -423,7 +496,7 @@ static bool torture_pac_saved_check(struct torture_context *tctx)
                                                         &server_info_out); 
        if (!NT_STATUS_IS_OK(nt_status)) {
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
-                                           &krbtgt_keyblock);
+                                           krbtgt_keyblock_p);
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                            &server_keyblock);
                krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
@@ -439,7 +512,7 @@ static bool torture_pac_saved_check(struct torture_context *tctx)
                                                "S-1-5-21-3048156945-3961193616-3706469200-1005"), 
                           server_info_out->account_sid)) {
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
-                                           &krbtgt_keyblock);
+                                           krbtgt_keyblock_p);
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                            &server_keyblock);
                krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
@@ -451,17 +524,25 @@ static bool torture_pac_saved_check(struct torture_context *tctx)
                                             dom_sid_string(mem_ctx, server_info_out->account_sid)));
        }
 
+       if (krbtgt_bytes == NULL) {
+               torture_comment(tctx, "skipping PAC encoding tests as non kdc key\n");
+               krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
+                                           &server_keyblock);
+               krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
+               return true;
+       }
+
        ret = kerberos_encode_pac(mem_ctx, 
                                  lp_iconv_convenience(tctx->lp_ctx),
                                  pac_data,
                                  smb_krb5_context->krb5_context,
-                                 &krbtgt_keyblock,
+                                 krbtgt_keyblock_p,
                                  &server_keyblock,
                                  &validate_blob);
 
        if (ret != 0) {
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
-                                           &krbtgt_keyblock);
+                                           krbtgt_keyblock_p);
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                            &server_keyblock);
                krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
@@ -477,7 +558,7 @@ static bool torture_pac_saved_check(struct torture_context *tctx)
         */
        if (tmp_blob.length != validate_blob.length) {
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
-                                           &krbtgt_keyblock);
+                                           krbtgt_keyblock_p);
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                            &server_keyblock);
                krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
@@ -490,7 +571,7 @@ static bool torture_pac_saved_check(struct torture_context *tctx)
 
        if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
-                                           &krbtgt_keyblock);
+                                           krbtgt_keyblock_p);
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                            &server_keyblock);
                krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
@@ -507,14 +588,14 @@ static bool torture_pac_saved_check(struct torture_context *tctx)
                                  lp_iconv_convenience(tctx->lp_ctx),
                                  server_info_out,
                                  smb_krb5_context->krb5_context,
-                                 &krbtgt_keyblock,
+                                 krbtgt_keyblock_p,
                                  &server_keyblock,
                                  client_principal, authtime,
                                  &validate_blob);
 
        if (ret != 0) {
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
-                                           &krbtgt_keyblock);
+                                           krbtgt_keyblock_p);
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                            &server_keyblock);
                krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
@@ -540,7 +621,7 @@ static bool torture_pac_saved_check(struct torture_context *tctx)
                NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
 
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
-                                           &krbtgt_keyblock);
+                                           krbtgt_keyblock_p);
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                            &server_keyblock);
                krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
@@ -562,7 +643,7 @@ static bool torture_pac_saved_check(struct torture_context *tctx)
                NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
 
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
-                                           &krbtgt_keyblock);
+                                           krbtgt_keyblock_p);
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                            &server_keyblock);
                krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
@@ -582,14 +663,14 @@ static bool torture_pac_saved_check(struct torture_context *tctx)
                                        &pac_data,
                                        tmp_blob,
                                        smb_krb5_context->krb5_context,
-                                       &krbtgt_keyblock,
+                                       krbtgt_keyblock_p,
                                        &server_keyblock,
                                        client_principal, 
                                        authtime + 1, NULL);
        if (NT_STATUS_IS_OK(nt_status)) {
 
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
-                                           &krbtgt_keyblock);
+                                           krbtgt_keyblock_p);
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                            &server_keyblock);
                krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
@@ -607,7 +688,7 @@ static bool torture_pac_saved_check(struct torture_context *tctx)
        if (ret) {
 
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
-                                           &krbtgt_keyblock);
+                                           krbtgt_keyblock_p);
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                            &server_keyblock);
                torture_fail(tctx, talloc_asprintf(tctx, 
@@ -620,13 +701,13 @@ static bool torture_pac_saved_check(struct torture_context *tctx)
                                        &pac_data,
                                        tmp_blob,
                                        smb_krb5_context->krb5_context,
-                                       &krbtgt_keyblock,
+                                       krbtgt_keyblock_p,
                                        &server_keyblock,
                                        client_principal, 
                                        authtime, NULL);
        if (NT_STATUS_IS_OK(nt_status)) {
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
-                                           &krbtgt_keyblock);
+                                           krbtgt_keyblock_p);
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                            &server_keyblock);
                torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on modified principal");
@@ -640,34 +721,32 @@ static bool torture_pac_saved_check(struct torture_context *tctx)
                                        &pac_data,
                                        tmp_blob,
                                        smb_krb5_context->krb5_context,
-                                       &krbtgt_keyblock,
+                                       krbtgt_keyblock_p,
                                        &server_keyblock,
                                        client_principal, 
                                        authtime, NULL);
        if (NT_STATUS_IS_OK(nt_status)) {
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
-                                           &krbtgt_keyblock);
+                                           krbtgt_keyblock_p);
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                            &server_keyblock);
                torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on broken checksum");
        }
 
        krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
-                                   &krbtgt_keyblock);
+                                   krbtgt_keyblock_p);
        krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                    &server_keyblock);
        return true;
 }
 
-_PUBLIC_ struct torture_suite *torture_pac(TALLOC_CTX *mem_ctx)
+struct torture_suite *torture_pac(TALLOC_CTX *mem_ctx)
 {
        struct torture_suite *suite = torture_suite_create(mem_ctx, "PAC");
 
        torture_suite_add_simple_test(suite, "self check", 
                                      torture_pac_self_check);
-
        torture_suite_add_simple_test(suite, "saved check",
                                      torture_pac_saved_check);
-
        return suite;
 }