summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/heimdal/kdc/krb5tgs.c6
-rw-r--r--source4/kdc/mit_samba.c2
-rw-r--r--source4/kdc/pac-glue.c121
-rw-r--r--source4/kdc/pac-glue.h10
-rw-r--r--source4/kdc/wdc-samba4.c29
5 files changed, 157 insertions, 11 deletions
diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c
index f13da57e45..55d5d09ede 100644
--- a/source4/heimdal/kdc/krb5tgs.c
+++ b/source4/heimdal/kdc/krb5tgs.c
@@ -2068,10 +2068,8 @@ server_lookup:
krb5_data_free(&rspac);
/*
- * generate the PAC for the user.
- *
- * TODO: pass in t->sname and t->realm and build
- * a S4U_DELEGATION_INFO blob to the PAC.
+ * generate the PAC for the user and pass
+ * dp for the S4U_DELEGATION_INFO blob in the PAC.
*/
ret = check_PAC(context, config, tp, dp,
client, server, krbtgt,
diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c
index 50b5d1d292..4905a19d99 100644
--- a/source4/kdc/mit_samba.c
+++ b/source4/kdc/mit_samba.c
@@ -255,7 +255,7 @@ static int mit_samba_update_pac_data(struct mit_samba_context *ctx,
}
nt_status = samba_kdc_update_pac_blob(tmp_ctx, ctx->context,
- &pac, logon_blob);
+ pac, logon_blob);
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(0, ("Building PAC failed: %s\n",
nt_errstr(nt_status)));
diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c
index 38db41d837..e92a511d0f 100644
--- a/source4/kdc/pac-glue.c
+++ b/source4/kdc/pac-glue.c
@@ -72,9 +72,11 @@ NTSTATUS samba_get_logon_info_pac_blob(TALLOC_CTX *mem_ctx,
krb5_error_code samba_make_krb5_pac(krb5_context context,
DATA_BLOB *pac_blob,
+ DATA_BLOB *deleg_blob,
krb5_pac *pac)
{
krb5_data pac_data;
+ krb5_data deleg_data;
krb5_error_code ret;
/* The user account may be set not to want the PAC */
@@ -87,18 +89,41 @@ krb5_error_code samba_make_krb5_pac(krb5_context context,
return ret;
}
+ ZERO_STRUCT(deleg_data);
+ if (deleg_blob) {
+ ret = krb5_data_copy(&deleg_data,
+ deleg_blob->data,
+ deleg_blob->length);
+ if (ret != 0) {
+ krb5_data_free(&pac_data);
+ return ret;
+ }
+ }
+
ret = krb5_pac_init(context, pac);
if (ret != 0) {
krb5_data_free(&pac_data);
+ krb5_data_free(&deleg_data);
return ret;
}
ret = krb5_pac_add_buffer(context, *pac, PAC_TYPE_LOGON_INFO, &pac_data);
krb5_data_free(&pac_data);
if (ret != 0) {
+ krb5_data_free(&deleg_data);
return ret;
}
+ if (deleg_blob) {
+ ret = krb5_pac_add_buffer(context, *pac,
+ PAC_TYPE_CONSTRAINED_DELEGATION,
+ &deleg_data);
+ krb5_data_free(&deleg_data);
+ if (ret != 0) {
+ return ret;
+ }
+ }
+
return ret;
}
@@ -183,13 +208,13 @@ NTSTATUS samba_kdc_get_pac_blob(TALLOC_CTX *mem_ctx,
NTSTATUS samba_kdc_update_pac_blob(TALLOC_CTX *mem_ctx,
krb5_context context,
- krb5_pac *pac, DATA_BLOB *pac_blob)
+ const krb5_pac pac, DATA_BLOB *pac_blob)
{
struct auth_user_info_dc *user_info_dc;
krb5_error_code ret;
NTSTATUS nt_status;
- ret = kerberos_pac_to_user_info_dc(mem_ctx, *pac,
+ ret = kerberos_pac_to_user_info_dc(mem_ctx, pac,
context, &user_info_dc, NULL, NULL);
if (ret) {
return NT_STATUS_UNSUCCESSFUL;
@@ -201,6 +226,98 @@ NTSTATUS samba_kdc_update_pac_blob(TALLOC_CTX *mem_ctx,
return nt_status;
}
+NTSTATUS samba_kdc_update_delegation_info_blob(TALLOC_CTX *mem_ctx,
+ krb5_context context,
+ const krb5_pac pac,
+ const krb5_principal server_principal,
+ const krb5_principal proxy_principal,
+ DATA_BLOB *new_blob)
+{
+ krb5_data old_data;
+ DATA_BLOB old_blob;
+ krb5_error_code ret;
+ NTSTATUS nt_status;
+ enum ndr_err_code ndr_err;
+ union PAC_INFO info;
+ struct PAC_CONSTRAINED_DELEGATION _d;
+ struct PAC_CONSTRAINED_DELEGATION *d = NULL;
+ char *server = NULL;
+ char *proxy = NULL;
+ uint32_t i;
+ TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+
+ if (tmp_ctx == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ret = krb5_pac_get_buffer(context, pac, PAC_TYPE_CONSTRAINED_DELEGATION, &old_data);
+ if (ret == ENOENT) {
+ ZERO_STRUCT(old_data);
+ } else if (ret) {
+ talloc_free(tmp_ctx);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ old_blob.length = old_data.length;
+ old_blob.data = (uint8_t *)old_data.data;
+
+ ZERO_STRUCT(info);
+ if (old_blob.length > 0) {
+ ndr_err = ndr_pull_union_blob(&old_blob, mem_ctx,
+ &info, PAC_TYPE_CONSTRAINED_DELEGATION,
+ (ndr_pull_flags_fn_t)ndr_pull_PAC_INFO);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ krb5_data_free(&old_data);
+ nt_status = ndr_map_error2ntstatus(ndr_err);
+ DEBUG(0,("can't parse the PAC LOGON_INFO: %s\n", nt_errstr(nt_status)));
+ talloc_free(tmp_ctx);
+ return nt_status;
+ }
+ } else {
+ ZERO_STRUCT(_d);
+ info.constrained_delegation.info = &_d;
+ }
+ krb5_data_free(&old_data);
+
+ ret = krb5_unparse_name(context, server_principal, &server);
+ if (ret) {
+ talloc_free(tmp_ctx);
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+
+ ret = krb5_unparse_name_flags(context, proxy_principal,
+ KRB5_PRINCIPAL_UNPARSE_NO_REALM, &proxy);
+ if (ret) {
+ SAFE_FREE(server);
+ talloc_free(tmp_ctx);
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+
+ d = info.constrained_delegation.info;
+ i = d->num_transited_services;
+ d->proxy_target.string = server;
+ d->transited_services = talloc_realloc(mem_ctx, d->transited_services,
+ struct lsa_String, i + 1);
+ d->transited_services[i].string = proxy;
+ d->num_transited_services = i + 1;
+
+ ndr_err = ndr_push_union_blob(new_blob, mem_ctx,
+ &info, PAC_TYPE_CONSTRAINED_DELEGATION,
+ (ndr_push_flags_fn_t)ndr_push_PAC_INFO);
+ SAFE_FREE(server);
+ SAFE_FREE(proxy);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ krb5_data_free(&old_data);
+ nt_status = ndr_map_error2ntstatus(ndr_err);
+ DEBUG(0,("can't parse the PAC LOGON_INFO: %s\n", nt_errstr(nt_status)));
+ talloc_free(tmp_ctx);
+ return nt_status;
+ }
+
+ talloc_free(tmp_ctx);
+ return NT_STATUS_OK;
+}
+
/* this function allocates 'data' using malloc.
* The caller is responsible for freeing it */
void samba_kdc_build_edata_reply(NTSTATUS nt_status, DATA_BLOB *e_data)
diff --git a/source4/kdc/pac-glue.h b/source4/kdc/pac-glue.h
index c5cc661c43..66c20cdc1e 100644
--- a/source4/kdc/pac-glue.h
+++ b/source4/kdc/pac-glue.h
@@ -23,6 +23,7 @@
krb5_error_code samba_make_krb5_pac(krb5_context context,
DATA_BLOB *pac_blob,
+ DATA_BLOB *deleg_blob,
krb5_pac *pac);
bool samba_princ_needs_pac(struct hdb_entry_ex *princ);
@@ -35,7 +36,14 @@ NTSTATUS samba_kdc_get_pac_blob(TALLOC_CTX *mem_ctx,
NTSTATUS samba_kdc_update_pac_blob(TALLOC_CTX *mem_ctx,
krb5_context context,
- krb5_pac *pac, DATA_BLOB *pac_blob);
+ const krb5_pac pac, DATA_BLOB *pac_blob);
+
+NTSTATUS samba_kdc_update_delegation_info_blob(TALLOC_CTX *mem_ctx,
+ krb5_context context,
+ const krb5_pac pac,
+ const krb5_principal server_principal,
+ const krb5_principal proxy_principal,
+ DATA_BLOB *pac_blob);
void samba_kdc_build_edata_reply(NTSTATUS nt_status, DATA_BLOB *e_data);
diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c
index 56d01dbfde..99ad96a6b5 100644
--- a/source4/kdc/wdc-samba4.c
+++ b/source4/kdc/wdc-samba4.c
@@ -46,7 +46,7 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context,
return EINVAL;
}
- ret = samba_make_krb5_pac(context, pac_blob, pac);
+ ret = samba_make_krb5_pac(context, pac_blob, NULL, pac);
talloc_free(mem_ctx);
return ret;
@@ -56,6 +56,7 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context,
static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context,
const krb5_principal client_principal,
+ const krb5_principal delegated_proxy_principal,
struct hdb_entry_ex *client,
struct hdb_entry_ex *server,
struct hdb_entry_ex *krbtgt,
@@ -64,6 +65,7 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context,
struct samba_kdc_entry *p = talloc_get_type(server->ctx, struct samba_kdc_entry);
TALLOC_CTX *mem_ctx = talloc_named(p, 0, "samba_kdc_reget_pac context");
DATA_BLOB *pac_blob;
+ DATA_BLOB *deleg_blob = NULL;
krb5_error_code ret;
NTSTATUS nt_status;
@@ -97,7 +99,7 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context,
}
nt_status = samba_kdc_update_pac_blob(mem_ctx, context,
- pac, pac_blob);
+ *pac, pac_blob);
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(0, ("Building PAC failed: %s\n",
nt_errstr(nt_status)));
@@ -105,10 +107,31 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context,
return EINVAL;
}
}
+
+ if (delegated_proxy_principal) {
+ deleg_blob = talloc_zero(mem_ctx, DATA_BLOB);
+ if (!deleg_blob) {
+ talloc_free(mem_ctx);
+ return ENOMEM;
+ }
+
+ nt_status = samba_kdc_update_delegation_info_blob(mem_ctx,
+ context, *pac,
+ server->entry.principal,
+ delegated_proxy_principal,
+ deleg_blob);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(0, ("Building PAC failed: %s\n",
+ nt_errstr(nt_status)));
+ talloc_free(mem_ctx);
+ return EINVAL;
+ }
+ }
+
/* We now completely regenerate this pac */
krb5_pac_free(context, *pac);
- ret = samba_make_krb5_pac(context, pac_blob, pac);
+ ret = samba_make_krb5_pac(context, pac_blob, deleg_blob, pac);
talloc_free(mem_ctx);
return ret;