mirror of
https://github.com/samba-team/samba.git
synced 2025-02-26 21:57:41 +03:00
s4-smbtorture: Show that the KDC provides no protection from CVE-2017-11103
The server name in the AS-REQ is unprotected, sadly. BUG: https://bugzilla.samba.org/show_bug.cgi?id=12894 Signed-off-by: Andrew Bartlett <abartlet@samba.org> Reviewed-by: Garming Sam <garming@catalyst.net.nz> Autobuild-User(master): Andrew Bartlett <abartlet@samba.org> Autobuild-Date(master): Thu Nov 2 07:16:50 CET 2017 on sn-devel-144
This commit is contained in:
parent
4d056974dd
commit
dc3adc898e
@ -62,6 +62,8 @@ struct torture_krb5_context {
|
||||
int packet_count;
|
||||
AS_REQ as_req;
|
||||
AS_REP as_rep;
|
||||
const char *krb5_service;
|
||||
const char *krb5_hostname;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -72,7 +74,7 @@ struct torture_krb5_context {
|
||||
*
|
||||
*/
|
||||
|
||||
static bool torture_krb5_pre_send_test(struct torture_krb5_context *test_context, const krb5_data *send_buf)
|
||||
static bool torture_krb5_pre_send_test(struct torture_krb5_context *test_context, krb5_data *send_buf)
|
||||
{
|
||||
size_t used;
|
||||
switch (test_context->test)
|
||||
@ -93,8 +95,41 @@ static bool torture_krb5_pre_send_test(struct torture_krb5_context *test_context
|
||||
break;
|
||||
case TORTURE_KRB5_TEST_CHANGE_SERVER_OUT:
|
||||
case TORTURE_KRB5_TEST_CHANGE_SERVER_BOTH:
|
||||
{
|
||||
AS_REQ mod_as_req;
|
||||
krb5_error_code k5ret;
|
||||
krb5_data modified_send_buf;
|
||||
torture_assert_int_equal(test_context->tctx,
|
||||
decode_AS_REQ(send_buf->data, send_buf->length, &test_context->as_req, &used), 0,
|
||||
"decode_AS_REQ failed");
|
||||
torture_assert_int_equal(test_context->tctx, used, send_buf->length, "length mismatch");
|
||||
torture_assert_int_equal(test_context->tctx, test_context->as_req.pvno, 5, "Got wrong as_req->pvno");
|
||||
|
||||
/* Only change it if configured with --option=torture:krb5-hostname= */
|
||||
if (test_context->krb5_hostname[0] == '\0') {
|
||||
break;
|
||||
}
|
||||
|
||||
mod_as_req = test_context->as_req;
|
||||
|
||||
torture_assert_int_equal(test_context->tctx,
|
||||
mod_as_req.req_body.sname->name_string.len, 2,
|
||||
"Sending wrong mod_as_req.req_body->sname.name_string.len");
|
||||
free(mod_as_req.req_body.sname->name_string.val[0]);
|
||||
free(mod_as_req.req_body.sname->name_string.val[1]);
|
||||
mod_as_req.req_body.sname->name_string.val[0] = strdup(test_context->krb5_service);
|
||||
mod_as_req.req_body.sname->name_string.val[1] = strdup(test_context->krb5_hostname);
|
||||
|
||||
ASN1_MALLOC_ENCODE(AS_REQ, modified_send_buf.data, modified_send_buf.length,
|
||||
&mod_as_req, &used, k5ret);
|
||||
torture_assert_int_equal(test_context->tctx,
|
||||
k5ret, 0,
|
||||
"encode_AS_REQ failed");
|
||||
|
||||
*send_buf = modified_send_buf;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -242,14 +277,16 @@ static bool torture_krb5_post_recv_test(struct torture_krb5_context *test_contex
|
||||
torture_assert(test_context->tctx,
|
||||
test_context->as_rep.ticket.enc_part.kvno,
|
||||
"Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno");
|
||||
if (torture_setting_bool(test_context->tctx, "expect_cached_at_rodc", false)) {
|
||||
torture_assert_int_not_equal(test_context->tctx,
|
||||
*test_context->as_rep.ticket.enc_part.kvno & 0xFFFF0000,
|
||||
0, "Did not get a RODC number in the KVNO");
|
||||
} else {
|
||||
torture_assert_int_equal(test_context->tctx,
|
||||
*test_context->as_rep.ticket.enc_part.kvno & 0xFFFF0000,
|
||||
if (test_context->test == TORTURE_KRB5_TEST_PLAIN) {
|
||||
if (torture_setting_bool(test_context->tctx, "expect_cached_at_rodc", false)) {
|
||||
torture_assert_int_not_equal(test_context->tctx,
|
||||
*test_context->as_rep.ticket.enc_part.kvno & 0xFFFF0000,
|
||||
0, "Did not get a RODC number in the KVNO");
|
||||
} else {
|
||||
torture_assert_int_equal(test_context->tctx,
|
||||
*test_context->as_rep.ticket.enc_part.kvno & 0xFFFF0000,
|
||||
0, "Unexpecedly got a RODC number in the KVNO");
|
||||
}
|
||||
}
|
||||
free_AS_REP(&test_context->as_rep);
|
||||
}
|
||||
@ -527,17 +564,18 @@ static krb5_error_code smb_krb5_send_and_recv_func_override(krb5_context context
|
||||
{
|
||||
krb5_error_code k5ret;
|
||||
bool ok;
|
||||
krb5_data modified_send_buf = *send_buf;
|
||||
|
||||
struct torture_krb5_context *test_context
|
||||
= talloc_get_type_abort(data, struct torture_krb5_context);
|
||||
|
||||
ok = torture_krb5_pre_send_test(test_context, send_buf);
|
||||
ok = torture_krb5_pre_send_test(test_context, &modified_send_buf);
|
||||
if (ok == false) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
k5ret = smb_krb5_send_and_recv_func_forced(context, test_context->server,
|
||||
hi, timeout, send_buf, recv_buf);
|
||||
hi, timeout, &modified_send_buf, recv_buf);
|
||||
if (k5ret != 0) {
|
||||
return k5ret;
|
||||
}
|
||||
@ -572,6 +610,9 @@ static bool torture_krb5_init_context(struct torture_context *tctx,
|
||||
test_context->test = test;
|
||||
test_context->tctx = tctx;
|
||||
|
||||
test_context->krb5_service = torture_setting_string(tctx, "krb5-service", "host");
|
||||
test_context->krb5_hostname = torture_setting_string(tctx, "krb5-hostname", "");
|
||||
|
||||
k5ret = smb_krb5_init_context(tctx, tctx->lp_ctx, smb_krb5_context);
|
||||
torture_assert_int_equal(tctx, k5ret, 0, "smb_krb5_init_context failed");
|
||||
|
||||
@ -605,6 +646,9 @@ static bool torture_krb5_as_req_creds(struct torture_context *tctx,
|
||||
const char *expected_principal_string;
|
||||
krb5_get_init_creds_opt *krb_options = NULL;
|
||||
const char *realm;
|
||||
const char *krb5_service = torture_setting_string(tctx, "krb5-service", "host");
|
||||
const char *krb5_hostname = torture_setting_string(tctx, "krb5-hostname", "");
|
||||
|
||||
|
||||
ok = torture_krb5_init_context(tctx, test, &smb_krb5_context);
|
||||
torture_assert(tctx, ok, "torture_krb5_init_context failed");
|
||||
@ -760,9 +804,54 @@ static bool torture_krb5_as_req_creds(struct torture_context *tctx,
|
||||
|
||||
case TORTURE_KRB5_TEST_CHANGE_SERVER_OUT:
|
||||
case TORTURE_KRB5_TEST_CHANGE_SERVER_BOTH:
|
||||
{
|
||||
char *got_principal_string;
|
||||
char *assertion_message;
|
||||
torture_assert_int_equal(tctx, k5ret, 0, "krb5_get_init_creds_password failed");
|
||||
|
||||
torture_assert_int_equal(tctx,
|
||||
krb5_principal_get_type(k5_context,
|
||||
my_creds.client),
|
||||
KRB5_NT_PRINCIPAL,
|
||||
"smb_krb5_init_context gave incorrect client->name.name_type");
|
||||
|
||||
torture_assert_int_equal(tctx,
|
||||
krb5_unparse_name(k5_context,
|
||||
my_creds.client,
|
||||
&got_principal_string), 0,
|
||||
"krb5_unparse_name failed");
|
||||
|
||||
assertion_message = talloc_asprintf(tctx,
|
||||
"krb5_get_init_creds_password returned a different principal %s to what was expected %s",
|
||||
got_principal_string, expected_principal_string);
|
||||
krb5_free_unparsed_name(k5_context, got_principal_string);
|
||||
|
||||
torture_assert(tctx, krb5_principal_compare(k5_context,
|
||||
my_creds.client,
|
||||
principal),
|
||||
assertion_message);
|
||||
|
||||
if (krb5_hostname[0] == '\0') {
|
||||
break;
|
||||
}
|
||||
|
||||
torture_assert_str_equal(tctx,
|
||||
my_creds.server->name.name_string.val[0],
|
||||
krb5_service,
|
||||
"Mismatch in name[0] between AS_REP and expected response");
|
||||
torture_assert_str_equal(tctx,
|
||||
my_creds.server->name.name_string.val[1],
|
||||
krb5_hostname,
|
||||
"Mismatch in name[1] between AS_REP and expected response");
|
||||
|
||||
torture_assert_str_equal(tctx,
|
||||
my_creds.server->realm,
|
||||
realm,
|
||||
"Mismatch in server realm in AS_REP, expected krbtgt/REALM@REALM");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
k5ret = krb5_free_cred_contents(smb_krb5_context->krb5_context, &my_creds);
|
||||
torture_assert_int_equal(tctx, k5ret, 0, "krb5_free_creds failed");
|
||||
|
Loading…
x
Reference in New Issue
Block a user