diff options
author | Andrew Bartlett <abartlet@samba.org> | 2015-01-05 17:48:50 +1300 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2015-01-23 05:42:07 +0100 |
commit | 672ade3876877ad30e4367f0cd01e660b0def8cd (patch) | |
tree | 2cde4db28942d61822f31892e252b1ce8fbd78f5 /source4/torture/krb5 | |
parent | fc84d35c4eaf50ca8139b1210201be12d89a0b3e (diff) | |
download | samba-672ade3876877ad30e4367f0cd01e660b0def8cd.tar.gz |
torture: Decode expected packets and test KDC behaviour for wrong passwords
Pair-programmed-with: Garming Sam <garming@catalyst.net.nz>
Signed-off-by: Garming Sam <garming@catalyst.net.nz>
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Diffstat (limited to 'source4/torture/krb5')
-rw-r--r-- | source4/torture/krb5/kdc.c | 173 |
1 files changed, 164 insertions, 9 deletions
diff --git a/source4/torture/krb5/kdc.c b/source4/torture/krb5/kdc.c index c9014cf56e2..c9a1a60794a 100644 --- a/source4/torture/krb5/kdc.c +++ b/source4/torture/krb5/kdc.c @@ -30,31 +30,170 @@ #include "source4/auth/kerberos/kerberos_util.h" #include "lib/util/util_net.h" +enum torture_krb5_test { + TORTURE_KRB5_TEST_PLAIN, + TORTURE_KRB5_TEST_BREAK_PW +}; + +struct torture_krb5_context { + struct torture_context *tctx; + struct addrinfo *server; + enum torture_krb5_test test; + int packet_count; + AS_REQ as_req; + AS_REP as_rep; +}; + +static bool torture_krb5_pre_send_test(struct torture_krb5_context *test_context, const krb5_data *send_buf) +{ + size_t used; + switch (test_context->test) + { + case TORTURE_KRB5_TEST_PLAIN: + case TORTURE_KRB5_TEST_BREAK_PW: + 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"); + break; + } + return true; +} + +static bool torture_krb5_post_recv_test(struct torture_krb5_context *test_context, const krb5_data *recv_buf) +{ + KRB_ERROR error; + size_t used; + switch (test_context->test) + { + case TORTURE_KRB5_TEST_PLAIN: + if (test_context->packet_count == 0) { + torture_assert_int_equal(test_context->tctx, + decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used), 0, + "decode_AS_REP failed"); + torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); + torture_assert_int_equal(test_context->tctx, error.pvno, 5, "Got wrong error.pvno"); + torture_assert_int_equal(test_context->tctx, error.error_code, KRB5KDC_ERR_PREAUTH_REQUIRED - KRB5KDC_ERR_NONE, + "Got wrong error.error_code"); + free_KRB_ERROR(&error); + } else if ((decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used) == 0) + && (test_context->packet_count == 1)) { + torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); + torture_assert_int_equal(test_context->tctx, error.pvno, 5, "Got wrong error.pvno"); + torture_assert_int_equal(test_context->tctx, error.error_code, KRB5KRB_ERR_RESPONSE_TOO_BIG - KRB5KDC_ERR_NONE, + "Got wrong error.error_code"); + free_KRB_ERROR(&error); + } else { + torture_assert_int_equal(test_context->tctx, + decode_AS_REP(recv_buf->data, recv_buf->length, &test_context->as_rep, &used), 0, + "decode_AS_REP failed"); + torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); + torture_assert_int_equal(test_context->tctx, test_context->as_rep.pvno, 5, "Got wrong as_rep->pvno"); + free_AS_REP(&test_context->as_rep); + } + torture_assert(test_context->tctx, test_context->packet_count < 3, "too many packets"); + free_AS_REQ(&test_context->as_req); + break; + case TORTURE_KRB5_TEST_BREAK_PW: + if (test_context->packet_count == 0) { + torture_assert_int_equal(test_context->tctx, + decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used), 0, + "decode_AS_REP failed"); + torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); + torture_assert_int_equal(test_context->tctx, error.pvno, 5, "Got wrong error.pvno"); + torture_assert_int_equal(test_context->tctx, error.error_code, KRB5KDC_ERR_PREAUTH_REQUIRED - KRB5KDC_ERR_NONE, + "Got wrong error.error_code"); + free_KRB_ERROR(&error); + } else if (test_context->packet_count == 1) { + torture_assert_int_equal(test_context->tctx, + decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used), 0, + "decode_AS_REP failed"); + torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch"); + torture_assert_int_equal(test_context->tctx, error.pvno, 5, "Got wrong error.pvno"); + torture_assert_int_equal(test_context->tctx, error.error_code, KRB5KDC_ERR_PREAUTH_FAILED - KRB5KDC_ERR_NONE, + "Got wrong error.error_code"); + free_KRB_ERROR(&error); + } + torture_assert(test_context->tctx, test_context->packet_count < 2, "too many packets"); + free_AS_REQ(&test_context->as_req); + break; + } + return true; +} + +static krb5_error_code smb_krb5_send_and_recv_func_override(krb5_context context, + void *data, /* struct torture_krb5_context */ + krb5_krbhst_info *hi, + time_t timeout, + const krb5_data *send_buf, + krb5_data *recv_buf) +{ + krb5_error_code k5ret; + bool ok; + + 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); + if (ok == false) { + return EINVAL; + } + + k5ret = smb_krb5_send_and_recv_func_forced(context, test_context->server, + hi, timeout, send_buf, recv_buf); + + ok = torture_krb5_post_recv_test(test_context, recv_buf); + if (ok == false) { + return EINVAL; + } + + test_context->packet_count++; + + return k5ret; +} + +static int test_context_destructor(struct torture_krb5_context *test_context) +{ + freeaddrinfo(test_context->server); + return 0; +} + + static bool torture_krb5_init_context(struct torture_context *tctx, + enum torture_krb5_test test, struct smb_krb5_context **smb_krb5_context) { const char *host = torture_setting_string(tctx, "host", NULL); krb5_error_code k5ret; bool ok; - struct addrinfo *server; + + struct torture_krb5_context *test_context = talloc_zero(tctx, struct torture_krb5_context); + torture_assert(tctx, test_context != NULL, "Failed to allocate"); + + test_context->test = test; + test_context->tctx = tctx; k5ret = smb_krb5_init_context(tctx, tctx->lp_ctx, smb_krb5_context); torture_assert_int_equal(tctx, k5ret, 0, "smb_krb5_init_context failed"); - ok = interpret_string_addr_internal(&server, host, AI_NUMERICHOST); + ok = interpret_string_addr_internal(&test_context->server, host, AI_NUMERICHOST); torture_assert(tctx, ok, "Failed to parse target server"); - set_sockaddr_port(server->ai_addr, 88); + talloc_set_destructor(test_context, test_context_destructor); + + set_sockaddr_port(test_context->server->ai_addr, 88); k5ret = krb5_set_send_to_kdc_func((*smb_krb5_context)->krb5_context, - smb_krb5_send_and_recv_func_forced, - server); + smb_krb5_send_and_recv_func_override, + test_context); torture_assert_int_equal(tctx, k5ret, 0, "krb5_set_send_to_kdc_func failed"); return true; } static bool torture_krb5_as_req_creds(struct torture_context *tctx, - struct cli_credentials *credentials) + struct cli_credentials *credentials, + enum torture_krb5_test test) { krb5_error_code k5ret; bool ok; @@ -65,16 +204,24 @@ static bool torture_krb5_as_req_creds(struct torture_context *tctx, const char *error_string; const char *password = cli_credentials_get_password(credentials); - ok = torture_krb5_init_context(tctx, &smb_krb5_context); + ok = torture_krb5_init_context(tctx, test, &smb_krb5_context); torture_assert(tctx, ok, "torture_krb5_init_context failed"); k5ret = principal_from_credentials(tctx, credentials, smb_krb5_context, &principal, &obtained, &error_string); torture_assert_int_equal(tctx, k5ret, 0, error_string); + if (test == TORTURE_KRB5_TEST_BREAK_PW) { + password = "NOT the password"; + } k5ret = krb5_get_init_creds_password(smb_krb5_context->krb5_context, &my_creds, principal, password, NULL, NULL, 0, NULL, NULL); - torture_assert_int_equal(tctx, k5ret, 0, "krb5_get_init_creds_password failed"); + if (test == TORTURE_KRB5_TEST_BREAK_PW) { + torture_assert_int_equal(tctx, k5ret, KRB5KDC_ERR_PREAUTH_FAILED, "krb5_get_init_creds_password should have failed"); + return true; + } else { + torture_assert_int_equal(tctx, k5ret, 0, "krb5_get_init_creds_password failed"); + } torture_assert_int_equal(tctx, krb5_principal_get_type(smb_krb5_context->krb5_context, @@ -103,7 +250,12 @@ static bool torture_krb5_as_req_creds(struct torture_context *tctx, static bool torture_krb5_as_req_cmdline(struct torture_context *tctx) { - return torture_krb5_as_req_creds(tctx, cmdline_credentials); + return torture_krb5_as_req_creds(tctx, cmdline_credentials, TORTURE_KRB5_TEST_PLAIN); +} + +static bool torture_krb5_as_req_break_pw(struct torture_context *tctx) +{ + return torture_krb5_as_req_creds(tctx, cmdline_credentials, TORTURE_KRB5_TEST_BREAK_PW); } NTSTATUS torture_krb5_init(void); @@ -117,6 +269,9 @@ NTSTATUS torture_krb5_init(void) torture_suite_add_simple_test(kdc_suite, "as-req-cmdline", torture_krb5_as_req_cmdline); + torture_suite_add_simple_test(kdc_suite, "as-req-break-pw", + torture_krb5_as_req_break_pw); + torture_suite_add_suite(suite, kdc_suite); torture_register_suite(suite); |