LCOV - code coverage report
Current view: top level - source4/torture/auth - pac.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 153 276 55.4 %
Date: 2024-05-31 13:13:24 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Validate the krb5 pac generation routines
       5             :    
       6             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             :    
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include "includes.h"
      24             : #include "lib/util/util_file.h"
      25             : #include "system/kerberos.h"
      26             : #include "auth/auth.h"
      27             : #include "auth/kerberos/kerberos.h"
      28             : #include "samba3/samba3.h"
      29             : #include "libcli/security/security.h"
      30             : #include "torture/torture.h"
      31             : #include "auth/auth_sam_reply.h"
      32             : #include "param/param.h"
      33             : #include "librpc/gen_ndr/ndr_krb5pac.h"
      34             : #include "torture/auth/proto.h"
      35             : #include "auth/kerberos/pac_utils.h"
      36             : 
      37           1 : static bool torture_pac_self_check(struct torture_context *tctx)
      38             : {
      39           1 :         NTSTATUS nt_status;
      40           1 :         DATA_BLOB tmp_blob;
      41           1 :         struct PAC_DATA *pac_data;
      42           1 :         struct PAC_LOGON_INFO *logon_info;
      43           1 :         union netr_Validation validation;
      44             : 
      45             :         /* Generate a nice, arbitrary keyblock */
      46           1 :         uint8_t server_bytes[16];
      47           1 :         uint8_t krbtgt_bytes[16];
      48           1 :         krb5_keyblock server_keyblock;
      49           1 :         krb5_keyblock krbtgt_keyblock;
      50             :         
      51           1 :         krb5_error_code ret;
      52             : 
      53           1 :         struct smb_krb5_context *smb_krb5_context;
      54             : 
      55           1 :         struct auth_user_info_dc *user_info_dc;
      56           1 :         struct auth_user_info_dc *user_info_dc_out;
      57             : 
      58           1 :         krb5_principal client_principal;
      59           1 :         time_t logon_time = time(NULL);
      60             : 
      61           1 :         TALLOC_CTX *mem_ctx = tctx;
      62             : 
      63           1 :         torture_assert(tctx, 0 == smb_krb5_init_context(mem_ctx, 
      64             :                                                         tctx->lp_ctx,
      65             :                                                         &smb_krb5_context), 
      66             :                        "smb_krb5_init_context");
      67             : 
      68           1 :         generate_random_buffer(server_bytes, 16);
      69           1 :         generate_random_buffer(krbtgt_bytes, 16);
      70             : 
      71           1 :         ret = smb_krb5_keyblock_init_contents(smb_krb5_context->krb5_context,
      72             :                                  ENCTYPE_ARCFOUR_HMAC,
      73             :                                  server_bytes, sizeof(server_bytes),
      74             :                                  &server_keyblock);
      75           1 :         torture_assert(tctx, !ret, talloc_asprintf(tctx, 
      76             :                                                    "(self test) Server Keyblock encoding failed: %s", 
      77             :                                                    smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
      78             :                                                                               ret, mem_ctx)));
      79             : 
      80           1 :         ret = smb_krb5_keyblock_init_contents(smb_krb5_context->krb5_context,
      81             :                                  ENCTYPE_ARCFOUR_HMAC,
      82             :                                  krbtgt_bytes, sizeof(krbtgt_bytes),
      83             :                                  &krbtgt_keyblock);
      84           1 :         if (ret) {
      85           0 :                 char *err = smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
      86             :                                                        ret, mem_ctx);
      87             :         
      88           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
      89             :                                             &server_keyblock);
      90             : 
      91           0 :                 torture_fail(tctx, talloc_asprintf(tctx, 
      92             :                                                    "(self test) KRBTGT Keyblock encoding failed: %s", err));
      93             :         }
      94             : 
      95             :         /* We need an input, and this one requires no underlying database */
      96           1 :         nt_status = auth_anonymous_user_info_dc(mem_ctx, lpcfg_netbios_name(tctx->lp_ctx), &user_info_dc);
      97             : 
      98           1 :         if (!NT_STATUS_IS_OK(nt_status)) {
      99           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     100             :                                             &server_keyblock);
     101           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     102             :                                             &krbtgt_keyblock);
     103           0 :                 torture_fail(tctx, "auth_anonymous_user_info_dc");
     104             :         }
     105             : 
     106           2 :         ret = krb5_parse_name_flags(smb_krb5_context->krb5_context, 
     107           1 :                                     user_info_dc->info->account_name,
     108             :                                     KRB5_PRINCIPAL_PARSE_NO_REALM, 
     109             :                                     &client_principal);
     110           1 :         if (ret) {
     111           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     112             :                                             &server_keyblock);
     113           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     114             :                                             &krbtgt_keyblock);
     115           0 :                 torture_fail(tctx, "krb5_parse_name_flags(norealm)");
     116             :         }
     117             : 
     118             :         /* OK, go ahead and make a PAC */
     119           2 :         ret = kerberos_create_pac(mem_ctx, 
     120             :                                   user_info_dc,
     121           1 :                                   smb_krb5_context->krb5_context,  
     122             :                                   &krbtgt_keyblock,
     123             :                                   &server_keyblock,
     124             :                                   client_principal,
     125             :                                   logon_time,
     126             :                                   &tmp_blob);
     127             :         
     128           1 :         if (ret) {
     129           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     130             :                                             &krbtgt_keyblock);
     131           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     132             :                                             &server_keyblock);
     133           0 :                 krb5_free_principal(smb_krb5_context->krb5_context, 
     134             :                                     client_principal);
     135             : 
     136           0 :                 torture_fail(tctx, talloc_asprintf(tctx,
     137             :                                                    "(self test) PAC encoding failed: %s", 
     138             :                                                    smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
     139             :                                                                               ret, mem_ctx)));
     140             :         }
     141             : 
     142           1 :         dump_data(10,tmp_blob.data,tmp_blob.length);
     143             : 
     144             :         /* Now check that we can read it back (using full decode and validate) */
     145           2 :         nt_status = kerberos_decode_pac(mem_ctx, 
     146             :                                         tmp_blob,
     147           1 :                                         smb_krb5_context->krb5_context,
     148             :                                         &krbtgt_keyblock,
     149             :                                         &server_keyblock,
     150             :                                         client_principal, 
     151             :                                         logon_time,
     152             :                                         &pac_data);
     153             : 
     154           1 :         if (!NT_STATUS_IS_OK(nt_status)) {
     155           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     156             :                                             &krbtgt_keyblock);
     157           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     158             :                                             &server_keyblock);
     159           0 :                 krb5_free_principal(smb_krb5_context->krb5_context, 
     160             :                                     client_principal);
     161             : 
     162           0 :                 torture_fail(tctx, talloc_asprintf(tctx,
     163             :                                                    "(self test) PAC decoding failed: %s", 
     164             :                                                    nt_errstr(nt_status)));
     165             :         }
     166             : 
     167             :         /* Now check we can read it back (using Heimdal's pac parsing) */
     168           2 :         nt_status = kerberos_pac_blob_to_user_info_dc(mem_ctx,
     169             :                                                      tmp_blob, 
     170           1 :                                                      smb_krb5_context->krb5_context,
     171             :                                                       &user_info_dc_out, NULL, NULL);
     172             : 
     173             :         /* The user's SID is the first element in the list */
     174           1 :         if (!dom_sid_equal(&user_info_dc->sids[PRIMARY_USER_SID_INDEX].sid,
     175           1 :                            &user_info_dc_out->sids[PRIMARY_USER_SID_INDEX].sid)) {
     176           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     177             :                                             &krbtgt_keyblock);
     178           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     179             :                                             &server_keyblock);
     180           0 :                 krb5_free_principal(smb_krb5_context->krb5_context, 
     181             :                                     client_principal);
     182             : 
     183           0 :                 torture_fail(tctx,  
     184             :                              talloc_asprintf(tctx, 
     185             :                                              "(self test) PAC Decode resulted in *different* domain SID: %s != %s",
     186             :                                              dom_sid_string(mem_ctx, &user_info_dc->sids[PRIMARY_USER_SID_INDEX].sid),
     187             :                                              dom_sid_string(mem_ctx, &user_info_dc_out->sids[PRIMARY_USER_SID_INDEX].sid)));
     188             :         }
     189           1 :         talloc_free(user_info_dc_out);
     190             : 
     191             :         /* Now check that we can read it back (yet again) */
     192           2 :         nt_status = kerberos_pac_logon_info(mem_ctx, 
     193             :                                             tmp_blob,
     194           1 :                                             smb_krb5_context->krb5_context,
     195             :                                             &krbtgt_keyblock,
     196             :                                             &server_keyblock,
     197             :                                             client_principal, 
     198             :                                             logon_time, 
     199             :                                             &logon_info);
     200             :         
     201           1 :         if (!NT_STATUS_IS_OK(nt_status)) {
     202           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     203             :                                             &krbtgt_keyblock);
     204           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     205             :                                             &server_keyblock);
     206           0 :                 krb5_free_principal(smb_krb5_context->krb5_context, 
     207             :                                     client_principal);
     208             :                 
     209           0 :                 torture_fail(tctx,  
     210             :                              talloc_asprintf(tctx, 
     211             :                                              "(self test) PAC decoding (for logon info) failed: %s", 
     212             :                                              nt_errstr(nt_status)));
     213             :         }
     214             :         
     215           1 :         krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     216             :                                     &krbtgt_keyblock);
     217           1 :         krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     218             :                                     &server_keyblock);
     219           1 :         krb5_free_principal(smb_krb5_context->krb5_context, 
     220             :                             client_principal);
     221             : 
     222             :         /* And make a server info from the samba-parsed PAC */
     223           1 :         validation.sam3 = &logon_info->info3;
     224           1 :         nt_status = make_user_info_dc_netlogon_validation(mem_ctx,
     225             :                                                          "",
     226             :                                                          3, &validation,
     227             :                                                           true, /* This user was authenticated */
     228             :                                                  &user_info_dc_out);
     229           1 :         if (!NT_STATUS_IS_OK(nt_status)) {
     230           0 :                 torture_fail(tctx, 
     231             :                              talloc_asprintf(tctx, 
     232             :                                              "(self test) PAC decoding (make server info) failed: %s", 
     233             :                                              nt_errstr(nt_status)));
     234             :         }
     235             :         
     236           1 :         if (!dom_sid_equal(&user_info_dc->sids[PRIMARY_USER_SID_INDEX].sid,
     237           1 :                            &user_info_dc_out->sids[PRIMARY_USER_SID_INDEX].sid)) {
     238           0 :                 torture_fail(tctx,  
     239             :                              talloc_asprintf(tctx, 
     240             :                                              "(self test) PAC Decode resulted in *different* domain SID: %s != %s",
     241             :                                              dom_sid_string(mem_ctx, &user_info_dc->sids[PRIMARY_USER_SID_INDEX].sid),
     242             :                                              dom_sid_string(mem_ctx, &user_info_dc_out->sids[PRIMARY_USER_SID_INDEX].sid)));
     243             :         }
     244           0 :         return true;
     245             : }
     246             : 
     247             : 
     248             : /* This is the PAC generated on my test network, by my test Win2k3 server.
     249             :    -- abartlet 2005-07-04
     250             : */
     251             : 
     252             : static const uint8_t saved_pac[] = {
     253             :         0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00, 
     254             :         0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
     255             :         0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
     256             :         0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
     257             :         0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x08, 0x00, 0xcc, 0xcc, 0xcc, 0xcc,
     258             :         0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x30, 0xdf, 0xa6, 0xcb, 
     259             :         0x4f, 0x7d, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 
     260             :         0xff, 0xff, 0xff, 0x7f, 0xc0, 0x3c, 0x4e, 0x59, 0x62, 0x73, 0xc5, 0x01, 0xc0, 0x3c, 0x4e, 0x59,
     261             :         0x62, 0x73, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x16, 0x00, 0x16, 0x00,
     262             :         0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
     263             :         0x0c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 
     264             :         0x14, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x02, 0x00, 0x65, 0x00, 0x00, 0x00, 
     265             :         0xed, 0x03, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x02, 0x00,
     266             :         0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     267             :         0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x16, 0x00, 0x20, 0x00, 0x02, 0x00, 0x16, 0x00, 0x18, 0x00,
     268             :         0x24, 0x00, 0x02, 0x00, 0x28, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     269             :         0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     270             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     271             :         0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     272             :         0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
     273             :         0x57, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00,
     274             :         0x41, 0x00, 0x4c, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     275             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     276             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     277             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     278             :         0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
     279             :         0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x57, 0x00, 0x32, 0x00,
     280             :         0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x41, 0x00, 0x4c, 0x00,
     281             :         0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x57, 0x00, 0x49, 0x00,
     282             :         0x4e, 0x00, 0x32, 0x00, 0x4b, 0x00, 0x33, 0x00, 0x54, 0x00, 0x48, 0x00, 0x49, 0x00, 0x4e, 0x00,
     283             :         0x4b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
     284             :         0x15, 0x00, 0x00, 0x00, 0x11, 0x2f, 0xaf, 0xb5, 0x90, 0x04, 0x1b, 0xec, 0x50, 0x3b, 0xec, 0xdc,
     285             :         0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
     286             :         0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     287             :         0x80, 0x66, 0x28, 0xea, 0x37, 0x80, 0xc5, 0x01, 0x16, 0x00, 0x77, 0x00, 0x32, 0x00, 0x30, 0x00,
     288             :         0x30, 0x00, 0x33, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x24, 0x00,
     289             :         0x76, 0xff, 0xff, 0xff, 0x37, 0xd5, 0xb0, 0xf7, 0x24, 0xf0, 0xd6, 0xd4, 0xec, 0x09, 0x86, 0x5a,
     290             :         0xa0, 0xe8, 0xc3, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x76, 0xff, 0xff, 0xff, 0xb4, 0xd8, 0xb8, 0xfe,
     291             :         0x83, 0xb3, 0x13, 0x3f, 0xfc, 0x5c, 0x41, 0xad, 0xe2, 0x64, 0x83, 0xe0, 0x00, 0x00, 0x00, 0x00
     292             : };
     293             : 
     294             : /* Check with a known 'well formed' PAC, from my test server */
     295           1 : static bool torture_pac_saved_check(struct torture_context *tctx)
     296             : {
     297           1 :         NTSTATUS nt_status;
     298           1 :         enum ndr_err_code ndr_err;
     299           1 :         DATA_BLOB tmp_blob, validate_blob;
     300           1 :         struct PAC_DATA *pac_data, pac_data2;
     301           1 :         struct PAC_LOGON_INFO *logon_info;
     302           1 :         union netr_Validation validation;
     303           1 :         const char *pac_file, *pac_kdc_key, *pac_member_key;
     304           1 :         struct auth_user_info_dc *user_info_dc_out;
     305             : 
     306           1 :         krb5_keyblock server_keyblock;
     307           1 :         krb5_keyblock krbtgt_keyblock, *krbtgt_keyblock_p;
     308           1 :         struct samr_Password *krbtgt_bytes, *krbsrv_bytes;
     309             :         
     310           1 :         krb5_error_code ret;
     311           1 :         struct smb_krb5_context *smb_krb5_context;
     312             : 
     313           1 :         const char *principal_string;
     314           1 :         char *broken_principal_string;
     315           1 :         krb5_principal client_principal;
     316           1 :         const char *authtime_string;
     317           1 :         time_t authtime;
     318           1 :         TALLOC_CTX *mem_ctx = tctx;
     319             : 
     320           1 :         torture_assert(tctx, 0 == smb_krb5_init_context(mem_ctx,
     321             :                                                         tctx->lp_ctx,
     322             :                                                         &smb_krb5_context),
     323             :                        "smb_krb5_init_context");
     324             : 
     325           1 :         pac_kdc_key = torture_setting_string(tctx, "pac_kdc_key", 
     326             :                                              "B286757148AF7FD252C53603A150B7E7");
     327             : 
     328           1 :         pac_member_key = torture_setting_string(tctx, "pac_member_key", 
     329             :                                                 "D217FAEAE5E6B5F95CCC94077AB8A5FC");
     330             : 
     331           1 :         torture_comment(tctx, "Using pac_kdc_key '%s'\n", pac_kdc_key);
     332           1 :         torture_comment(tctx, "Using pac_member_key '%s'\n", pac_member_key);
     333             : 
     334             :         /* The krbtgt key in use when the above PAC was generated.
     335             :          * This is an arcfour-hmac-md5 key, extracted with our 'net
     336             :          * samdump' tool. */
     337           1 :         if (*pac_kdc_key == 0) {
     338           0 :                 krbtgt_bytes = NULL;
     339             :         } else {
     340           1 :                 krbtgt_bytes = smbpasswd_gethexpwd(mem_ctx, pac_kdc_key);
     341           1 :                 if (!krbtgt_bytes) {
     342           0 :                         torture_fail(tctx, "(saved test) Could not interpret krbtgt key");
     343             :                 }
     344             :         }
     345             : 
     346           1 :         krbsrv_bytes = smbpasswd_gethexpwd(mem_ctx, pac_member_key);
     347           1 :         if (!krbsrv_bytes) {
     348           0 :                 torture_fail(tctx, "(saved test) Could not interpret krbsrv key");
     349             :         }
     350             : 
     351           2 :         ret = smb_krb5_keyblock_init_contents(smb_krb5_context->krb5_context,
     352             :                                  ENCTYPE_ARCFOUR_HMAC,
     353           1 :                                  krbsrv_bytes->hash, sizeof(krbsrv_bytes->hash),
     354             :                                  &server_keyblock);
     355           1 :         torture_assert(tctx, !ret,
     356             :                        talloc_asprintf(tctx,
     357             :                                        "(saved test) Server Keyblock encoding failed: %s", 
     358             :                                        smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
     359             :                                                                   ret, mem_ctx)));
     360             : 
     361           1 :         if (krbtgt_bytes) {
     362           2 :                 ret = smb_krb5_keyblock_init_contents(smb_krb5_context->krb5_context,
     363             :                                          ENCTYPE_ARCFOUR_HMAC,
     364           1 :                                          krbtgt_bytes->hash, sizeof(krbtgt_bytes->hash),
     365             :                                          &krbtgt_keyblock);
     366           1 :                 if (ret) {
     367           0 :                         krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     368             :                                                     &server_keyblock);
     369           0 :                         torture_fail(tctx, 
     370             :                                      talloc_asprintf(tctx, 
     371             :                                                      "(saved test) Server Keyblock encoding failed: %s", 
     372             :                                                      smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
     373             :                                                                                 ret, mem_ctx)));
     374             :                 }
     375           0 :                 krbtgt_keyblock_p = &krbtgt_keyblock;
     376             :         } else {
     377           0 :                 krbtgt_keyblock_p = NULL;
     378             :         }
     379             : 
     380           1 :         pac_file = torture_setting_string(tctx, "pac_file", NULL);
     381           1 :         if (pac_file) {
     382           0 :                 tmp_blob.data = (uint8_t *)file_load(pac_file, &tmp_blob.length, 0, mem_ctx);
     383           0 :                 torture_comment(tctx, "(saved test) Loaded pac of size %ld from %s\n", (long)tmp_blob.length, pac_file);
     384             :         } else {
     385           1 :                 tmp_blob = data_blob_talloc(mem_ctx, saved_pac, sizeof(saved_pac));
     386             :         }
     387             :         
     388           1 :         dump_data(10,tmp_blob.data,tmp_blob.length);
     389             : 
     390           1 :         principal_string = torture_setting_string(tctx, "pac_client_principal", 
     391             :                                                   "w2003final$@WIN2K3.THINKER.LOCAL");
     392             : 
     393           1 :         authtime_string = torture_setting_string(tctx, "pac_authtime", "1120440609");
     394           1 :         authtime = strtoull(authtime_string, NULL, 0);
     395             : 
     396           1 :         ret = krb5_parse_name(smb_krb5_context->krb5_context, principal_string, 
     397             :                               &client_principal);
     398           1 :         if (ret) {
     399           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     400             :                                             krbtgt_keyblock_p);
     401           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     402             :                                             &server_keyblock);
     403           0 :                 torture_fail(tctx,  
     404             :                              talloc_asprintf(tctx, 
     405             :                                              "(saved test) parsing of client principal [%s] failed: %s", 
     406             :                                              principal_string, 
     407             :                                              smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
     408             :         }
     409             : 
     410             :         /* Decode and verify the signaure on the PAC */
     411           2 :         nt_status = kerberos_decode_pac(mem_ctx, 
     412             :                                         tmp_blob,
     413           1 :                                         smb_krb5_context->krb5_context,
     414             :                                         krbtgt_keyblock_p,
     415             :                                         &server_keyblock, 
     416             :                                         client_principal, authtime, &pac_data);
     417           1 :         if (!NT_STATUS_IS_OK(nt_status)) {
     418           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     419             :                                             krbtgt_keyblock_p);
     420           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     421             :                                             &server_keyblock);
     422           0 :                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
     423             :                 
     424           0 :                 torture_fail(tctx, talloc_asprintf(tctx, 
     425             :                                                    "(saved test) PAC decoding failed: %s", 
     426             :                                                    nt_errstr(nt_status)));
     427             :         }
     428             : 
     429             :         /* Now check we can read it back (using Heimdal's pac parsing) */
     430           2 :         nt_status = kerberos_pac_blob_to_user_info_dc(mem_ctx,
     431             :                                                      tmp_blob, 
     432           1 :                                                      smb_krb5_context->krb5_context,
     433             :                                                       &user_info_dc_out,
     434             :                                                       NULL, NULL);
     435             : 
     436           1 :         if (!NT_STATUS_IS_OK(nt_status)) {
     437           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     438             :                                             krbtgt_keyblock_p);
     439           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     440             :                                             &server_keyblock);
     441           0 :                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
     442             :                 
     443           0 :                 torture_fail(tctx, talloc_asprintf(tctx, 
     444             :                                                    "(saved test) Heimdal PAC decoding failed: %s", 
     445             :                                                    nt_errstr(nt_status)));
     446             :         }
     447             : 
     448           2 :         if (!pac_file &&
     449           1 :             !dom_sid_equal(dom_sid_parse_talloc(mem_ctx, 
     450             :                                                 "S-1-5-21-3048156945-3961193616-3706469200-1005"), 
     451           1 :                            &user_info_dc_out->sids[PRIMARY_USER_SID_INDEX].sid)) {
     452           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     453             :                                             krbtgt_keyblock_p);
     454           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     455             :                                             &server_keyblock);
     456           0 :                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
     457             : 
     458           0 :                 torture_fail(tctx,  
     459             :                              talloc_asprintf(tctx, 
     460             :                                              "(saved test) Heimdal PAC Decode resulted in *different* domain SID: %s != %s",
     461             :                                              "S-1-5-21-3048156945-3961193616-3706469200-1005", 
     462             :                                              dom_sid_string(mem_ctx, &user_info_dc_out->sids[PRIMARY_USER_SID_INDEX].sid)));
     463             :         }
     464             : 
     465           1 :         talloc_free(user_info_dc_out);
     466             : 
     467             :         /* Parse the PAC again, for the logon info this time (using Samba4's parsing) */
     468           2 :         nt_status = kerberos_pac_logon_info(mem_ctx, 
     469             :                                             tmp_blob,
     470           1 :                                             smb_krb5_context->krb5_context,
     471             :                                             krbtgt_keyblock_p,
     472             :                                             &server_keyblock,
     473             :                                             client_principal, authtime, &logon_info);
     474             : 
     475           1 :         if (!NT_STATUS_IS_OK(nt_status)) {
     476           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     477             :                                             krbtgt_keyblock_p);
     478           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     479             :                                             &server_keyblock);
     480           0 :                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
     481             :         
     482           0 :                 torture_fail(tctx,  
     483             :                              talloc_asprintf(tctx, 
     484             :                                              "(saved test) PAC decoding (for logon info) failed: %s", 
     485             :                                              nt_errstr(nt_status)));
     486             :         }
     487             : 
     488           1 :         validation.sam3 = &logon_info->info3;
     489           1 :         nt_status = make_user_info_dc_netlogon_validation(mem_ctx,
     490             :                                                          "",
     491             :                                                          3, &validation,
     492             :                                                           true, /* This user was authenticated */
     493             :                                                          &user_info_dc_out);
     494           1 :         if (!NT_STATUS_IS_OK(nt_status)) {
     495           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     496             :                                             krbtgt_keyblock_p);
     497           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     498             :                                             &server_keyblock);
     499           0 :                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
     500             : 
     501           0 :                 torture_fail(tctx,  
     502             :                              talloc_asprintf(tctx, 
     503             :                                              "(saved test) PAC decoding (make server info) failed: %s", 
     504             :                                              nt_errstr(nt_status)));
     505             :         }
     506             : 
     507           2 :         if (!pac_file &&
     508           1 :             !dom_sid_equal(dom_sid_parse_talloc(mem_ctx, 
     509             :                                                 "S-1-5-21-3048156945-3961193616-3706469200-1005"), 
     510           1 :                            &user_info_dc_out->sids[PRIMARY_USER_SID_INDEX].sid)) {
     511           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     512             :                                             krbtgt_keyblock_p);
     513           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     514             :                                             &server_keyblock);
     515           0 :                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
     516             : 
     517           0 :                 torture_fail(tctx,  
     518             :                              talloc_asprintf(tctx, 
     519             :                                              "(saved test) PAC Decode resulted in *different* domain SID: %s != %s",
     520             :                                              "S-1-5-21-3048156945-3961193616-3706469200-1005", 
     521             :                                              dom_sid_string(mem_ctx, &user_info_dc_out->sids[PRIMARY_USER_SID_INDEX].sid)));
     522             :         }
     523             : 
     524           1 :         if (krbtgt_bytes == NULL) {
     525           0 :                 torture_comment(tctx, "skipping PAC encoding tests as non kdc key\n");
     526           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     527             :                                             &server_keyblock);
     528           0 :                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
     529           0 :                 return true;
     530             :         }
     531             : 
     532           2 :         ret = kerberos_encode_pac(mem_ctx, 
     533             :                                   pac_data,
     534           1 :                                   smb_krb5_context->krb5_context,
     535             :                                   krbtgt_keyblock_p,
     536             :                                   &server_keyblock,
     537             :                                   &validate_blob);
     538             : 
     539           1 :         if (ret != 0) {
     540           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     541             :                                             krbtgt_keyblock_p);
     542           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     543             :                                             &server_keyblock);
     544           0 :                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
     545             : 
     546           0 :                 torture_fail(tctx, "(saved test) PAC push failed");
     547             :         }
     548             : 
     549           1 :         dump_data(10, validate_blob.data, validate_blob.length);
     550             : 
     551             :         /* compare both the length and the data bytes after a
     552             :          * pull/push cycle.  This ensures we use the exact same
     553             :          * pointer, padding etc algorithms as win2k3.
     554             :          */
     555           1 :         if (tmp_blob.length != validate_blob.length) {
     556           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     557             :                                             krbtgt_keyblock_p);
     558           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     559             :                                             &server_keyblock);
     560           0 :                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
     561             : 
     562           0 :                 torture_fail(tctx, 
     563             :                              talloc_asprintf(tctx, 
     564             :                                              "(saved test) PAC push failed: original buffer length[%u] != created buffer length[%u]",
     565             :                                              (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
     566             :         }
     567             : 
     568           1 :         if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
     569           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     570             :                                             krbtgt_keyblock_p);
     571           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     572             :                                             &server_keyblock);
     573           0 :                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
     574             : 
     575           0 :                 DEBUG(0, ("tmp_data:\n"));
     576           0 :                 dump_data(0, tmp_blob.data, tmp_blob.length);
     577           0 :                 DEBUG(0, ("validate_blob:\n"));
     578           0 :                 dump_data(0, validate_blob.data, validate_blob.length);
     579             : 
     580           0 :                 torture_fail(tctx, talloc_asprintf(tctx, "(saved test) PAC push failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
     581             :         }
     582             : 
     583           2 :         ret = kerberos_create_pac(mem_ctx, 
     584             :                                   user_info_dc_out,
     585           1 :                                   smb_krb5_context->krb5_context,
     586             :                                   krbtgt_keyblock_p,
     587             :                                   &server_keyblock,
     588             :                                   client_principal, authtime,
     589             :                                   &validate_blob);
     590             : 
     591           1 :         if (ret != 0) {
     592           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     593             :                                             krbtgt_keyblock_p);
     594           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     595             :                                             &server_keyblock);
     596           0 :                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
     597             : 
     598           0 :                 torture_fail(tctx, "(saved test) regnerated PAC create failed");
     599             :         }
     600             : 
     601           1 :         dump_data(10,validate_blob.data,validate_blob.length);
     602             : 
     603             :         /* compare both the length and the data bytes after a
     604             :          * pull/push cycle.  This ensures we use the exact same
     605             :          * pointer, padding etc algorithms as win2k3.
     606             :          */
     607           1 :         if (tmp_blob.length != validate_blob.length) {
     608           0 :                 ndr_err = ndr_pull_struct_blob(&validate_blob, mem_ctx, 
     609             :                                                &pac_data2,
     610             :                                                (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
     611           0 :                 nt_status = ndr_map_error2ntstatus(ndr_err);
     612           0 :                 torture_assert_ntstatus_ok(tctx, nt_status, "can't parse the PAC");
     613             :                 
     614           0 :                 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
     615             : 
     616           0 :                 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
     617             : 
     618           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     619             :                                             krbtgt_keyblock_p);
     620           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     621             :                                             &server_keyblock);
     622           0 :                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
     623             : 
     624           0 :                 torture_fail(tctx, talloc_asprintf(tctx, 
     625             :                                                    "(saved test) PAC regenerate failed: original buffer length[%u] != created buffer length[%u]",
     626             :                                                    (unsigned)tmp_blob.length, (unsigned)validate_blob.length));
     627             :         }
     628             : 
     629           1 :         if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
     630           0 :                 ndr_err = ndr_pull_struct_blob(&validate_blob, mem_ctx, 
     631             :                                                &pac_data2,
     632             :                                                (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
     633           0 :                 nt_status = ndr_map_error2ntstatus(ndr_err);
     634           0 :                 torture_assert_ntstatus_ok(tctx, nt_status, "can't parse the PAC");
     635             :                 
     636           0 :                 NDR_PRINT_DEBUG(PAC_DATA, pac_data);
     637             : 
     638           0 :                 NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
     639             : 
     640           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     641             :                                             krbtgt_keyblock_p);
     642           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     643             :                                             &server_keyblock);
     644           0 :                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
     645             : 
     646           0 :                 DEBUG(0, ("tmp_data:\n"));
     647           0 :                 dump_data(0, tmp_blob.data, tmp_blob.length);
     648           0 :                 DEBUG(0, ("validate_blob:\n"));
     649           0 :                 dump_data(0, validate_blob.data, validate_blob.length);
     650             : 
     651           0 :                 torture_fail(tctx, talloc_asprintf(tctx, 
     652             :                                                    "(saved test) PAC regenerate failed: length[%u] matches, but data does not", (unsigned)tmp_blob.length));
     653             :         }
     654             : 
     655             :         /* Break the auth time, to ensure we check this vital detail (not setting this caused all the pain in the first place... */
     656           2 :         nt_status = kerberos_decode_pac(mem_ctx, 
     657             :                                         tmp_blob,
     658           1 :                                         smb_krb5_context->krb5_context,
     659             :                                         krbtgt_keyblock_p,
     660             :                                         &server_keyblock,
     661             :                                         client_principal, 
     662             :                                         authtime + 1, &pac_data);
     663           1 :         if (NT_STATUS_IS_OK(nt_status)) {
     664             : 
     665           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     666             :                                             krbtgt_keyblock_p);
     667           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     668             :                                             &server_keyblock);
     669           0 :                 krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
     670           0 :                 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on broken auth time (time + 1)");
     671             :         }
     672             : 
     673             :         /* Break the client principal */
     674           1 :         krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
     675             : 
     676           1 :         broken_principal_string = talloc_strdup(mem_ctx, principal_string);
     677           1 :         broken_principal_string[0]++;
     678             : 
     679           1 :         ret = krb5_parse_name(smb_krb5_context->krb5_context,
     680             :                               broken_principal_string, &client_principal);
     681           1 :         if (ret) {
     682             : 
     683           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     684             :                                             krbtgt_keyblock_p);
     685           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     686             :                                             &server_keyblock);
     687           0 :                 torture_fail(tctx, talloc_asprintf(tctx, 
     688             :                                                    "(saved test) parsing of broken client principal failed: %s", 
     689             :                                                    smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
     690             :         }
     691             : 
     692           2 :         nt_status = kerberos_decode_pac(mem_ctx, 
     693             :                                         tmp_blob,
     694           1 :                                         smb_krb5_context->krb5_context,
     695             :                                         krbtgt_keyblock_p,
     696             :                                         &server_keyblock,
     697             :                                         client_principal, 
     698             :                                         authtime, &pac_data);
     699           1 :         if (NT_STATUS_IS_OK(nt_status)) {
     700           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     701             :                                             krbtgt_keyblock_p);
     702           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     703             :                                             &server_keyblock);
     704           0 :                 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on modified principal");
     705             :         }
     706             : 
     707             :         /* Finally...  Bugger up the signature, and check we fail the checksum */
     708           1 :         tmp_blob.data[tmp_blob.length - 2]++;
     709             : 
     710           2 :         nt_status = kerberos_decode_pac(mem_ctx, 
     711             :                                         tmp_blob,
     712           1 :                                         smb_krb5_context->krb5_context,
     713             :                                         krbtgt_keyblock_p,
     714             :                                         &server_keyblock,
     715             :                                         client_principal, 
     716             :                                         authtime,
     717             :                                         &pac_data);
     718           1 :         if (NT_STATUS_IS_OK(nt_status)) {
     719           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     720             :                                             krbtgt_keyblock_p);
     721           0 :                 krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     722             :                                             &server_keyblock);
     723           0 :                 torture_fail(tctx, "(saved test) PAC decoding DID NOT fail on broken checksum");
     724             :         }
     725             : 
     726           1 :         krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     727             :                                     krbtgt_keyblock_p);
     728           1 :         krb5_free_keyblock_contents(smb_krb5_context->krb5_context, 
     729             :                                     &server_keyblock);
     730           1 :         return true;
     731             : }
     732             : 
     733        2338 : struct torture_suite *torture_pac(TALLOC_CTX *mem_ctx)
     734             : {
     735        2338 :         struct torture_suite *suite = torture_suite_create(mem_ctx, "pac");
     736             : 
     737        2338 :         torture_suite_add_simple_test(suite, "self check", 
     738             :                                       torture_pac_self_check);
     739        2338 :         torture_suite_add_simple_test(suite, "saved check",
     740             :                                       torture_pac_saved_check);
     741        2338 :         return suite;
     742             : }

Generated by: LCOV version 1.14