The Samba-Bugzilla – Attachment 11340 Details for
Bug 11441
Smart Card Logins break client-side DPAPI (among others)
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Implement the actual PAC_CREDENTIAL_* formatting/serialization in pac-glue and use it.
0004-Implement-actual-PAC_CREDENTIAL_INFO-generation-and-.patch (text/plain), 14.80 KB, created by
Heiko Wundram
on 2015-08-16 19:53:48 UTC
(
hide
)
Description:
Implement the actual PAC_CREDENTIAL_* formatting/serialization in pac-glue and use it.
Filename:
MIME Type:
Creator:
Heiko Wundram
Created:
2015-08-16 19:53:48 UTC
Size:
14.80 KB
patch
obsolete
>From d4a292afb659ac6a78a9455593215e861201037a Mon Sep 17 00:00:00 2001 >From: root <root@vpn.gehrkens.it> >Date: Sun, 16 Aug 2015 21:36:21 +0200 >Subject: [PATCH 4/4] Implement actual PAC_CREDENTIAL_INFO generation and > attachment. > >Implements the actual PAC_CREDENTIAL_INFO generation and attachment for the >PAC glue functions that take BLOBs retrieved from the auth_user_info_dc >structure and formats them accordingly for wire transfer. >--- > source4/kdc/mit_samba.c | 22 ++++- > source4/kdc/mit_samba_interface.h | 3 +- > source4/kdc/pac-glue.c | 179 +++++++++++++++++++++++++++++++++++--- > source4/kdc/pac-glue.h | 10 ++- > source4/kdc/wdc-samba4.c | 12 +-- > 5 files changed, 203 insertions(+), 23 deletions(-) > >diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c >index f56e679..3f045ce 100644 >--- a/source4/kdc/mit_samba.c >+++ b/source4/kdc/mit_samba.c >@@ -188,12 +188,14 @@ static int mit_samba_get_nextkey(struct mit_samba_context *ctx, > return ret; > } > >-static int mit_samba_get_pac_data(struct mit_samba_context *ctx, >+static int mit_samba_get_pac_cred_data(struct mit_samba_context *ctx, > hdb_entry_ex *client, >- DATA_BLOB *data) >+ DATA_BLOB *data, >+ DATA_BLOB *cred) > { > TALLOC_CTX *tmp_ctx; > DATA_BLOB *pac_blob; >+ DATA_BLOB *cred_blob; > NTSTATUS nt_status; > > tmp_ctx = talloc_named(ctx, 0, "mit_samba_get_pac_data context"); >@@ -201,7 +203,8 @@ static int mit_samba_get_pac_data(struct mit_samba_context *ctx, > return ENOMEM; > } > >- nt_status = samba_kdc_get_pac_blob(tmp_ctx, client, &pac_blob); >+ nt_status = samba_kdc_get_pac_cred_blob(tmp_ctx, client, &pac_blob, >+ &cred_blob); > if (!NT_STATUS_IS_OK(nt_status)) { > talloc_free(tmp_ctx); > return EINVAL; >@@ -214,6 +217,17 @@ static int mit_samba_get_pac_data(struct mit_samba_context *ctx, > } > memcpy(data->data, pac_blob->data, pac_blob->length); > data->length = pac_blob->length; >+ >+ if (cred) { >+ cred->data = (uint8_t *)malloc(cred_blob->length); >+ if (!cred->data) { >+ free(cred->data); >+ talloc_free(tmp_ctx); >+ return ENOMEM; >+ } >+ memcpy(cred->data, cred_blob->data, cred_blob->length); >+ cred->length = cred_blob->length; >+ } > > talloc_free(tmp_ctx); > return 0; >@@ -358,7 +372,7 @@ struct mit_samba_function_table mit_samba_function_table = { > mit_samba_get_principal, > mit_samba_get_firstkey, > mit_samba_get_nextkey, >- mit_samba_get_pac_data, >+ mit_samba_get_pac_cred_data, > mit_samba_update_pac_data, > mit_samba_check_client_access, > mit_samba_check_s4u2proxy >diff --git a/source4/kdc/mit_samba_interface.h b/source4/kdc/mit_samba_interface.h >index b92f7bf..2a4e489 100644 >--- a/source4/kdc/mit_samba_interface.h >+++ b/source4/kdc/mit_samba_interface.h >@@ -48,7 +48,8 @@ struct mit_samba_function_table { > int (*get_nextkey)(struct mit_samba_context *, hdb_entry_ex **); > > /* windc */ >- int (*get_pac)(struct mit_samba_context *, hdb_entry_ex *, DATA_BLOB *); >+ int (*get_pac_cred)(struct mit_samba_context *, hdb_entry_ex *, DATA_BLOB *, >+ DATA_BLOB *); > int (*update_pac)(struct mit_samba_context *, hdb_entry_ex *, > DATA_BLOB *, DATA_BLOB *); > int (*client_access)(struct mit_samba_context *, >diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c >index cca74d8..d5a510b 100644 >--- a/source4/kdc/pac-glue.c >+++ b/source4/kdc/pac-glue.c >@@ -35,12 +35,15 @@ > #include "auth/kerberos/pac_utils.h" > > static >-NTSTATUS samba_get_logon_info_pac_blob(TALLOC_CTX *mem_ctx, >+NTSTATUS samba_get_logon_info_pac_cred_blob(TALLOC_CTX *mem_ctx, > struct auth_user_info_dc *info, >- DATA_BLOB *pac_data) >+ DATA_BLOB *pac_data, >+ DATA_BLOB *cred_data) > { > struct netr_SamInfo3 *info3; > union PAC_INFO pac_info; >+ struct PAC_CREDENTIAL_DATA pac_cred_data; >+ DATA_BLOB ntlm_secpkg; > enum ndr_err_code ndr_err; > NTSTATUS nt_status; > >@@ -69,20 +72,79 @@ NTSTATUS samba_get_logon_info_pac_blob(TALLOC_CTX *mem_ctx, > nt_errstr(nt_status))); > return nt_status; > } >+ >+ /* Only fill in credential data PAC buffer template when requested and >+ * passwords are actually available. >+ * This is required for PKINIT login to the domain so that the client >+ * can create the appropriate passwords for NTLM authentication without >+ * knowing them. */ >+ if (cred_data && info->passwords->flags) { >+ NDR_PRINT_DEBUG(PAC_CREDENTIAL_NTLM_SECPKG, info->passwords); >+ >+ ndr_err = ndr_push_struct_blob(&ntlm_secpkg, mem_ctx, info->passwords, >+ (ndr_push_flags_fn_t)ndr_push_PAC_CREDENTIAL_NTLM_SECPKG); >+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { >+ nt_status = ndr_map_error2ntstatus(ndr_err); >+ DEBUG(1, ("PAC (presig ntlm cred) push failed: %s\n", >+ nt_errstr(nt_status))); >+ return nt_status; >+ } >+ >+ ZERO_STRUCT(pac_cred_data); >+ >+ pac_cred_data.count = 1; >+ pac_cred_data.credentials = talloc_zero(mem_ctx, struct PAC_CREDENTIAL_SECPKG); >+ if (!pac_cred_data.credentials) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ >+ pac_cred_data.credentials->pkgname.string = talloc_strdup(mem_ctx, "NTLM"); >+ pac_cred_data.credentials->size = ntlm_secpkg.length; >+ pac_cred_data.credentials->data = ntlm_secpkg.data; >+ >+ NDR_PRINT_DEBUG(PAC_CREDENTIAL_DATA, &pac_cred_data); >+ >+ ndr_err = ndr_push_struct_blob(cred_data, mem_ctx, &pac_cred_data, >+ (ndr_push_flags_fn_t)ndr_push_PAC_CREDENTIAL_DATA); >+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { >+ nt_status = ndr_map_error2ntstatus(ndr_err); >+ DEBUG(1, ("PAC (presig cred pkg) push failed: %s\n", >+ nt_errstr(nt_status))); >+ return nt_status; >+ } >+ >+ DEBUG(2, ("Created credential BLOB (len %u) for user\n", >+ cred_data->length)); >+ } else if (cred_data) { >+ DEBUG(2, ("Requested credentials, but none available to send\n")); >+ *cred_data = data_blob(NULL, 0); >+ } > > return NT_STATUS_OK; > } > > krb5_error_code samba_make_krb5_pac(krb5_context context, >+ TALLOC_CTX *mem_ctx, > DATA_BLOB *pac_blob, >+ DATA_BLOB *cred_blob, > DATA_BLOB *deleg_blob, >- krb5_pac *pac) >+ krb5_pac *pac, >+ const krb5_keyblock *pkreplykey) > { > krb5_data pac_data; >+ krb5_crypto cred_crypto; >+ krb5_enctype cred_enctype; >+ krb5_data cred_crypt_data; >+ struct PAC_CREDENTIAL_INFO pac_cred_info; >+ DATA_BLOB cred_info_blob; >+ krb5_data cred_data; > krb5_data deleg_data; > krb5_error_code ret; >+ const char *krb5err; >+ enum ndr_err_code ndr_err; >+ NTSTATUS nt_status; > >- /* The user account may be set not to want the PAC */ >+ /* The user account may be set not to want the PAC */ > if (!pac_blob) { > return 0; > } >@@ -91,6 +153,73 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, > if (ret != 0) { > return ret; > } >+ >+ /* Only process credentials blob in case we have been passed a pkreplykey >+ * which allows the credentials blob to be encrypted. This does not need >+ * a data copy, as we encrypt the buffer anyway. */ >+ ZERO_STRUCT(cred_data); >+ if (cred_blob && cred_blob->length && pkreplykey) { >+ ret = krb5_crypto_init(context, pkreplykey, ETYPE_NULL, &cred_crypto); >+ if (ret != 0) { >+ krb5err = krb5_get_error_message(context, ret); >+ DEBUG(1, ("Failed initializing cred data crypto: %s\n", krb5err)); >+ krb5_free_error_message(context, krb5err); >+ krb5_data_free(&pac_data); >+ return ret; >+ } >+ >+ ret = krb5_crypto_getenctype(context, cred_crypto, &cred_enctype); >+ if (ret != 0) { >+ DEBUG(1, ("Failed getting crypto type for key\n")); >+ krb5_data_free(&pac_data); >+ krb5_crypto_destroy(context, cred_crypto); >+ return ret; >+ } >+ >+ ret = krb5_encrypt(context, cred_crypto, KRB5_KU_OTHER_ENCRYPTED, >+ cred_blob->data, cred_blob->length, &cred_crypt_data); >+ krb5_crypto_destroy(context, cred_crypto); >+ if (ret != 0) { >+ krb5err = krb5_get_error_message(context, ret); >+ DEBUG(1, ("Failed crypt of cred data: %s\n", krb5err)); >+ krb5_free_error_message(context, krb5err); >+ krb5_data_free(&pac_data); >+ return ret; >+ } >+ >+ ZERO_STRUCT(pac_cred_info); >+ >+ pac_cred_info.enctype = cred_enctype; >+ pac_cred_info.data.length = cred_crypt_data.length; >+ pac_cred_info.data.data = (uint8_t *)cred_crypt_data.data; >+ >+ NDR_PRINT_DEBUG(PAC_CREDENTIAL_INFO, &pac_cred_info); >+ >+ ndr_err = ndr_push_struct_blob(&cred_info_blob, mem_ctx, &pac_cred_info, >+ (ndr_push_flags_fn_t)ndr_push_PAC_CREDENTIAL_INFO); >+ krb5_data_free(&cred_crypt_data); >+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { >+ nt_status = ndr_map_error2ntstatus(ndr_err); >+ DEBUG(1, ("PAC (wrapped cred info) push failed: %s\n", >+ nt_errstr(nt_status))); >+ krb5_data_free(&pac_data); >+ return KRB5KDC_ERR_SVC_UNAVAILABLE; >+ } >+ >+ DEBUG(2, ("Encrypted credential BLOB (len %u) with alg %d\n", >+ cred_info_blob.length, pac_cred_info.enctype)); >+ >+ ret = krb5_data_copy(&cred_data, >+ cred_info_blob.data, >+ cred_info_blob.length); >+ if (ret != 0) { >+ krb5_data_free(&pac_data); >+ return ret; >+ } >+ } else if (cred_blob && cred_blob->length) >+ DEBUG(2, ("Have credentials BLOB but no reply key, not adding it\n")); >+ else if (pkreplykey) >+ DEBUG(1, ("Have PKINIT reply key but no credentials blob to add\n")); > > ZERO_STRUCT(deleg_data); > if (deleg_blob) { >@@ -99,6 +228,7 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, > deleg_blob->length); > if (ret != 0) { > krb5_data_free(&pac_data); >+ krb5_data_free(&cred_data); > return ret; > } > } >@@ -106,6 +236,7 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, > ret = krb5_pac_init(context, pac); > if (ret != 0) { > krb5_data_free(&pac_data); >+ krb5_data_free(&cred_data); > krb5_data_free(&deleg_data); > return ret; > } >@@ -113,9 +244,21 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, > ret = krb5_pac_add_buffer(context, *pac, PAC_TYPE_LOGON_INFO, &pac_data); > krb5_data_free(&pac_data); > if (ret != 0) { >+ krb5_data_free(&cred_data); > krb5_data_free(&deleg_data); > return ret; > } >+ >+ if (cred_blob && cred_blob->length && pkreplykey) { >+ ret = krb5_pac_add_buffer(context, *pac, >+ PAC_TYPE_CREDENTIAL_INFO, >+ &cred_data); >+ krb5_data_free(&cred_data); >+ if (ret != 0) { >+ krb5_data_free(&deleg_data); >+ return ret; >+ } >+ } > > if (deleg_blob) { > ret = krb5_pac_add_buffer(context, *pac, >@@ -216,18 +359,23 @@ int samba_krbtgt_is_in_db(struct hdb_entry_ex *princ, bool *is_in_db, bool *is_u > return 0; > } > >-NTSTATUS samba_kdc_get_pac_blob(TALLOC_CTX *mem_ctx, >+NTSTATUS samba_kdc_get_pac_cred_blob(TALLOC_CTX *mem_ctx, > struct hdb_entry_ex *client, >- DATA_BLOB **_pac_blob) >+ DATA_BLOB **_pac_blob, >+ DATA_BLOB **_cred_blob) > { > struct samba_kdc_entry *p = talloc_get_type(client->ctx, struct samba_kdc_entry); > struct auth_user_info_dc *user_info_dc; > DATA_BLOB *pac_blob; >+ DATA_BLOB *cred_blob = NULL; > NTSTATUS nt_status; > > /* The user account may be set not to want the PAC */ > if ( ! samba_princ_needs_pac(client)) { > *_pac_blob = NULL; >+ if (_cred_blob) { >+ *_cred_blob = NULL; >+ } > return NT_STATUS_OK; > } > >@@ -235,6 +383,13 @@ NTSTATUS samba_kdc_get_pac_blob(TALLOC_CTX *mem_ctx, > if (!pac_blob) { > return NT_STATUS_NO_MEMORY; > } >+ >+ if (_cred_blob) { >+ cred_blob = talloc_zero(mem_ctx, DATA_BLOB); >+ if (!cred_blob) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ } > > nt_status = authsam_make_user_info_dc(mem_ctx, p->kdc_db_ctx->samdb, > lpcfg_netbios_name(p->kdc_db_ctx->lp_ctx), >@@ -250,14 +405,18 @@ NTSTATUS samba_kdc_get_pac_blob(TALLOC_CTX *mem_ctx, > return nt_status; > } > >- nt_status = samba_get_logon_info_pac_blob(mem_ctx, user_info_dc, pac_blob); >+ nt_status = samba_get_logon_info_pac_cred_blob(mem_ctx, user_info_dc, >+ pac_blob, cred_blob); > if (!NT_STATUS_IS_OK(nt_status)) { >- DEBUG(0, ("Building PAC failed: %s\n", >+ DEBUG(0, ("Building PAC blob(s) failed: %s\n", > nt_errstr(nt_status))); > return nt_status; > } > > *_pac_blob = pac_blob; >+ if (_cred_blob) { >+ *_cred_blob = cred_blob; >+ } > return NT_STATUS_OK; > } > >@@ -277,8 +436,8 @@ NTSTATUS samba_kdc_update_pac_blob(TALLOC_CTX *mem_ctx, > return NT_STATUS_UNSUCCESSFUL; > } > >- nt_status = samba_get_logon_info_pac_blob(mem_ctx, >- user_info_dc, pac_blob); >+ nt_status = samba_get_logon_info_pac_cred_blob(mem_ctx, >+ user_info_dc, pac_blob, NULL); > > return nt_status; > } >diff --git a/source4/kdc/pac-glue.h b/source4/kdc/pac-glue.h >index 0e1cdcd..e320bae 100644 >--- a/source4/kdc/pac-glue.h >+++ b/source4/kdc/pac-glue.h >@@ -22,17 +22,21 @@ > */ > > krb5_error_code samba_make_krb5_pac(krb5_context context, >+ TALLOC_CTX *mem_ctx, > DATA_BLOB *pac_blob, >+ DATA_BLOB *cred_blob, > DATA_BLOB *deleg_blob, >- krb5_pac *pac); >+ krb5_pac *pac, >+ const krb5_keyblock *pkreplykey); > > bool samba_princ_needs_pac(struct hdb_entry_ex *princ); > > int samba_krbtgt_is_in_db(struct hdb_entry_ex *princ, bool *is_in_db, bool *is_untrusted); > >-NTSTATUS samba_kdc_get_pac_blob(TALLOC_CTX *mem_ctx, >+NTSTATUS samba_kdc_get_pac_cred_blob(TALLOC_CTX *mem_ctx, > struct hdb_entry_ex *client, >- DATA_BLOB **_pac_blob); >+ DATA_BLOB **_pac_blob, >+ DATA_BLOB **_cred_blob); > > NTSTATUS samba_kdc_update_pac_blob(TALLOC_CTX *mem_ctx, > krb5_context context, >diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c >index 929ee38..a93545e 100644 >--- a/source4/kdc/wdc-samba4.c >+++ b/source4/kdc/wdc-samba4.c >@@ -30,12 +30,12 @@ > * key to encrypt data in the PAC. */ > static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context, > struct hdb_entry_ex *client, >- krb5_pac *pac) > krb5_pac *pac, > const krb5_keyblock *pkreplykey) > { > TALLOC_CTX *mem_ctx; > DATA_BLOB *pac_blob; >+ DATA_BLOB *cred_blob = NULL; > krb5_error_code ret; > NTSTATUS nt_status; > >@@ -44,13 +44,14 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context, > return ENOMEM; > } > >- nt_status = samba_kdc_get_pac_blob(mem_ctx, client, &pac_blob); >+ nt_status = samba_kdc_get_pac_cred_blob(mem_ctx, client, &pac_blob, &cred_blob); > if (!NT_STATUS_IS_OK(nt_status)) { > talloc_free(mem_ctx); > return EINVAL; > } > >- ret = samba_make_krb5_pac(context, pac_blob, NULL, pac); >+ ret = samba_make_krb5_pac(context, mem_ctx, pac_blob, >+ cred_blob, NULL, pac, pkreplykey); > > talloc_free(mem_ctx); > return ret; >@@ -99,7 +100,7 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context, > if (client == NULL) { > return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; > } >- nt_status = samba_kdc_get_pac_blob(mem_ctx, client, &pac_blob); >+ nt_status = samba_kdc_get_pac_cred_blob(mem_ctx, client, &pac_blob, NULL); > if (!NT_STATUS_IS_OK(nt_status)) { > talloc_free(mem_ctx); > return EINVAL; >@@ -167,7 +168,8 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context, > /* We now completely regenerate this pac */ > krb5_pac_free(context, *pac); > >- ret = samba_make_krb5_pac(context, pac_blob, deleg_blob, pac); >+ ret = samba_make_krb5_pac(context, mem_ctx, pac_blob, >+ NULL, deleg_blob, pac, NULL); > > talloc_free(mem_ctx); > return ret; >-- >2.1.4 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 11441
:
11337
|
11338
|
11339
| 11340