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

Generated by: LCOV version 1.14