root/source4/torture/rpc/remote_pac.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. test_PACVerify
  2. torture_rpc_remote_pac

   1 /* 
   2    Unix SMB/CIFS implementation.
   3 
   4    test suite for netlogon PAC operations
   5 
   6    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008
   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    You should have received a copy of the GNU General Public License
  19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  20 */
  21 
  22 #include "includes.h"
  23 #include "torture/torture.h"
  24 #include "lib/events/events.h"
  25 #include "auth/auth.h"
  26 #include "auth/gensec/gensec.h"
  27 #include "lib/cmdline/popt_common.h"
  28 #include "torture/rpc/rpc.h"
  29 #include "torture/rpc/netlogon.h"
  30 #include "libcli/auth/libcli_auth.h"
  31 #include "librpc/gen_ndr/ndr_netlogon_c.h"
  32 #include "librpc/gen_ndr/ndr_krb5pac.h"
  33 #include "param/param.h"
  34 #include "lib/messaging/irpc.h"
  35 #include "cluster/cluster.h"
  36 
  37 #define TEST_MACHINE_NAME "torturepactest"
  38 
  39 /* Check to see if we can pass the PAC across to the NETLOGON server for validation */
  40 
  41 /* Also happens to be a really good one-step verfication of our Kerberos stack */
  42 
  43 static bool test_PACVerify(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
  44                            struct dcerpc_pipe *p,
  45                            struct cli_credentials *credentials)
  46 {
  47         NTSTATUS status;
  48 
  49         struct netr_LogonSamLogon r;
  50 
  51         union netr_LogonLevel logon;
  52         union netr_Validation validation;
  53         uint8_t authoritative;
  54         struct netr_Authenticator return_authenticator;
  55 
  56         struct netr_GenericInfo generic;
  57         struct netr_Authenticator auth, auth2;
  58         
  59 
  60         struct creds_CredentialState *creds;
  61         struct gensec_security *gensec_client_context;
  62         struct gensec_security *gensec_server_context;
  63 
  64         DATA_BLOB client_to_server, server_to_client, pac_wrapped, payload;
  65         struct PAC_Validate pac_wrapped_struct;
  66         
  67         enum ndr_err_code ndr_err;
  68 
  69         struct auth_session_info *session_info;
  70 
  71         char *tmp_dir;
  72 
  73         TALLOC_CTX *tmp_ctx = talloc_new(tctx);
  74         
  75         torture_assert(tctx, tmp_ctx != NULL, "talloc_new() failed");
  76 
  77         if (!test_SetupCredentials2(p, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, 
  78                                     credentials, SEC_CHAN_BDC, 
  79                                     &creds)) {
  80                 return false;
  81         }
  82 
  83         status = torture_temp_dir(tctx, "PACVerify", &tmp_dir);
  84         torture_assert_ntstatus_ok(tctx, status, "torture_temp_dir failed");
  85 
  86         status = gensec_client_start(tctx, &gensec_client_context, tctx->ev, 
  87                                      lp_gensec_settings(tctx, tctx->lp_ctx));
  88         torture_assert_ntstatus_ok(tctx, status, "gensec_client_start (client) failed");
  89 
  90         status = gensec_set_target_hostname(gensec_client_context, TEST_MACHINE_NAME);
  91 
  92         status = gensec_set_credentials(gensec_client_context, cmdline_credentials);
  93         torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (client) failed");
  94 
  95         status = gensec_start_mech_by_sasl_name(gensec_client_context, "GSSAPI");
  96         torture_assert_ntstatus_ok(tctx, status, "gensec_start_mech_by_sasl_name (client) failed");
  97 
  98         status = gensec_server_start(tctx, tctx->ev, 
  99                                      lp_gensec_settings(tctx, tctx->lp_ctx), 
 100                                      NULL, &gensec_server_context);
 101         torture_assert_ntstatus_ok(tctx, status, "gensec_server_start (server) failed");
 102 
 103         status = gensec_set_credentials(gensec_server_context, credentials);
 104         torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (server) failed");
 105 
 106         status = gensec_start_mech_by_sasl_name(gensec_server_context, "GSSAPI");
 107         torture_assert_ntstatus_ok(tctx, status, "gensec_start_mech_by_sasl_name (server) failed");
 108 
 109         server_to_client = data_blob(NULL, 0);
 110         
 111         do {
 112                 /* Do a client-server update dance */
 113                 status = gensec_update(gensec_client_context, tmp_ctx, server_to_client, &client_to_server);
 114                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {;
 115                         torture_assert_ntstatus_ok(tctx, status, "gensec_update (client) failed");
 116                 }
 117 
 118                 status = gensec_update(gensec_server_context, tmp_ctx, client_to_server, &server_to_client);
 119                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {;
 120                         torture_assert_ntstatus_ok(tctx, status, "gensec_update (server) failed");
 121                 }
 122 
 123                 if (NT_STATUS_IS_OK(status)) {
 124                         break;
 125                 }
 126         } while (1);
 127 
 128         /* Extract the PAC using Samba's code */
 129 
 130         status = gensec_session_info(gensec_server_context, &session_info);
 131         torture_assert_ntstatus_ok(tctx, status, "gensec_session_info failed");
 132         
 133         pac_wrapped_struct.ChecksumLength = session_info->server_info->pac_srv_sig.signature.length;
 134         pac_wrapped_struct.SignatureType = session_info->server_info->pac_kdc_sig.type;
 135         pac_wrapped_struct.SignatureLength = session_info->server_info->pac_kdc_sig.signature.length;
 136         pac_wrapped_struct.ChecksumAndSignature = payload
 137                 = data_blob_talloc(tmp_ctx, NULL, 
 138                                    pac_wrapped_struct.ChecksumLength
 139                                    + pac_wrapped_struct.SignatureLength);
 140         memcpy(&payload.data[0], 
 141                session_info->server_info->pac_srv_sig.signature.data, 
 142                pac_wrapped_struct.ChecksumLength);
 143         memcpy(&payload.data[pac_wrapped_struct.ChecksumLength], 
 144                session_info->server_info->pac_kdc_sig.signature.data, 
 145                pac_wrapped_struct.SignatureLength);
 146 
 147         ndr_err = ndr_push_struct_blob(&pac_wrapped, tmp_ctx, lp_iconv_convenience(tctx->lp_ctx), &pac_wrapped_struct,
 148                                        (ndr_push_flags_fn_t)ndr_push_PAC_Validate);
 149         torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "ndr_push_struct_blob of PACValidate structure failed");
 150                 
 151         torture_assert(tctx, (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR), "not willing to even try a PACValidate without RC4 encryption");
 152         creds_arcfour_crypt(creds, pac_wrapped.data, pac_wrapped.length);
 153 
 154         generic.length = pac_wrapped.length;
 155         generic.data = pac_wrapped.data;
 156 
 157         /* Validate it over the netlogon pipe */
 158 
 159         generic.identity_info.parameter_control = 0;
 160         generic.identity_info.logon_id_high = 0;
 161         generic.identity_info.logon_id_low = 0;
 162         generic.identity_info.domain_name.string = session_info->server_info->domain_name;
 163         generic.identity_info.account_name.string = session_info->server_info->account_name;
 164         generic.identity_info.workstation.string = TEST_MACHINE_NAME;
 165 
 166         generic.package_name.string = "Kerberos";
 167 
 168         logon.generic = &generic;
 169 
 170         ZERO_STRUCT(auth2);
 171         creds_client_authenticator(creds, &auth);
 172         r.in.credential = &auth;
 173         r.in.return_authenticator = &auth2;
 174         r.in.logon = &logon;
 175         r.in.logon_level = NetlogonGenericInformation;
 176         r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
 177         r.in.computer_name = cli_credentials_get_workstation(credentials);
 178         r.in.validation_level = NetlogonValidationGenericInfo2;
 179         r.out.validation = &validation;
 180         r.out.authoritative = &authoritative;
 181         r.out.return_authenticator = &return_authenticator;
 182 
 183         status = dcerpc_netr_LogonSamLogon(p, tctx, &r);
 184 
 185         torture_assert_ntstatus_ok(tctx, status, "LogonSamLogon failed");
 186         
 187         /* This will break the signature nicely (even in the crypto wrapping), check we get a logon failure */
 188         generic.data[generic.length-1]++;
 189 
 190         logon.generic = &generic;
 191 
 192         ZERO_STRUCT(auth2);
 193         creds_client_authenticator(creds, &auth);
 194         r.in.credential = &auth;
 195         r.in.return_authenticator = &auth2;
 196         r.in.logon_level = NetlogonGenericInformation;
 197         r.in.logon = &logon;
 198         r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
 199         r.in.computer_name = cli_credentials_get_workstation(credentials);
 200         r.in.validation_level = NetlogonValidationGenericInfo2;
 201 
 202         status = dcerpc_netr_LogonSamLogon(p, tctx, &r);
 203 
 204         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOGON_FAILURE, "LogonSamLogon failed");
 205         
 206         torture_assert(tctx, creds_client_check(creds, &r.out.return_authenticator->cred), 
 207                        "Credential chaining failed");
 208 
 209         /* This will break the parsing nicely (even in the crypto wrapping), check we get INVALID_PARAMETER */
 210         generic.length--;
 211 
 212         logon.generic = &generic;
 213 
 214         ZERO_STRUCT(auth2);
 215         creds_client_authenticator(creds, &auth);
 216         r.in.credential = &auth;
 217         r.in.return_authenticator = &auth2;
 218         r.in.logon_level = NetlogonGenericInformation;
 219         r.in.logon = &logon;
 220         r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
 221         r.in.computer_name = cli_credentials_get_workstation(credentials);
 222         r.in.validation_level = NetlogonValidationGenericInfo2;
 223 
 224         status = dcerpc_netr_LogonSamLogon(p, tctx, &r);
 225 
 226         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_INVALID_PARAMETER, "LogonSamLogon failed");
 227         
 228         torture_assert(tctx, creds_client_check(creds, &r.out.return_authenticator->cred), 
 229                        "Credential chaining failed");
 230 
 231         pac_wrapped_struct.ChecksumLength = session_info->server_info->pac_srv_sig.signature.length;
 232         pac_wrapped_struct.SignatureType = session_info->server_info->pac_kdc_sig.type;
 233         
 234         /* Break the SignatureType */
 235         pac_wrapped_struct.SignatureType++;
 236 
 237         pac_wrapped_struct.SignatureLength = session_info->server_info->pac_kdc_sig.signature.length;
 238         pac_wrapped_struct.ChecksumAndSignature = payload
 239                 = data_blob_talloc(tmp_ctx, NULL, 
 240                                    pac_wrapped_struct.ChecksumLength
 241                                    + pac_wrapped_struct.SignatureLength);
 242         memcpy(&payload.data[0], 
 243                session_info->server_info->pac_srv_sig.signature.data, 
 244                pac_wrapped_struct.ChecksumLength);
 245         memcpy(&payload.data[pac_wrapped_struct.ChecksumLength], 
 246                session_info->server_info->pac_kdc_sig.signature.data, 
 247                pac_wrapped_struct.SignatureLength);
 248         
 249         ndr_err = ndr_push_struct_blob(&pac_wrapped, tmp_ctx, lp_iconv_convenience(tctx->lp_ctx), &pac_wrapped_struct,
 250                                        (ndr_push_flags_fn_t)ndr_push_PAC_Validate);
 251         torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "ndr_push_struct_blob of PACValidate structure failed");
 252         
 253         torture_assert(tctx, (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR), "not willing to even try a PACValidate without RC4 encryption");
 254         creds_arcfour_crypt(creds, pac_wrapped.data, pac_wrapped.length);
 255         
 256         generic.length = pac_wrapped.length;
 257         generic.data = pac_wrapped.data;
 258 
 259         logon.generic = &generic;
 260 
 261         ZERO_STRUCT(auth2);
 262         creds_client_authenticator(creds, &auth);
 263         r.in.credential = &auth;
 264         r.in.return_authenticator = &auth2;
 265         r.in.logon_level = NetlogonGenericInformation;
 266         r.in.logon = &logon;
 267         r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
 268         r.in.computer_name = cli_credentials_get_workstation(credentials);
 269         r.in.validation_level = NetlogonValidationGenericInfo2;
 270         
 271         status = dcerpc_netr_LogonSamLogon(p, tctx, &r);
 272         
 273         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOGON_FAILURE, "LogonSamLogon failed");
 274         
 275         torture_assert(tctx, creds_client_check(creds, &r.out.return_authenticator->cred), 
 276                        "Credential chaining failed");
 277 
 278         pac_wrapped_struct.ChecksumLength = session_info->server_info->pac_srv_sig.signature.length;
 279         pac_wrapped_struct.SignatureType = session_info->server_info->pac_kdc_sig.type;
 280         pac_wrapped_struct.SignatureLength = session_info->server_info->pac_kdc_sig.signature.length;
 281 
 282         pac_wrapped_struct.ChecksumAndSignature = payload
 283                 = data_blob_talloc(tmp_ctx, NULL, 
 284                                    pac_wrapped_struct.ChecksumLength
 285                                    + pac_wrapped_struct.SignatureLength);
 286         memcpy(&payload.data[0], 
 287                session_info->server_info->pac_srv_sig.signature.data, 
 288                pac_wrapped_struct.ChecksumLength);
 289         memcpy(&payload.data[pac_wrapped_struct.ChecksumLength], 
 290                session_info->server_info->pac_kdc_sig.signature.data, 
 291                pac_wrapped_struct.SignatureLength);
 292         
 293         /* Break the signature length */
 294         pac_wrapped_struct.SignatureLength++;
 295 
 296         ndr_err = ndr_push_struct_blob(&pac_wrapped, tmp_ctx, lp_iconv_convenience(tctx->lp_ctx), &pac_wrapped_struct,
 297                                        (ndr_push_flags_fn_t)ndr_push_PAC_Validate);
 298         torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "ndr_push_struct_blob of PACValidate structure failed");
 299         
 300         torture_assert(tctx, (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR), "not willing to even try a PACValidate without RC4 encryption");
 301         creds_arcfour_crypt(creds, pac_wrapped.data, pac_wrapped.length);
 302         
 303         generic.length = pac_wrapped.length;
 304         generic.data = pac_wrapped.data;
 305 
 306         logon.generic = &generic;
 307 
 308         ZERO_STRUCT(auth2);
 309         creds_client_authenticator(creds, &auth);
 310         r.in.credential = &auth;
 311         r.in.return_authenticator = &auth2;
 312         r.in.logon_level = NetlogonGenericInformation;
 313         r.in.logon = &logon;
 314         r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
 315         r.in.computer_name = cli_credentials_get_workstation(credentials);
 316         r.in.validation_level = NetlogonValidationGenericInfo2;
 317         
 318         status = dcerpc_netr_LogonSamLogon(p, tctx, &r);
 319         
 320         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_INVALID_PARAMETER, "LogonSamLogon failed");
 321         
 322         torture_assert(tctx, creds_client_check(creds, &r.out.return_authenticator->cred), 
 323                        "Credential chaining failed");
 324         return true;
 325 }
 326 
 327 struct torture_suite *torture_rpc_remote_pac(TALLOC_CTX *mem_ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 328 {
 329         struct torture_suite *suite = torture_suite_create(mem_ctx, "PAC");
 330         struct torture_rpc_tcase *tcase;
 331 
 332         tcase = torture_suite_add_machine_rpc_iface_tcase(suite, "netlogon", 
 333                                                   &ndr_table_netlogon, TEST_MACHINE_NAME);
 334         torture_rpc_tcase_add_test_creds(tcase, "verify", test_PACVerify);
 335 
 336         return suite;
 337 }

/* [<][>][^][v][top][bottom][index][help] */