summaryrefslogtreecommitdiff
path: root/source4/auth/kerberos/kerberos_pac.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/auth/kerberos/kerberos_pac.c')
-rw-r--r--source4/auth/kerberos/kerberos_pac.c96
1 files changed, 66 insertions, 30 deletions
diff --git a/source4/auth/kerberos/kerberos_pac.c b/source4/auth/kerberos/kerberos_pac.c
index b26a25eac1..3294699070 100644
--- a/source4/auth/kerberos/kerberos_pac.c
+++ b/source4/auth/kerberos/kerberos_pac.c
@@ -33,11 +33,11 @@
#include "librpc/gen_ndr/ndr_krb5pac.h"
#include "auth/auth.h"
-static NTSTATUS check_pac_checksum(TALLOC_CTX *mem_ctx,
- DATA_BLOB pac_data,
- struct PAC_SIGNATURE_DATA *sig,
- krb5_context context,
- krb5_keyblock *keyblock)
+static krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx,
+ DATA_BLOB pac_data,
+ struct PAC_SIGNATURE_DATA *sig,
+ krb5_context context,
+ krb5_keyblock *keyblock)
{
krb5_error_code ret;
krb5_crypto crypto;
@@ -55,7 +55,7 @@ static NTSTATUS check_pac_checksum(TALLOC_CTX *mem_ctx,
if (ret) {
DEBUG(0,("krb5_crypto_init() failed: %s\n",
smb_get_krb5_error_message(context, ret, mem_ctx)));
- return NT_STATUS_FOOBAR;
+ return ret;
}
ret = krb5_verify_checksum(context,
crypto,
@@ -63,18 +63,9 @@ static NTSTATUS check_pac_checksum(TALLOC_CTX *mem_ctx,
pac_data.data,
pac_data.length,
&cksum);
- if (ret) {
- DEBUG(2, ("PAC Verification failed: %s\n",
- smb_get_krb5_error_message(context, ret, mem_ctx)));
- }
-
krb5_crypto_destroy(context, crypto);
- if (ret) {
- return NT_STATUS_ACCESS_DENIED;
- }
-
- return NT_STATUS_OK;
+ return ret;
}
NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
@@ -82,17 +73,23 @@ static NTSTATUS check_pac_checksum(TALLOC_CTX *mem_ctx,
DATA_BLOB blob,
krb5_context context,
krb5_keyblock *krbtgt_keyblock,
- krb5_keyblock *service_keyblock)
+ krb5_keyblock *service_keyblock,
+ krb5_const_principal client_principal,
+ time_t tgs_authtime)
{
+ krb5_error_code ret;
NTSTATUS status;
struct PAC_SIGNATURE_DATA srv_sig;
struct PAC_SIGNATURE_DATA *srv_sig_ptr = NULL;
struct PAC_SIGNATURE_DATA kdc_sig;
struct PAC_SIGNATURE_DATA *kdc_sig_ptr = NULL;
struct PAC_LOGON_INFO *logon_info = NULL;
+ struct PAC_LOGON_NAME *logon_name = NULL;
struct PAC_DATA *pac_data;
DATA_BLOB modified_pac_blob = data_blob_talloc(mem_ctx, blob.data, blob.length);
+ NTTIME tgs_authtime_nttime;
+ krb5_principal client_principal_pac;
int i;
pac_data = talloc(mem_ctx, struct PAC_DATA);
@@ -136,6 +133,7 @@ static NTSTATUS check_pac_checksum(TALLOC_CTX *mem_ctx,
kdc_sig = pac_data->buffers[i].info->kdc_cksum;
break;
case PAC_TYPE_LOGON_NAME:
+ logon_name = &pac_data->buffers[i].info->logon_name;
break;
default:
break;
@@ -163,28 +161,54 @@ static NTSTATUS check_pac_checksum(TALLOC_CTX *mem_ctx,
'\0', 16);
/* verify by service_key */
- status = check_pac_checksum(mem_ctx,
+ ret = check_pac_checksum(mem_ctx,
modified_pac_blob, &srv_sig,
context,
service_keyblock);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("PAC Decode: Failed to verify the service signature\n"));
- return status;
+ if (ret) {
+ DEBUG(1, ("PAC Decode: Failed to verify the service signature: %s\n",
+ smb_get_krb5_error_message(context, ret, mem_ctx)));
+ return NT_STATUS_ACCESS_DENIED;
}
if (krbtgt_keyblock) {
DATA_BLOB service_checksum_blob
= data_blob_const(srv_sig_ptr->signature, sizeof(srv_sig_ptr->signature));
- status = check_pac_checksum(mem_ctx,
+ ret = check_pac_checksum(mem_ctx,
service_checksum_blob, &kdc_sig,
context, krbtgt_keyblock);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("PAC Decode: Failed to verify the krbtgt signature\n"));
- return status;
+ if (ret) {
+ DEBUG(1, ("PAC Decode: Failed to verify the KDC signature: %s\n",
+ smb_get_krb5_error_message(context, ret, mem_ctx)));
+ 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_norealm(context, logon_name->account_name, &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)));
+ 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));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
#if 0
if (strcasecmp(logon_info->info3.base.account_name.string,
"Administrator")== 0) {
@@ -205,7 +229,9 @@ static NTSTATUS check_pac_checksum(TALLOC_CTX *mem_ctx,
DATA_BLOB blob,
krb5_context context,
krb5_keyblock *krbtgt_keyblock,
- krb5_keyblock *service_keyblock)
+ krb5_keyblock *service_keyblock,
+ krb5_const_principal client_principal,
+ time_t tgs_authtime)
{
NTSTATUS nt_status;
struct PAC_DATA *pac_data;
@@ -215,7 +241,9 @@ static NTSTATUS check_pac_checksum(TALLOC_CTX *mem_ctx,
blob,
context,
krbtgt_keyblock,
- service_keyblock);
+ service_keyblock,
+ client_principal,
+ tgs_authtime);
if (!NT_STATUS_IS_OK(nt_status)) {
return nt_status;
}
@@ -275,6 +303,7 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
if (cksum.checksum.length == sizeof(sig->signature)) {
memcpy(sig->signature, cksum.checksum.data, sizeof(sig->signature));
}
+ free_Checksum(&cksum);
return 0;
}
@@ -385,6 +414,7 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
krb5_context context,
krb5_keyblock *krbtgt_keyblock,
krb5_keyblock *service_keyblock,
+ krb5_principal client_principal,
time_t tgs_authtime,
DATA_BLOB *pac)
{
@@ -400,6 +430,8 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
union PAC_INFO *u_KDC_CHECKSUM;
union PAC_INFO *u_SRV_CHECKSUM;
+ char *name;
+
enum {
PAC_BUF_LOGON_INFO = 0,
PAC_BUF_LOGON_NAME = 1,
@@ -478,11 +510,15 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
LOGON_INFO->info3 = *sam3;
LOGON_INFO->info3.base.last_logon = timeval_to_nttime(&tv);
- LOGON_NAME->account_name = server_info->account_name;
-
+ ret = krb5_unparse_name_norealm(context, client_principal, &name);
+ if (ret) {
+ return ret;
+ }
+ LOGON_NAME->account_name = talloc_strdup(LOGON_NAME, name);
+ free(name);
/*
this logon_time field is absolutely critical. This is what
- caused all our pac troubles :-)
+ caused all our PAC troubles :-)
*/
unix_to_nt_time(&LOGON_NAME->logon_time, tgs_authtime);