summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
Diffstat (limited to 'source4')
-rw-r--r--source4/auth/gensec/gensec_krb5.c4
-rw-r--r--source4/auth/kerberos/kerberos.h27
-rw-r--r--source4/auth/kerberos/kerberos_pac.c324
-rw-r--r--source4/torture/auth/pac.c23
4 files changed, 28 insertions, 350 deletions
diff --git a/source4/auth/gensec/gensec_krb5.c b/source4/auth/gensec/gensec_krb5.c
index e6497bb905..c3e3b98f74 100644
--- a/source4/auth/gensec/gensec_krb5.c
+++ b/source4/auth/gensec/gensec_krb5.c
@@ -697,11 +697,11 @@ static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security
/* decode and verify the pac */
nt_status = kerberos_pac_logon_info(gensec_krb5_state,
- &logon_info, pac,
+ pac,
gensec_krb5_state->smb_krb5_context->krb5_context,
NULL, gensec_krb5_state->keyblock,
client_principal,
- gensec_krb5_state->ticket->ticket.authtime, NULL);
+ gensec_krb5_state->ticket->ticket.authtime, &logon_info);
if (!NT_STATUS_IS_OK(nt_status)) {
free(principal_string);
diff --git a/source4/auth/kerberos/kerberos.h b/source4/auth/kerberos/kerberos.h
index 3f021ad70a..c712569e5d 100644
--- a/source4/auth/kerberos/kerberos.h
+++ b/source4/auth/kerberos/kerberos.h
@@ -25,6 +25,7 @@
#include "auth/kerberos/krb5_init_context.h"
#include "librpc/gen_ndr/krb5pac.h"
+#include "libcli/auth/krb5_wrap.h"
struct auth_user_info_dc;
struct cli_credentials;
@@ -112,24 +113,14 @@ bool kerberos_compatible_enctypes(krb5_context context, krb5_enctype enctype1, k
void kerberos_free_data_contents(krb5_context context, krb5_data *pdata);
krb5_error_code smb_krb5_kt_free_entry(krb5_context context, krb5_keytab_entry *kt_entry);
char *smb_get_krb5_error_message(krb5_context context, krb5_error_code code, TALLOC_CTX *mem_ctx);
-NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
- struct PAC_DATA **pac_data_out,
- DATA_BLOB blob,
- krb5_context context,
- const krb5_keyblock *krbtgt_keyblock,
- const krb5_keyblock *service_keyblock,
- krb5_const_principal client_principal,
- time_t tgs_authtime,
- krb5_error_code *k5ret);
- NTSTATUS kerberos_pac_logon_info(TALLOC_CTX *mem_ctx,
- struct PAC_LOGON_INFO **logon_info,
- DATA_BLOB blob,
- krb5_context context,
- const krb5_keyblock *krbtgt_keyblock,
- const krb5_keyblock *service_keyblock,
- krb5_const_principal client_principal,
- time_t tgs_authtime,
- krb5_error_code *k5ret);
+NTSTATUS kerberos_pac_logon_info(TALLOC_CTX *mem_ctx,
+ DATA_BLOB blob,
+ krb5_context context,
+ const krb5_keyblock *krbtgt_keyblock,
+ const krb5_keyblock *service_keyblock,
+ krb5_const_principal client_principal,
+ time_t tgs_authtime,
+ struct PAC_LOGON_INFO **logon_info);
krb5_error_code kerberos_encode_pac(TALLOC_CTX *mem_ctx,
struct PAC_DATA *pac_data,
krb5_context context,
diff --git a/source4/auth/kerberos/kerberos_pac.c b/source4/auth/kerberos/kerberos_pac.c
index 07f936ad2e..5bc80c9a58 100644
--- a/source4/auth/kerberos/kerberos_pac.c
+++ b/source4/auth/kerberos/kerberos_pac.c
@@ -31,334 +31,26 @@
#include <ldb.h>
#include "auth/auth_sam_reply.h"
-krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx,
- DATA_BLOB pac_data,
- struct PAC_SIGNATURE_DATA *sig,
- krb5_context context,
- const krb5_keyblock *keyblock)
-{
- krb5_error_code ret;
- krb5_crypto crypto;
- Checksum cksum;
-
- cksum.cksumtype = (CKSUMTYPE)sig->type;
- cksum.checksum.length = sig->signature.length;
- cksum.checksum.data = sig->signature.data;
-
- ret = krb5_crypto_init(context,
- keyblock,
- 0,
- &crypto);
- if (ret) {
- DEBUG(0,("krb5_crypto_init() failed: %s\n",
- smb_get_krb5_error_message(context, ret, mem_ctx)));
- return ret;
- }
- ret = krb5_verify_checksum(context,
- crypto,
- KRB5_KU_OTHER_CKSUM,
- pac_data.data,
- pac_data.length,
- &cksum);
- krb5_crypto_destroy(context, crypto);
-
- return ret;
-}
-
- NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
- struct PAC_DATA **pac_data_out,
- DATA_BLOB blob,
- krb5_context context,
- const krb5_keyblock *krbtgt_keyblock,
- const krb5_keyblock *service_keyblock,
- krb5_const_principal client_principal,
- time_t tgs_authtime,
- krb5_error_code *k5ret)
-{
- krb5_error_code ret;
- NTSTATUS status;
- enum ndr_err_code ndr_err;
- struct PAC_SIGNATURE_DATA *srv_sig_ptr = NULL;
- struct PAC_SIGNATURE_DATA *kdc_sig_ptr = NULL;
- struct PAC_SIGNATURE_DATA *srv_sig_wipe = NULL;
- struct PAC_SIGNATURE_DATA *kdc_sig_wipe = NULL;
- struct PAC_LOGON_INFO *logon_info = NULL;
- struct PAC_LOGON_NAME *logon_name = NULL;
- struct PAC_DATA *pac_data;
- struct PAC_DATA_RAW *pac_data_raw;
-
- DATA_BLOB *srv_sig_blob = NULL;
- DATA_BLOB *kdc_sig_blob = NULL;
-
- DATA_BLOB modified_pac_blob;
- NTTIME tgs_authtime_nttime;
- krb5_principal client_principal_pac;
- uint32_t i;
-
- krb5_clear_error_message(context);
-
- if (k5ret) {
- *k5ret = KRB5_PARSE_MALFORMED;
- }
-
- pac_data = talloc(mem_ctx, struct PAC_DATA);
- pac_data_raw = talloc(mem_ctx, struct PAC_DATA_RAW);
- kdc_sig_wipe = talloc(mem_ctx, struct PAC_SIGNATURE_DATA);
- srv_sig_wipe = talloc(mem_ctx, struct PAC_SIGNATURE_DATA);
- if (!pac_data_raw || !pac_data || !kdc_sig_wipe || !srv_sig_wipe) {
- if (k5ret) {
- *k5ret = ENOMEM;
- }
- return NT_STATUS_NO_MEMORY;
- }
-
- ndr_err = ndr_pull_struct_blob(&blob, pac_data,
- pac_data, (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- status = ndr_map_error2ntstatus(ndr_err);
- DEBUG(0,("can't parse the PAC: %s\n",
- nt_errstr(status)));
- return status;
- }
-
- if (pac_data->num_buffers < 4) {
- /* we need logon_ingo, service_key and kdc_key */
- DEBUG(0,("less than 4 PAC buffers\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- ndr_err = ndr_pull_struct_blob(&blob, pac_data_raw,
- pac_data_raw,
- (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA_RAW);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- status = ndr_map_error2ntstatus(ndr_err);
- DEBUG(0,("can't parse the PAC: %s\n",
- nt_errstr(status)));
- return status;
- }
-
- if (pac_data_raw->num_buffers < 4) {
- /* we need logon_ingo, service_key and kdc_key */
- DEBUG(0,("less than 4 PAC buffers\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- if (pac_data->num_buffers != pac_data_raw->num_buffers) {
- /* we need logon_ingo, service_key and kdc_key */
- DEBUG(0,("misparse! PAC_DATA has %d buffers while PAC_DATA_RAW has %d\n",
- pac_data->num_buffers, pac_data_raw->num_buffers));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- for (i=0; i < pac_data->num_buffers; i++) {
- if (pac_data->buffers[i].type != pac_data_raw->buffers[i].type) {
- DEBUG(0,("misparse! PAC_DATA buffer %d has type %d while PAC_DATA_RAW has %d\n",
- i, pac_data->buffers[i].type, pac_data->buffers[i].type));
- return NT_STATUS_INVALID_PARAMETER;
- }
- switch (pac_data->buffers[i].type) {
- case PAC_TYPE_LOGON_INFO:
- if (!pac_data->buffers[i].info) {
- break;
- }
- logon_info = pac_data->buffers[i].info->logon_info.info;
- break;
- case PAC_TYPE_SRV_CHECKSUM:
- if (!pac_data->buffers[i].info) {
- break;
- }
- srv_sig_ptr = &pac_data->buffers[i].info->srv_cksum;
- srv_sig_blob = &pac_data_raw->buffers[i].info->remaining;
- break;
- case PAC_TYPE_KDC_CHECKSUM:
- if (!pac_data->buffers[i].info) {
- break;
- }
- kdc_sig_ptr = &pac_data->buffers[i].info->kdc_cksum;
- kdc_sig_blob = &pac_data_raw->buffers[i].info->remaining;
- break;
- case PAC_TYPE_LOGON_NAME:
- logon_name = &pac_data->buffers[i].info->logon_name;
- break;
- default:
- break;
- }
- }
-
- if (!logon_info) {
- DEBUG(0,("PAC no logon_info\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- if (!logon_name) {
- DEBUG(0,("PAC no logon_name\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- if (!srv_sig_ptr || !srv_sig_blob) {
- DEBUG(0,("PAC no srv_key\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- if (!kdc_sig_ptr || !kdc_sig_blob) {
- DEBUG(0,("PAC no kdc_key\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- /* Find and zero out the signatures, as required by the signing algorithm */
-
- /* We find the data blobs above, now we parse them to get at the exact portion we should zero */
- ndr_err = ndr_pull_struct_blob(kdc_sig_blob, kdc_sig_wipe,
- kdc_sig_wipe,
- (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- status = ndr_map_error2ntstatus(ndr_err);
- DEBUG(0,("can't parse the KDC signature: %s\n",
- nt_errstr(status)));
- return status;
- }
-
- ndr_err = ndr_pull_struct_blob(srv_sig_blob, srv_sig_wipe,
- srv_sig_wipe,
- (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- status = ndr_map_error2ntstatus(ndr_err);
- DEBUG(0,("can't parse the SRV signature: %s\n",
- nt_errstr(status)));
- return status;
- }
-
- /* Now zero the decoded structure */
- memset(kdc_sig_wipe->signature.data, '\0', kdc_sig_wipe->signature.length);
- memset(srv_sig_wipe->signature.data, '\0', srv_sig_wipe->signature.length);
-
- /* and reencode, back into the same place it came from */
- ndr_err = ndr_push_struct_blob(kdc_sig_blob, pac_data_raw,
- kdc_sig_wipe,
- (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- status = ndr_map_error2ntstatus(ndr_err);
- DEBUG(0,("can't repack the KDC signature: %s\n",
- nt_errstr(status)));
- return status;
- }
- ndr_err = ndr_push_struct_blob(srv_sig_blob, pac_data_raw,
- srv_sig_wipe,
- (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- status = ndr_map_error2ntstatus(ndr_err);
- DEBUG(0,("can't repack the SRV signature: %s\n",
- nt_errstr(status)));
- return status;
- }
-
- /* push out the whole structure, but now with zero'ed signatures */
- ndr_err = ndr_push_struct_blob(&modified_pac_blob, pac_data_raw,
- pac_data_raw,
- (ndr_push_flags_fn_t)ndr_push_PAC_DATA_RAW);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- status = ndr_map_error2ntstatus(ndr_err);
- DEBUG(0,("can't repack the RAW PAC: %s\n",
- nt_errstr(status)));
- return status;
- }
-
- /* verify by service_key */
- ret = check_pac_checksum(mem_ctx,
- modified_pac_blob, srv_sig_ptr,
- context,
- service_keyblock);
- if (ret) {
- DEBUG(1, ("PAC Decode: Failed to verify the service signature: %s\n",
- smb_get_krb5_error_message(context, ret, mem_ctx)));
- if (k5ret) {
- *k5ret = ret;
- }
- return NT_STATUS_ACCESS_DENIED;
- }
-
- if (krbtgt_keyblock) {
- ret = check_pac_checksum(mem_ctx,
- srv_sig_ptr->signature, kdc_sig_ptr,
- context, krbtgt_keyblock);
- if (ret) {
- DEBUG(1, ("PAC Decode: Failed to verify the KDC signature: %s\n",
- smb_get_krb5_error_message(context, ret, mem_ctx)));
- if (k5ret) {
- *k5ret = ret;
- }
- return NT_STATUS_ACCESS_DENIED;
- }
- }
-
- /* Convert to NT time, so as not to loose accuracy in comparison */
- unix_to_nt_time(&tgs_authtime_nttime, tgs_authtime);
-
- if (tgs_authtime_nttime != logon_name->logon_time) {
- DEBUG(2, ("PAC Decode: Logon time mismatch between ticket and PAC!\n"));
- DEBUG(2, ("PAC Decode: PAC: %s\n", nt_time_string(mem_ctx, logon_name->logon_time)));
- DEBUG(2, ("PAC Decode: Ticket: %s\n", nt_time_string(mem_ctx, tgs_authtime_nttime)));
- return NT_STATUS_ACCESS_DENIED;
- }
-
- ret = krb5_parse_name_flags(context, logon_name->account_name, KRB5_PRINCIPAL_PARSE_NO_REALM,
- &client_principal_pac);
- if (ret) {
- DEBUG(2, ("Could not parse name from incoming PAC: [%s]: %s\n",
- logon_name->account_name,
- smb_get_krb5_error_message(context, ret, mem_ctx)));
- if (k5ret) {
- *k5ret = ret;
- }
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- if (!krb5_principal_compare_any_realm(context, client_principal, client_principal_pac)) {
- DEBUG(2, ("Name in PAC [%s] does not match principal name in ticket\n",
- logon_name->account_name));
- krb5_free_principal(context, client_principal_pac);
- return NT_STATUS_ACCESS_DENIED;
- }
-
- krb5_free_principal(context, client_principal_pac);
-
-#if 0
- if (strcasecmp(logon_info->info3.base.account_name.string,
- "Administrator")== 0) {
- file_save("tmp_pac_data-admin.dat",blob.data,blob.length);
- }
-#endif
-
- DEBUG(3,("Found account name from PAC: %s [%s]\n",
- logon_info->info3.base.account_name.string,
- logon_info->info3.base.full_name.string));
- *pac_data_out = pac_data;
-
- return NT_STATUS_OK;
-}
-
_PUBLIC_ NTSTATUS kerberos_pac_logon_info(TALLOC_CTX *mem_ctx,
- struct PAC_LOGON_INFO **logon_info,
- DATA_BLOB blob,
- krb5_context context,
- const krb5_keyblock *krbtgt_keyblock,
- const krb5_keyblock *service_keyblock,
- krb5_const_principal client_principal,
- time_t tgs_authtime,
- krb5_error_code *k5ret)
+ DATA_BLOB blob,
+ krb5_context context,
+ const krb5_keyblock *krbtgt_keyblock,
+ const krb5_keyblock *service_keyblock,
+ krb5_const_principal client_principal,
+ time_t tgs_authtime,
+ struct PAC_LOGON_INFO **logon_info)
{
NTSTATUS nt_status;
struct PAC_DATA *pac_data;
int i;
nt_status = kerberos_decode_pac(mem_ctx,
- &pac_data,
blob,
context,
krbtgt_keyblock,
service_keyblock,
client_principal,
tgs_authtime,
- k5ret);
+ &pac_data);
if (!NT_STATUS_IS_OK(nt_status)) {
return nt_status;
}
diff --git a/source4/torture/auth/pac.c b/source4/torture/auth/pac.c
index 4a306131cc..f09e039964 100644
--- a/source4/torture/auth/pac.c
+++ b/source4/torture/auth/pac.c
@@ -142,13 +142,13 @@ static bool torture_pac_self_check(struct torture_context *tctx)
/* Now check that we can read it back (using full decode and validate) */
nt_status = kerberos_decode_pac(mem_ctx,
- &pac_data,
tmp_blob,
smb_krb5_context->krb5_context,
&krbtgt_keyblock,
&server_keyblock,
client_principal,
- logon_time, NULL);
+ logon_time,
+ &pac_data);
if (!NT_STATUS_IS_OK(nt_status)) {
krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
@@ -189,14 +189,13 @@ static bool torture_pac_self_check(struct torture_context *tctx)
/* Now check that we can read it back (yet again) */
nt_status = kerberos_pac_logon_info(mem_ctx,
- &logon_info,
tmp_blob,
smb_krb5_context->krb5_context,
&krbtgt_keyblock,
&server_keyblock,
client_principal,
logon_time,
- NULL);
+ &logon_info);
if (!NT_STATUS_IS_OK(nt_status)) {
krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
@@ -408,12 +407,11 @@ static bool torture_pac_saved_check(struct torture_context *tctx)
/* Decode and verify the signaure on the PAC */
nt_status = kerberos_decode_pac(mem_ctx,
- &pac_data,
tmp_blob,
smb_krb5_context->krb5_context,
krbtgt_keyblock_p,
&server_keyblock,
- client_principal, authtime, NULL);
+ client_principal, authtime, &pac_data);
if (!NT_STATUS_IS_OK(nt_status)) {
krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
krbtgt_keyblock_p);
@@ -466,12 +464,11 @@ static bool torture_pac_saved_check(struct torture_context *tctx)
/* Parse the PAC again, for the logon info this time (using Samba4's parsing) */
nt_status = kerberos_pac_logon_info(mem_ctx,
- &logon_info,
tmp_blob,
smb_krb5_context->krb5_context,
krbtgt_keyblock_p,
&server_keyblock,
- client_principal, authtime, NULL);
+ client_principal, authtime, &logon_info);
if (!NT_STATUS_IS_OK(nt_status)) {
krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
@@ -654,13 +651,12 @@ static bool torture_pac_saved_check(struct torture_context *tctx)
/* Break the auth time, to ensure we check this vital detail (not setting this caused all the pain in the first place... */
nt_status = kerberos_decode_pac(mem_ctx,
- &pac_data,
tmp_blob,
smb_krb5_context->krb5_context,
krbtgt_keyblock_p,
&server_keyblock,
client_principal,
- authtime + 1, NULL);
+ authtime + 1, &pac_data);
if (NT_STATUS_IS_OK(nt_status)) {
krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
@@ -691,13 +687,12 @@ static bool torture_pac_saved_check(struct torture_context *tctx)
}
nt_status = kerberos_decode_pac(mem_ctx,
- &pac_data,
tmp_blob,
smb_krb5_context->krb5_context,
krbtgt_keyblock_p,
&server_keyblock,
client_principal,
- authtime, NULL);
+ authtime, &pac_data);
if (NT_STATUS_IS_OK(nt_status)) {
krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
krbtgt_keyblock_p);
@@ -710,13 +705,13 @@ static bool torture_pac_saved_check(struct torture_context *tctx)
tmp_blob.data[tmp_blob.length - 2]++;
nt_status = kerberos_decode_pac(mem_ctx,
- &pac_data,
tmp_blob,
smb_krb5_context->krb5_context,
krbtgt_keyblock_p,
&server_keyblock,
client_principal,
- authtime, NULL);
+ authtime,
+ &pac_data);
if (NT_STATUS_IS_OK(nt_status)) {
krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
krbtgt_keyblock_p);