r12608: Remove some unused #include lines.
[kai/samba-autobuild/.git] / source4 / torture / auth / pac.c
index 8b0da02bf340a9e52f4e00341a113446c682e617..0ea31a24d10fc65a1e4a7e9d5331d8180459737b 100644 (file)
@@ -26,7 +26,6 @@
 #include "auth/auth.h"
 #include "auth/kerberos/kerberos.h"
 #include "librpc/gen_ndr/ndr_krb5pac.h"
-#include "librpc/gen_ndr/ndr_samr.h"
 
 static BOOL torture_pac_self_check(void) 
 {
@@ -50,6 +49,9 @@ static BOOL torture_pac_self_check(void)
        struct auth_serversupplied_info *server_info;
        struct auth_serversupplied_info *server_info_out;
 
+       krb5_principal client_principal;
+       time_t logon_time = time(NULL);
+
        ret = smb_krb5_init_context(mem_ctx, &smb_krb5_context);
 
        if (ret) {
@@ -65,7 +67,7 @@ static BOOL torture_pac_self_check(void)
                                 server_bytes, sizeof(server_bytes),
                                 &server_keyblock);
        if (ret) {
-               printf("Server Keyblock encoding failed: %s\n", 
+               printf("(self test) Server Keyblock encoding failed: %s\n", 
                       smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
                                                  ret, mem_ctx));
                
@@ -78,7 +80,7 @@ static BOOL torture_pac_self_check(void)
                                 krbtgt_bytes, sizeof(krbtgt_bytes),
                                 &krbtgt_keyblock);
        if (ret) {
-               printf("KRBTGT Keyblock encoding failed: %s\n", 
+               printf("(self test) KRBTGT Keyblock encoding failed: %s\n", 
                       smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
                                                  ret, mem_ctx));
        
@@ -99,17 +101,29 @@ static BOOL torture_pac_self_check(void)
                talloc_free(mem_ctx);
                return False;
        }
-       
+
+       ret = krb5_parse_name_norealm(smb_krb5_context->krb5_context, 
+                                     server_info->account_name, &client_principal);
+       if (ret) {
+               krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
+                                           &server_keyblock);
+               krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
+                                           &krbtgt_keyblock);
+               talloc_free(mem_ctx);
+               return False;
+       }
+
        /* OK, go ahead and make a PAC */
        ret = kerberos_create_pac(mem_ctx, server_info, 
                                  smb_krb5_context->krb5_context,  
                                  &krbtgt_keyblock,
                                  &server_keyblock,
-                                 time(NULL),
+                                 client_principal,
+                                 logon_time,
                                  &tmp_blob);
        
        if (ret) {
-               printf("PAC encoding failed: %s\n", 
+               printf("(self test) PAC encoding failed: %s\n", 
                       smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
                                                  ret, mem_ctx));
 
@@ -117,6 +131,8 @@ static BOOL torture_pac_self_check(void)
                                            &krbtgt_keyblock);
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                            &server_keyblock);
+               krb5_free_principal(smb_krb5_context->krb5_context, 
+                                   client_principal);
                talloc_free(mem_ctx);
                return False;
        }
@@ -128,14 +144,18 @@ static BOOL torture_pac_self_check(void)
                                        tmp_blob,
                                        smb_krb5_context->krb5_context,
                                        &krbtgt_keyblock,
-                                       &server_keyblock);
+                                       &server_keyblock,
+                                       client_principal, 
+                                       logon_time, NULL);
 
        if (!NT_STATUS_IS_OK(nt_status)) {
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                            &krbtgt_keyblock);
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                            &server_keyblock);
-               DEBUG(1, ("PAC decoding failed: %s\n", 
+               krb5_free_principal(smb_krb5_context->krb5_context, 
+                                   client_principal);
+               DEBUG(1, ("(self test) PAC decoding failed: %s\n", 
                          nt_errstr(nt_status)));
 
                talloc_free(mem_ctx);
@@ -147,14 +167,19 @@ static BOOL torture_pac_self_check(void)
                                            tmp_blob,
                                            smb_krb5_context->krb5_context,
                                            &krbtgt_keyblock,
-                                           &server_keyblock);
+                                           &server_keyblock,
+                                           client_principal, 
+                                           logon_time, 
+                                           NULL);
        
        if (!NT_STATUS_IS_OK(nt_status)) {
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                            &krbtgt_keyblock);
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                            &server_keyblock);
-               printf("PAC decoding (for logon info) failed: %s\n", 
+               krb5_free_principal(smb_krb5_context->krb5_context, 
+                                   client_principal);
+               printf("(self test) PAC decoding (for logon info) failed: %s\n", 
                       nt_errstr(nt_status));
                
                talloc_free(mem_ctx);
@@ -165,6 +190,8 @@ static BOOL torture_pac_self_check(void)
                                    &krbtgt_keyblock);
        krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                    &server_keyblock);
+       krb5_free_principal(smb_krb5_context->krb5_context, 
+                           client_principal);
 
        validation.sam3 = &logon_info->info3;
        nt_status = make_server_info_netlogon_validation(mem_ctx,
@@ -172,7 +199,7 @@ static BOOL torture_pac_self_check(void)
                                                         3, &validation,
                                                         &server_info_out); 
        if (!NT_STATUS_IS_OK(nt_status)) {
-               printf("PAC decoding (make server info) failed: %s\n", 
+               printf("(self test) PAC decoding (make server info) failed: %s\n", 
                       nt_errstr(nt_status));
                
                talloc_free(mem_ctx);
@@ -181,7 +208,7 @@ static BOOL torture_pac_self_check(void)
        
        if (!dom_sid_equal(server_info->account_sid, 
                           server_info_out->account_sid)) {
-               printf("PAC Decode resulted in *different* domain SID: %s != %s\n",
+               printf("(self test) PAC Decode resulted in *different* domain SID: %s != %s\n",
                       dom_sid_string(mem_ctx, server_info->account_sid), 
                       dom_sid_string(mem_ctx, server_info_out->account_sid));
                talloc_free(mem_ctx);
@@ -245,11 +272,10 @@ static BOOL torture_pac_saved_check(void)
        NTSTATUS nt_status;
        TALLOC_CTX *mem_ctx = talloc_named(NULL, 0, "PAC saved check");
        DATA_BLOB tmp_blob, validate_blob;
-       struct PAC_DATA *pac_data;
+       struct PAC_DATA *pac_data, pac_data2;
        struct PAC_LOGON_INFO *logon_info;
        union netr_Validation validation;
        const char *pac_file, *pac_kdc_key, *pac_member_key;
-
        struct auth_serversupplied_info *server_info_out;
 
        krb5_keyblock server_keyblock;
@@ -257,9 +283,13 @@ static BOOL torture_pac_saved_check(void)
        struct samr_Password *krbtgt_bytes, *krbsrv_bytes;
        
        krb5_error_code ret;
-
        struct smb_krb5_context *smb_krb5_context;
 
+       const char *principal_string;
+       krb5_principal client_principal;
+       const char *authtime_string;
+       time_t authtime;
+
        ret = smb_krb5_init_context(mem_ctx, &smb_krb5_context);
 
        if (ret) {
@@ -285,14 +315,14 @@ static BOOL torture_pac_saved_check(void)
         * samdump' tool. */
        krbtgt_bytes = smbpasswd_gethexpwd(mem_ctx, pac_kdc_key);
        if (!krbtgt_bytes) {
-               DEBUG(0, ("Could not interpret krbtgt key"));
+               DEBUG(0, ("(saved test) Could not interpret krbtgt key"));
                talloc_free(mem_ctx);
                return False;
        }
 
        krbsrv_bytes = smbpasswd_gethexpwd(mem_ctx, pac_member_key);
        if (!krbsrv_bytes) {
-               DEBUG(0, ("Could not interpret krbsrv key"));
+               DEBUG(0, ("(saved test) Could not interpret krbsrv key"));
                talloc_free(mem_ctx);
                return False;
        }
@@ -302,7 +332,7 @@ static BOOL torture_pac_saved_check(void)
                                 krbsrv_bytes->hash, sizeof(krbsrv_bytes->hash),
                                 &server_keyblock);
        if (ret) {
-               DEBUG(1, ("Server Keyblock encoding failed: %s\n", 
+               DEBUG(1, ("(saved test) Server Keyblock encoding failed: %s\n", 
                          smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
                                                     ret, mem_ctx)));
 
@@ -315,7 +345,7 @@ static BOOL torture_pac_saved_check(void)
                                 krbtgt_bytes->hash, sizeof(krbtgt_bytes->hash),
                                 &krbtgt_keyblock);
        if (ret) {
-               DEBUG(1, ("Server Keyblock encoding failed: %s\n", 
+               DEBUG(1, ("(saved test) Server Keyblock encoding failed: %s\n", 
                          smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
                                                     ret, mem_ctx)));
 
@@ -327,29 +357,58 @@ static BOOL torture_pac_saved_check(void)
 
        pac_file = lp_parm_string(-1,"torture","pac_file");
        if (pac_file) {
-               tmp_blob.data = file_load(pac_file, &tmp_blob.length, mem_ctx);
-               printf("Loaded pac of size %d from %s\n", tmp_blob.length, pac_file);
+               tmp_blob.data = (uint8_t *)file_load(pac_file, &tmp_blob.length, mem_ctx);
+               printf("(saved test) Loaded pac of size %ld from %s\n", (long)tmp_blob.length, pac_file);
        } else {
-               tmp_blob = data_blob(saved_pac, sizeof(saved_pac));
-               file_save("x.dat", tmp_blob.data, tmp_blob.length);
+               tmp_blob = data_blob_talloc(mem_ctx, saved_pac, sizeof(saved_pac));
        }
        
        dump_data(10,tmp_blob.data,tmp_blob.length);
 
+       principal_string = lp_parm_string(-1,"torture","pac_client_principal");
+       if (!principal_string) {
+               principal_string = "w2003final$@WIN2K3.THINKER.LOCAL";
+       }
+
+       authtime_string = lp_parm_string(-1,"torture","pac_authtime");
+       if (!authtime_string) {
+               authtime = 1120440609;
+       } else {
+               authtime = strtoull(authtime_string, NULL, 0);
+       }
+
+       ret = krb5_parse_name(smb_krb5_context->krb5_context, principal_string, 
+                             &client_principal);
+       if (ret) {
+               DEBUG(1, ("(saved test) parsing of client principal [%s] failed: %s\n", 
+                         principal_string, 
+                         smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
+
+               krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
+                                           &krbtgt_keyblock);
+               krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
+                                           &server_keyblock);
+               talloc_free(mem_ctx);
+               return False;
+       }
+
        /* Decode and verify the signaure on the PAC */
        nt_status = kerberos_decode_pac(mem_ctx, &pac_data,
                                        tmp_blob,
                                        smb_krb5_context->krb5_context,
                                        &krbtgt_keyblock,
-                                       &server_keyblock);
+                                       &server_keyblock, 
+                                       client_principal, authtime, NULL);
        if (!NT_STATUS_IS_OK(nt_status)) {
-               DEBUG(1, ("PAC decoding failed: %s\n", 
+               DEBUG(1, ("(saved test) PAC decoding failed: %s\n", 
                          nt_errstr(nt_status)));
 
                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);
+               
                talloc_free(mem_ctx);
                return False;
        }
@@ -359,14 +418,17 @@ static BOOL torture_pac_saved_check(void)
                                            tmp_blob,
                                            smb_krb5_context->krb5_context,
                                            &krbtgt_keyblock,
-                                           &server_keyblock);
+                                           &server_keyblock,
+                                           client_principal, authtime, NULL);
 
        if (!NT_STATUS_IS_OK(nt_status)) {
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                            &krbtgt_keyblock);
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                            &server_keyblock);
-               printf("PAC decoding (for logon info) failed: %s\n", 
+               krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
+       
+               printf("(saved test) PAC decoding (for logon info) failed: %s\n", 
                          nt_errstr(nt_status));
 
                talloc_free(mem_ctx);
@@ -383,8 +445,9 @@ static BOOL torture_pac_saved_check(void)
                                            &krbtgt_keyblock);
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                    &server_keyblock);
+               krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
 
-               printf("PAC decoding (make server info) failed: %s\n", 
+               printf("(saved test) PAC decoding (make server info) failed: %s\n", 
                       nt_errstr(nt_status));
                
                talloc_free(mem_ctx);
@@ -398,8 +461,9 @@ static BOOL torture_pac_saved_check(void)
                                            &krbtgt_keyblock);
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                            &server_keyblock);
+               krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
 
-               printf("PAC Decode resulted in *different* domain SID: %s != %s\n",
+               printf("(saved test) PAC Decode resulted in *different* domain SID: %s != %s\n",
                       "S-1-5-21-3048156945-3961193616-3706469200-1005", 
                       dom_sid_string(mem_ctx, server_info_out->account_sid));
                talloc_free(mem_ctx);
@@ -418,8 +482,9 @@ static BOOL torture_pac_saved_check(void)
                                            &krbtgt_keyblock);
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                            &server_keyblock);
+               krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
 
-               DEBUG(0, ("PAC push failed\n"));
+               DEBUG(0, ("(saved test) PAC push failed\n"));
                talloc_free(mem_ctx);
                return False;
        }
@@ -435,8 +500,9 @@ static BOOL torture_pac_saved_check(void)
                                            &krbtgt_keyblock);
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                            &server_keyblock);
+               krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
 
-               DEBUG(0, ("PAC push failed: original buffer length[%u] != created buffer length[%u]\n",
+               DEBUG(0, ("(saved test) PAC push failed: original buffer length[%u] != created buffer length[%u]\n",
                                (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
                talloc_free(mem_ctx);
                return False;
@@ -447,9 +513,149 @@ static BOOL torture_pac_saved_check(void)
                                            &krbtgt_keyblock);
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                            &server_keyblock);
+               krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
 
-               DEBUG(0, ("PAC push failed: length[%u] matches, but data does not\n",
+               DEBUG(0, ("(saved test) PAC push failed: length[%u] matches, but data does not\n",
                          (unsigned)tmp_blob.length));
+               DEBUG(0, ("tmp_data:\n"));
+               dump_data(0, tmp_blob.data, tmp_blob.length);
+               DEBUG(0, ("validate_blob:\n"));
+               dump_data(0, validate_blob.data, validate_blob.length);
+
+               talloc_free(mem_ctx);
+               return False;
+       }
+
+       ret = kerberos_create_pac(mem_ctx, 
+                                 server_info_out,
+                                 smb_krb5_context->krb5_context,
+                                 &krbtgt_keyblock,
+                                 &server_keyblock,
+                                 client_principal, authtime,
+                                 &validate_blob);
+
+       if (ret != 0) {
+               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);
+
+               DEBUG(0, ("(saved test) regnerated PAC create failed\n"));
+               talloc_free(mem_ctx);
+               return False;
+       }
+
+       dump_data(10,validate_blob.data,validate_blob.length);
+
+       /* compare both the length and the data bytes after a
+        * pull/push cycle.  This ensures we use the exact same
+        * pointer, padding etc algorithms as win2k3.
+        */
+       if (tmp_blob.length != validate_blob.length) {
+               nt_status = ndr_pull_struct_blob(&validate_blob, mem_ctx, &pac_data2,
+                                             (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
+               if (!NT_STATUS_IS_OK(nt_status)) {
+                       DEBUG(0,("can't parse the PAC\n"));
+                       return False;
+               }
+               
+               NDR_PRINT_DEBUG(PAC_DATA, pac_data);
+
+               NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
+
+               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);
+
+               DEBUG(0, ("(saved test) PAC regenerate failed: original buffer length[%u] != created buffer length[%u]\n",
+                               (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
+               talloc_free(mem_ctx);
+               return False;
+       }
+
+       if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
+               nt_status = ndr_pull_struct_blob(&validate_blob, mem_ctx, &pac_data2,
+                                             (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
+               if (!NT_STATUS_IS_OK(nt_status)) {
+                       DEBUG(0,("can't parse the PAC\n"));
+                       return False;
+               }
+               
+               NDR_PRINT_DEBUG(PAC_DATA, pac_data);
+
+               NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
+
+               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);
+
+               DEBUG(0, ("(saved test) PAC regenerate failed: length[%u] matches, but data does not\n",
+                         (unsigned)tmp_blob.length));
+               DEBUG(0, ("tmp_data:\n"));
+               dump_data(0, tmp_blob.data, tmp_blob.length);
+               DEBUG(0, ("validate_blob:\n"));
+               dump_data(0, validate_blob.data, validate_blob.length);
+
+               talloc_free(mem_ctx);
+               return False;
+       }
+
+       /* Break the auth time, to ensure we check this vital detail (not setting this caused all the pain in the first place... */
+       nt_status = kerberos_decode_pac(mem_ctx, &pac_data,
+                                       tmp_blob,
+                                       smb_krb5_context->krb5_context,
+                                       &krbtgt_keyblock,
+                                       &server_keyblock,
+                                       client_principal, 
+                                       authtime + 1, NULL);
+       if (NT_STATUS_IS_OK(nt_status)) {
+               DEBUG(1, ("(saved test) PAC decoding DID NOT fail on broken auth time (time + 1)\n"));
+
+               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);
+               talloc_free(mem_ctx);
+               return False;
+       }
+
+       /* Break the client principal */
+       krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
+
+       ret = krb5_parse_name(smb_krb5_context->krb5_context,
+                            "not the right principal", &client_principal);
+       if (ret) {
+               DEBUG(1, ("(saved test) parsing of bogus client principal failed: %s\n", 
+                         smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
+
+               krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
+                                           &krbtgt_keyblock);
+               krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
+                                           &server_keyblock);
+               talloc_free(mem_ctx);
+               return False;
+       }
+
+       nt_status = kerberos_decode_pac(mem_ctx, &pac_data,
+                                       tmp_blob,
+                                       smb_krb5_context->krb5_context,
+                                       &krbtgt_keyblock,
+                                       &server_keyblock,
+                                       client_principal, 
+                                       authtime, NULL);
+       if (NT_STATUS_IS_OK(nt_status)) {
+               DEBUG(1, ("(saved test) PAC decoding DID NOT fail on modified principal\n"));
+
+               krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
+                                           &krbtgt_keyblock);
+               krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
+                                           &server_keyblock);
                talloc_free(mem_ctx);
                return False;
        }
@@ -461,9 +667,11 @@ static BOOL torture_pac_saved_check(void)
                                        tmp_blob,
                                        smb_krb5_context->krb5_context,
                                        &krbtgt_keyblock,
-                                       &server_keyblock);
+                                       &server_keyblock,
+                                       client_principal, 
+                                       authtime, NULL);
        if (NT_STATUS_IS_OK(nt_status)) {
-               DEBUG(1, ("PAC decoding DID NOT fail on broken checksum\n"));
+               DEBUG(1, ("(saved test) PAC decoding DID NOT fail on broken checksum\n"));
 
                krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
                                            &krbtgt_keyblock);