summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2005-06-29 13:55:09 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:18:57 -0500
commit9a7481bcfeff29495334eff8803878c2c238878f (patch)
tree040ffa0f4b35ebe93b749a7b32166a9be1e525ad /source4
parentf4e75294be1f4c9d110d4ca48c5143078ade2bce (diff)
downloadsamba-9a7481bcfeff29495334eff8803878c2c238878f.tar.gz
samba-9a7481bcfeff29495334eff8803878c2c238878f.tar.bz2
samba-9a7481bcfeff29495334eff8803878c2c238878f.zip
r7993: Further work on the Krb5 PAC.
We now generate the PAC, and can verifiy both our own PAC and the PAC from Win2k3. This commit adds the PAC generation code, spits out the code to get the information we need from the NETLOGON server back into a auth/ helper function, and adds a number of glue functions. In the process of building the PAC generation code, some hints in the Microsoft PAC specification shed light on other parts of the code, and the updates to samr.idl and netlogon.idl come from those hints. Also in this commit: The Heimdal build package has been split up, so as to only link the KDC with smbd, not the client utils. To enable the PAC to be veified with gensec_krb5 (which isn't quite dead yet), the keyblock has been passed back to the calling layer. Andrew Bartlett (This used to be commit e2015671c2f7501f832ff402873ffe6e53b89466)
Diffstat (limited to 'source4')
-rw-r--r--source4/auth/auth_sam_reply.c109
-rw-r--r--source4/auth/config.mk1
-rw-r--r--source4/auth/gensec/config.mk4
-rw-r--r--source4/auth/gensec/gensec_krb5.c6
-rw-r--r--source4/auth/kerberos/config.mk1
-rw-r--r--source4/auth/kerberos/kerberos.h7
-rw-r--r--source4/auth/kerberos/kerberos_pac.c182
-rw-r--r--source4/auth/kerberos/kerberos_verify.c17
-rw-r--r--source4/heimdal_build/config.mk4
-rw-r--r--source4/kdc/config.mk3
-rw-r--r--source4/kdc/hdb-ldb.c10
-rw-r--r--source4/kdc/kdc.c4
-rw-r--r--source4/kdc/kdc.h4
-rw-r--r--source4/kdc/pac-glue.c79
-rw-r--r--source4/librpc/idl/krb5pac.idl16
-rw-r--r--source4/librpc/idl/netlogon.idl6
-rw-r--r--source4/librpc/idl/samr.idl14
-rw-r--r--source4/rpc_server/netlogon/dcerpc_netlogon.c65
-rw-r--r--source4/rpc_server/samr/dcesrv_samr.c8
-rw-r--r--source4/torture/rpc/samsync.c4
20 files changed, 426 insertions, 118 deletions
diff --git a/source4/auth/auth_sam_reply.c b/source4/auth/auth_sam_reply.c
new file mode 100644
index 0000000000..2ff071f737
--- /dev/null
+++ b/source4/auth/auth_sam_reply.c
@@ -0,0 +1,109 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Convert a server info struct into the form for PAC and NETLOGON replies
+
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004
+ Copyright (C) Stefan Metzmacher <metze@samba.org> 2005
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "librpc/gen_ndr/ndr_netlogon.h"
+#include "rpc_server/dcerpc_server.h"
+#include "rpc_server/common/common.h"
+#include "librpc/gen_ndr/ndr_dcom.h"
+#include "auth/auth.h"
+#include "lib/ldb/include/ldb.h"
+
+NTSTATUS auth_convert_server_info_sambaseinfo(TALLOC_CTX *mem_ctx,
+ struct auth_serversupplied_info *server_info,
+ struct netr_SamBaseInfo **_sam)
+{
+ struct netr_SamBaseInfo *sam = talloc_zero(mem_ctx, struct netr_SamBaseInfo);
+ NT_STATUS_HAVE_NO_MEMORY(sam);
+
+ sam->last_logon = server_info->last_logon;
+ sam->last_logoff = server_info->last_logoff;
+ sam->acct_expiry = server_info->acct_expiry;
+ sam->last_password_change = server_info->last_password_change;
+ sam->allow_password_change = server_info->allow_password_change;
+ sam->force_password_change = server_info->force_password_change;
+
+ sam->account_name.string = server_info->account_name;
+ sam->full_name.string = server_info->full_name;
+ sam->logon_script.string = server_info->logon_script;
+ sam->profile_path.string = server_info->profile_path;
+ sam->home_directory.string = server_info->home_directory;
+ sam->home_drive.string = server_info->home_drive;
+
+ sam->logon_count = server_info->logon_count;
+ sam->bad_password_count = sam->bad_password_count;
+ sam->rid = server_info->account_sid->sub_auths[server_info->account_sid->num_auths-1];
+ sam->primary_gid = server_info->primary_group_sid->sub_auths[server_info->primary_group_sid->num_auths-1];
+
+ sam->groups.count = 0;
+ sam->groups.rids = NULL;
+
+ if (server_info->n_domain_groups > 0) {
+ int i;
+ sam->groups.rids = talloc_array(sam, struct samr_RidWithAttribute,
+ server_info->n_domain_groups);
+
+ if (sam->groups.rids == NULL)
+ return NT_STATUS_NO_MEMORY;
+
+ for (i=0; i<server_info->n_domain_groups; i++) {
+
+ struct dom_sid *group_sid = server_info->domain_groups[i];
+ sam->groups.rids[sam->groups.count].rid =
+ group_sid->sub_auths[group_sid->num_auths-1];
+
+ sam->groups.rids[sam->groups.count].attributes =
+ SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED;
+ sam->groups.count += 1;
+ }
+ }
+
+ sam->user_flags = 0; /* TODO: w2k3 uses 0x120. We know 0x20
+ * as extra sids (PAC doc) but what is
+ * 0x100? */
+ sam->acct_flags = server_info->acct_flags;
+ sam->logon_server.string = lp_netbios_name();
+ sam->domain.string = server_info->domain_name;
+
+ sam->domain_sid = dom_sid_dup(mem_ctx, server_info->account_sid);
+ NT_STATUS_HAVE_NO_MEMORY(sam->domain_sid);
+ sam->domain_sid->num_auths--;
+
+ ZERO_STRUCT(sam->unknown);
+
+ ZERO_STRUCT(sam->key);
+ if (server_info->user_session_key.length == sizeof(sam->key.key)) {
+ memcpy(sam->key.key, server_info->user_session_key.data, sizeof(sam->key.key));
+ }
+
+ ZERO_STRUCT(sam->LMSessKey);
+ if (server_info->lm_session_key.length == sizeof(sam->LMSessKey.key)) {
+ memcpy(sam->LMSessKey.key, server_info->lm_session_key.data,
+ sizeof(sam->LMSessKey.key));
+ }
+
+ *_sam = sam;
+
+ return NT_STATUS_OK;
+}
+
diff --git a/source4/auth/config.mk b/source4/auth/config.mk
index 37c6ddc931..405f776830 100644
--- a/source4/auth/config.mk
+++ b/source4/auth/config.mk
@@ -76,6 +76,7 @@ INIT_OBJ_FILES = \
auth/auth.o
ADD_OBJ_FILES = \
auth/auth_util.o \
+ auth/auth_sam_reply.o \
auth/ntlm_check.o
# End SUBSYSTEM AUTH
#######################
diff --git a/source4/auth/gensec/config.mk b/source4/auth/gensec/config.mk
index 34587e2e45..03f7f24848 100644
--- a/source4/auth/gensec/config.mk
+++ b/source4/auth/gensec/config.mk
@@ -14,7 +14,7 @@ REQUIRED_SUBSYSTEMS = \
SUBSYSTEM = GENSEC
INIT_FUNCTION = gensec_krb5_init
INIT_OBJ_FILES = auth/gensec/gensec_krb5.o
-REQUIRED_SUBSYSTEMS = NDR_KRB5PAC KERBEROS KERBEROS_LIB AUTH
+REQUIRED_SUBSYSTEMS = KERBEROS AUTH
# End MODULE gensec_krb5
################################################
@@ -24,7 +24,7 @@ REQUIRED_SUBSYSTEMS = NDR_KRB5PAC KERBEROS KERBEROS_LIB AUTH
SUBSYSTEM = GENSEC
INIT_FUNCTION = gensec_gssapi_init
INIT_OBJ_FILES = auth/gensec/gensec_gssapi.o
-REQUIRED_SUBSYSTEMS = KERBEROS_LIB AUTH
+REQUIRED_SUBSYSTEMS = KERBEROS AUTH
# End MODULE gensec_gssapi
################################################
diff --git a/source4/auth/gensec/gensec_krb5.c b/source4/auth/gensec/gensec_krb5.c
index c8367d33f7..bd705531bd 100644
--- a/source4/auth/gensec/gensec_krb5.c
+++ b/source4/auth/gensec/gensec_krb5.c
@@ -47,7 +47,7 @@ struct gensec_krb5_state {
krb5_auth_context auth_context;
krb5_ccache ccache;
krb5_data ticket;
- krb5_keyblock keyblock;
+ krb5_keyblock *keyblock;
char *peer_principal;
};
@@ -61,8 +61,8 @@ static int gensec_krb5_destory(void *ptr)
}
/* ccache freed in a child destructor */
- krb5_free_keyblock_contents(gensec_krb5_state->smb_krb5_context->krb5_context,
- &gensec_krb5_state->keyblock);
+ krb5_free_keyblock(gensec_krb5_state->smb_krb5_context->krb5_context,
+ &gensec_krb5_state->keyblock);
if (gensec_krb5_state->auth_context) {
krb5_auth_con_free(gensec_krb5_state->smb_krb5_context->krb5_context,
diff --git a/source4/auth/kerberos/config.mk b/source4/auth/kerberos/config.mk
index 62710f3cc4..56ce64fdb1 100644
--- a/source4/auth/kerberos/config.mk
+++ b/source4/auth/kerberos/config.mk
@@ -8,5 +8,6 @@ ADD_OBJ_FILES = \
auth/kerberos/kerberos_util.o \
auth/kerberos/kerberos_pac.o \
auth/kerberos/gssapi_parse.o
+REQUIRED_SUBSYSTEMS = KERBEROS_LIB NDR_KRB5PAC
# End SUBSYSTEM KERBEROS
#################################
diff --git a/source4/auth/kerberos/kerberos.h b/source4/auth/kerberos/kerberos.h
index ca0bbbed0e..1fd48197f8 100644
--- a/source4/auth/kerberos/kerberos.h
+++ b/source4/auth/kerberos/kerberos.h
@@ -97,7 +97,7 @@ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
const DATA_BLOB *ticket,
char **principal, DATA_BLOB *auth_data,
DATA_BLOB *ap_rep,
- krb5_keyblock *keyblock);
+ krb5_keyblock **keyblock);
int kerberos_kinit_password_cc(krb5_context ctx, krb5_ccache cc,
const char *principal, const char *password,
time_t *expire_time, time_t *kdc_time);
@@ -132,5 +132,10 @@ NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
DATA_BLOB blob,
struct smb_krb5_context *smb_krb5_context,
krb5_keyblock *keyblock);
+krb5_error_code kerberos_encode_pac(TALLOC_CTX *mem_ctx,
+ struct auth_serversupplied_info *server_info,
+ krb5_context context,
+ krb5_keyblock *keyblock,
+ krb5_data *pac);
#endif /* HAVE_KRB5 */
diff --git a/source4/auth/kerberos/kerberos_pac.c b/source4/auth/kerberos/kerberos_pac.c
index 9d57245798..e1d05b9949 100644
--- a/source4/auth/kerberos/kerberos_pac.c
+++ b/source4/auth/kerberos/kerberos_pac.c
@@ -28,16 +28,16 @@
#include "system/kerberos.h"
#include "system/time.h"
#include "system/network.h"
+#include "auth/auth.h"
#include "auth/kerberos/kerberos.h"
#include "librpc/gen_ndr/ndr_krb5pac.h"
#include "auth/auth.h"
-static NTSTATUS kerberos_pac_checksum(TALLOC_CTX *mem_ctx,
- DATA_BLOB pac_data,
- struct PAC_SIGNATURE_DATA *sig,
- struct smb_krb5_context *smb_krb5_context,
- krb5_keyblock *keyblock,
- uint32_t keyusage)
+static NTSTATUS 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;
@@ -48,7 +48,7 @@ static NTSTATUS kerberos_pac_checksum(TALLOC_CTX *mem_ctx,
cksum.checksum.data = sig->signature;
- ret = krb5_crypto_init(smb_krb5_context->krb5_context,
+ ret = krb5_crypto_init(context,
keyblock,
0,
&crypto);
@@ -56,7 +56,7 @@ static NTSTATUS kerberos_pac_checksum(TALLOC_CTX *mem_ctx,
DEBUG(0,("krb5_crypto_init() failed\n"));
return NT_STATUS_FOOBAR;
}
- ret = krb5_verify_checksum(smb_krb5_context->krb5_context,
+ ret = krb5_verify_checksum(context,
crypto,
KRB5_KU_OTHER_CKSUM,
pac_data.data,
@@ -64,10 +64,10 @@ static NTSTATUS kerberos_pac_checksum(TALLOC_CTX *mem_ctx,
&cksum);
if (ret) {
DEBUG(2, ("PAC Verification failed: %s\n",
- smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx)));
+ smb_get_krb5_error_message(context, ret, mem_ctx)));
}
- krb5_crypto_destroy(smb_krb5_context->krb5_context, crypto);
+ krb5_crypto_destroy(context, crypto);
if (ret) {
return NT_STATUS_ACCESS_DENIED;
@@ -92,6 +92,8 @@ static NTSTATUS kerberos_pac_checksum(TALLOC_CTX *mem_ctx,
DATA_BLOB modified_pac_blob = data_blob_talloc(mem_ctx, blob.data, blob.length);
int i;
+ file_save("/tmp/pac.in", blob.data, blob.length);
+
status = ndr_pull_struct_blob(&blob, mem_ctx, &pac_data,
(ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
if (!NT_STATUS_IS_OK(status)) {
@@ -127,7 +129,7 @@ static NTSTATUS kerberos_pac_checksum(TALLOC_CTX *mem_ctx,
kdc_sig_ptr = &pac_data.buffers[i].info->kdc_cksum;
kdc_sig = pac_data.buffers[i].info->kdc_cksum;
break;
- case PAC_TYPE_UNKNOWN_10:
+ case PAC_TYPE_LOGON_NAME:
break;
default:
break;
@@ -154,11 +156,13 @@ static NTSTATUS kerberos_pac_checksum(TALLOC_CTX *mem_ctx,
memset(&modified_pac_blob.data[modified_pac_blob.length - 44],
'\0', 16);
- /* verify by servie_key */
- status = kerberos_pac_checksum(mem_ctx,
- modified_pac_blob, &srv_sig,
- smb_krb5_context, keyblock, 0);
+ file_save("/tmp/pac.in.blanked", modified_pac_blob.data, modified_pac_blob.length);
+ /* verify by service_key */
+ status = check_pac_checksum(mem_ctx,
+ modified_pac_blob, &srv_sig,
+ smb_krb5_context->krb5_context, keyblock);
+
if (!NT_STATUS_IS_OK(status)) {
return status;
}
@@ -170,3 +174,151 @@ static NTSTATUS kerberos_pac_checksum(TALLOC_CTX *mem_ctx,
return status;
}
+static krb5_error_code make_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;
+ Checksum cksum;
+
+
+ ret = krb5_crypto_init(context,
+ keyblock,
+ 0,
+ &crypto);
+ if (ret) {
+ DEBUG(0,("krb5_crypto_init() failed\n"));
+ return ret;
+ }
+ ret = krb5_create_checksum(context,
+ crypto,
+ KRB5_KU_OTHER_CKSUM,
+ 0,
+ 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 ret;
+ }
+
+ sig->type = cksum.cksumtype;
+ if (cksum.checksum.length == sizeof(sig->signature)) {
+ memcpy(sig->signature, cksum.checksum.data, sizeof(sig->signature));
+ }
+
+ return 0;
+}
+
+ krb5_error_code kerberos_encode_pac(TALLOC_CTX *mem_ctx,
+ struct auth_serversupplied_info *server_info,
+ krb5_context context,
+ krb5_keyblock *keyblock,
+ krb5_data *pac)
+{
+ NTSTATUS nt_status;
+ DATA_BLOB tmp_blob = data_blob(NULL, 0);
+ krb5_error_code ret;
+ struct PAC_DATA *pac_data = talloc(mem_ctx, struct PAC_DATA);
+ struct netr_SamBaseInfo *sam;
+ struct timeval tv = timeval_current();
+
+ if (!pac_data) {
+ return ENOMEM;
+ }
+
+ pac_data->num_buffers = 4;
+ pac_data->version = 0;
+
+ pac_data->buffers = talloc_array(pac_data,
+ struct PAC_BUFFER,
+ pac_data->num_buffers);
+
+ if (!pac_data->buffers) {
+ talloc_free(pac_data);
+ return ENOMEM;
+ }
+ pac_data->buffers[0].type = PAC_TYPE_LOGON_INFO;
+ pac_data->buffers[0].info = talloc_zero(pac_data->buffers,
+ union PAC_INFO);
+
+ nt_status = auth_convert_server_info_sambaseinfo(pac_data->buffers[0].info,
+ server_info, &sam);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(1, ("Getting Samba info failed: %s\n", nt_errstr(nt_status)));
+ talloc_free(pac_data);
+ return EINVAL;
+ }
+
+ pac_data->buffers[0].info->logon_info.info3.base = *sam;
+
+ pac_data->buffers[1].type = PAC_TYPE_LOGON_NAME;
+ pac_data->buffers[1].info = talloc_zero(pac_data->buffers,
+ union PAC_INFO);
+ pac_data->buffers[1].info->logon_name.account_name
+ = server_info->account_name;
+ pac_data->buffers[1].info->logon_name.logon_time
+ = timeval_to_nttime(&tv);
+
+ pac_data->buffers[2].type = PAC_TYPE_KDC_CHECKSUM;
+ pac_data->buffers[2].info = talloc_zero(pac_data->buffers,
+ union PAC_INFO);
+
+ pac_data->buffers[3].type = PAC_TYPE_SRV_CHECKSUM;
+ pac_data->buffers[3].info = talloc_zero(pac_data->buffers,
+ union PAC_INFO);
+
+ /* First, just get the keytypes filled in (and lengths right, eventually) */
+ ret = make_pac_checksum(mem_ctx, tmp_blob, &pac_data->buffers[2].info->srv_cksum,
+ context, keyblock);
+ if (ret) {
+ DEBUG(2, ("making PAC checksum failed: %s\n",
+ smb_get_krb5_error_message(context, ret, mem_ctx)));
+ talloc_free(pac_data);
+ return ret;
+ }
+
+ /* But wipe out the actual signatures */
+ ZERO_STRUCT(pac_data->buffers[2].info->kdc_cksum.signature);
+ ZERO_STRUCT(pac_data->buffers[3].info->srv_cksum.signature);
+
+ nt_status = ndr_push_struct_blob(&tmp_blob, mem_ctx, pac_data,
+ (ndr_push_flags_fn_t)ndr_push_PAC_DATA);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(1, ("PAC push failed: %s\n", nt_errstr(nt_status)));
+ talloc_free(pac_data);
+ return EINVAL;
+ }
+
+ file_save("/tmp/pac.out.blank", tmp_blob.data, tmp_blob.length);
+
+ /* Then sign the result of the previous push, where the sig was zero'ed out */
+ ret = make_pac_checksum(mem_ctx, tmp_blob, &pac_data->buffers[3].info->srv_cksum,
+ context, keyblock);
+
+ /* And push it out to the world. This relies on determanistic pointer values */
+ nt_status = ndr_push_struct_blob(&tmp_blob, mem_ctx, pac_data,
+ (ndr_push_flags_fn_t)ndr_push_PAC_DATA);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(1, ("PAC push failed: %s\n", nt_errstr(nt_status)));
+ talloc_free(pac_data);
+ return EINVAL;
+ }
+
+ file_save("/tmp/pac.out.signed", tmp_blob.data, tmp_blob.length);
+
+ ret = krb5_data_copy(pac, tmp_blob.data, tmp_blob.length);
+
+ talloc_free(pac_data);
+ return ret;
+}
+
diff --git a/source4/auth/kerberos/kerberos_verify.c b/source4/auth/kerberos/kerberos_verify.c
index 01b8a75c95..b140eb6ae9 100644
--- a/source4/auth/kerberos/kerberos_verify.c
+++ b/source4/auth/kerberos/kerberos_verify.c
@@ -75,7 +75,7 @@ static krb5_error_code ads_keytab_verify_ticket(TALLOC_CTX *mem_ctx, krb5_contex
const char *service,
const DATA_BLOB *ticket, krb5_data *p_packet,
krb5_ticket **pp_tkt,
- krb5_keyblock *keyblock)
+ krb5_keyblock **keyblock)
{
krb5_error_code ret = 0;
krb5_keytab keytab = NULL;
@@ -149,7 +149,9 @@ static krb5_error_code ads_keytab_verify_ticket(TALLOC_CTX *mem_ctx, krb5_contex
p_packet->length = ticket->length;
p_packet->data = (krb5_pointer)ticket->data;
*pp_tkt = NULL;
- ret = krb5_rd_req(context, &auth_context, p_packet, kt_entry.principal, keytab, NULL, pp_tkt);
+ ret = krb5_rd_req_return_keyblock(context, &auth_context, p_packet,
+ kt_entry.principal, keytab,
+ NULL, pp_tkt, keyblock);
if (ret) {
last_error_message = smb_get_krb5_error_message(context, ret, mem_ctx);
DEBUG(10, ("ads_keytab_verify_ticket: krb5_rd_req(%s) failed: %s\n",
@@ -224,7 +226,7 @@ static krb5_error_code ads_secrets_verify_ticket(TALLOC_CTX *mem_ctx,
krb5_principal salt_princ,
const DATA_BLOB *ticket, krb5_data *p_packet,
krb5_ticket **pp_tkt,
- krb5_keyblock *keyblock)
+ krb5_keyblock **keyblock)
{
krb5_error_code ret = 0;
krb5_error_code our_ret;
@@ -274,9 +276,10 @@ static krb5_error_code ads_secrets_verify_ticket(TALLOC_CTX *mem_ctx,
krb5_free_keyblock(context, key);
- our_ret = krb5_rd_req(context, &auth_context, p_packet,
- NULL,
- NULL, NULL, pp_tkt);
+ our_ret = krb5_rd_req_return_keyblock(context, &auth_context, p_packet,
+ NULL,
+ NULL, NULL, pp_tkt,
+ keyblock);
if (!our_ret) {
DEBUG(10,("ads_secrets_verify_ticket: enc type [%u] decrypted message !\n",
@@ -311,7 +314,7 @@ static krb5_error_code ads_secrets_verify_ticket(TALLOC_CTX *mem_ctx,
const DATA_BLOB *ticket,
char **principal, DATA_BLOB *auth_data,
DATA_BLOB *ap_rep,
- krb5_keyblock *keyblock)
+ krb5_keyblock **keyblock)
{
NTSTATUS sret = NT_STATUS_LOGON_FAILURE;
krb5_data packet;
diff --git a/source4/heimdal_build/config.mk b/source4/heimdal_build/config.mk
index a376ceb9e4..8d46c536f1 100644
--- a/source4/heimdal_build/config.mk
+++ b/source4/heimdal_build/config.mk
@@ -1,6 +1,7 @@
#######################
# Start SUBSYSTEM HEIMDAL_KDC
[SUBSYSTEM::HEIMDAL_KDC]
+TARGET_CFLAGS = -Iheimdal_build -Iheimdal/kdc -Iheimdal/lib/des -Iheimdal/lib/roken -Iheimdal/include
ADD_OBJ_FILES = \
heimdal/kdc/default_config.o \
heimdal/kdc/kerberos5.o \
@@ -18,6 +19,7 @@ NOPROTO = YES
#######################
# Start SUBSYSTEM HEIMDAL_HDB
[SUBSYSTEM::HEIMDAL_HDB]
+TARGET_CFLAGS = -Iheimdal_build -Iheimdal/kdc -Iheimdal/lib/des -Iheimdal/lib/roken -Iheimdal/include
ADD_OBJ_FILES = \
heimdal/lib/hdb/db.o \
heimdal/lib/hdb/hdb.o \
@@ -372,7 +374,7 @@ REQUIRED_SUBSYSTEMS = ASN1_COMPILER
NOPROTO = YES
TARGET_CFLAGS = -Iheimdal_build -Iheimdal/kdc -Iheimdal/lib/des -Iheimdal/lib/roken -Iheimdal/include
REQUIRED_SUBSYSTEMS = \
- HEIMDAL_KDC HEIMDAL_HDB HEIMDAL_GSSAPI HEIMDAL_KRB5 \
+ HEIMDAL_GSSAPI HEIMDAL_KRB5 \
HEIMDAL_ASN1 HEIMDAL_DES HEIMDAL_ROKEN HEIMDAL_COM_ERR
# End SUBSYSTEM HEIMDAL
#######################
diff --git a/source4/kdc/config.mk b/source4/kdc/config.mk
index b1de650faa..ce655dea82 100644
--- a/source4/kdc/config.mk
+++ b/source4/kdc/config.mk
@@ -5,8 +5,9 @@
[SUBSYSTEM::KDC]
INIT_OBJ_FILES = \
kdc/kdc.o \
+ kdc/pac-glue.o \
kdc/hdb-ldb.o
REQUIRED_SUBSYSTEMS = \
- LIBLDB KERBEROS_LIB
+ LIBLDB KERBEROS_LIB HEIMDAL_KDC HEIMDAL_HDB
# End SUBSYSTEM KDC
#######################
diff --git a/source4/kdc/hdb-ldb.c b/source4/kdc/hdb-ldb.c
index 231d7db436..0875803be0 100644
--- a/source4/kdc/hdb-ldb.c
+++ b/source4/kdc/hdb-ldb.c
@@ -40,7 +40,8 @@
#include "system/iconv.h"
enum hdb_ldb_ent_type
-{ HDB_LDB_ENT_TYPE_CLIENT, HDB_LDB_ENT_TYPE_SERVER, HDB_LDB_ENT_TYPE_KRBTGT, HDB_LDB_ENT_TYPE_ANY };
+{ HDB_LDB_ENT_TYPE_CLIENT, HDB_LDB_ENT_TYPE_SERVER,
+ HDB_LDB_ENT_TYPE_KRBTGT, HDB_LDB_ENT_TYPE_ANY };
static const char * const krb5_attrs[] = {
"objectClass",
@@ -980,9 +981,10 @@ static krb5_error_code LDB_destroy(krb5_context context, HDB *db)
return 0;
}
-krb5_error_code hdb_ldb_create(krb5_context context, struct HDB **db, const char *arg)
+krb5_error_code hdb_ldb_create(TALLOC_CTX *mem_ctx,
+ krb5_context context, struct HDB **db, const char *arg)
{
- *db = talloc(NULL, HDB);
+ *db = talloc(mem_ctx, HDB);
if (!*db) {
krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
@@ -990,8 +992,8 @@ krb5_error_code hdb_ldb_create(krb5_context context, struct HDB **db, const char
(*db)->hdb_master_key_set = 0;
(*db)->hdb_db = NULL;
- /* in future, we could cache the connect here, but for now KISS */
+ /* Setup the link to LDB */
(*db)->hdb_db = samdb_connect(db);
if ((*db)->hdb_db == NULL) {
krb5_warnx(context, "hdb_ldb_create: samdb_connect failed!");
diff --git a/source4/kdc/kdc.c b/source4/kdc/kdc.c
index 8a7e497913..a1958b54fa 100644
--- a/source4/kdc/kdc.c
+++ b/source4/kdc/kdc.c
@@ -29,6 +29,8 @@
#include "system/network.h"
#include "dlinklist.h"
+
+
/*
handle fd send events on a KDC socket
*/
@@ -276,7 +278,7 @@ static void kdc_task_init(struct task_server *task)
}
kdc->config->num_db = 1;
- ret = hdb_ldb_create(kdc->smb_krb5_context->krb5_context,
+ ret = hdb_ldb_create(kdc, kdc->smb_krb5_context->krb5_context,
&kdc->config->db[0], lp_sam_url());
if (ret != 0) {
DEBUG(1, ("kdc_task_init: hdb_ldb_create fails: %s\n",
diff --git a/source4/kdc/kdc.h b/source4/kdc/kdc.h
index 25f643eadd..d59fa3e2e7 100644
--- a/source4/kdc/kdc.h
+++ b/source4/kdc/kdc.h
@@ -24,8 +24,10 @@
#include "system/kerberos.h"
#include "auth/kerberos/kerberos.h"
#include "heimdal/kdc/kdc.h"
+#include "kdc/pac-glue.h"
-krb5_error_code hdb_ldb_create(krb5_context context, struct HDB **db, const char *arg);
+krb5_error_code hdb_ldb_create(TALLOC_CTX *mem_ctx,
+ krb5_context context, struct HDB **db, const char *arg);
/* hold all the info needed to send a reply */
struct kdc_reply {
diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c
new file mode 100644
index 0000000000..40d11d31e9
--- /dev/null
+++ b/source4/kdc/pac-glue.c
@@ -0,0 +1,79 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ PAC Glue between Samba and the KDC
+
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "kdc/kdc.h"
+
+ krb5_error_code samba_get_pac(krb5_context context,
+ struct krb5_kdc_configuration *config,
+ krb5_principal client,
+ krb5_keyblock *keyblock,
+ krb5_data *pac)
+{
+ krb5_error_code ret;
+ NTSTATUS nt_status;
+ struct auth_serversupplied_info *server_info;
+ char *username, *p;
+ const char *realm;
+ TALLOC_CTX *mem_ctx = talloc_named(config, 0, "samba_get_pac context");
+ if (!mem_ctx) {
+ return ENOMEM;
+ }
+
+ ret = krb5_unparse_name(context, client, &username);
+
+ if (ret != 0) {
+ krb5_set_error_string(context, "get pac: could not parse principal");
+ krb5_warnx(context, "get pac: could not parse principal");
+ talloc_free(mem_ctx);
+ return ret;
+ }
+
+ /* parse the principal name */
+ realm = krb5_principal_get_realm(context, client);
+ username = talloc_strdup(mem_ctx, username);
+ p = strchr(username, '@');
+ if (p) {
+ p[0] = '\0';
+ }
+
+
+ nt_status = sam_get_server_info(mem_ctx, username, realm,
+ data_blob(NULL, 0), data_blob(NULL, 0),
+ &server_info);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(0, ("Getting user info for PAC failed: %s\n",
+ nt_errstr(nt_status)));
+ talloc_free(mem_ctx);
+ return EINVAL;
+ }
+
+ ret = kerberos_encode_pac(mem_ctx, server_info,
+ context,
+ keyblock,
+ pac);
+
+ talloc_free(mem_ctx);
+
+ return ret;
+}
diff --git a/source4/librpc/idl/krb5pac.idl b/source4/librpc/idl/krb5pac.idl
index 16524197c5..e3395f8961 100644
--- a/source4/librpc/idl/krb5pac.idl
+++ b/source4/librpc/idl/krb5pac.idl
@@ -16,37 +16,39 @@ interface krb5pac
typedef struct {
NTTIME logon_time;
[flag(STR_SIZE2|STR_NOTERM|STR_BYTESIZE)] string account_name;
- } PAC_UNKNOWN_10;
+ [value(0)] uint32 _pad;
+ } PAC_LOGON_NAME;
typedef [flag(NDR_PAHEX)] struct {
uint32 type;
uint8 signature[16];
+ [value(0)] uint32 _pad;
} PAC_SIGNATURE_DATA;
typedef struct {
uint32 unknown[5];
netr_SamInfo3 info3;
dom_sid2 *res_group_dom_sid;
- samr_RidWithTypeArray res_groups;
+ samr_RidWithAttributeArray res_groups;
} PAC_LOGON_INFO;
const uint8 PAC_TYPE_LOGON_INFO = 1;
const uint8 PAC_TYPE_SRV_CHECKSUM = 6;
const uint8 PAC_TYPE_KDC_CHECKSUM = 7;
- const uint8 PAC_TYPE_UNKNOWN_10 = 10;
+ const uint8 PAC_TYPE_LOGON_NAME = 10;
- typedef [nodiscriminant] union {
+ typedef [nodiscriminant,gensize,flag(NDR_ALIGN8)] union {
[case(PAC_TYPE_LOGON_INFO)] PAC_LOGON_INFO logon_info;
[case(PAC_TYPE_SRV_CHECKSUM)] PAC_SIGNATURE_DATA srv_cksum;
[case(PAC_TYPE_KDC_CHECKSUM)] PAC_SIGNATURE_DATA kdc_cksum;
- [case(PAC_TYPE_UNKNOWN_10)] PAC_UNKNOWN_10 type_10;
+ [case(PAC_TYPE_LOGON_NAME)] PAC_LOGON_NAME logon_name;
} PAC_INFO;
typedef struct {
uint32 type;
- uint32 size;
+ [value(ndr_size_PAC_INFO(info,type,ndr->flags))] uint32 size;
[relative,switch_is(type)] PAC_INFO *info;
- uint32 _pad;
+ [value(0)] uint32 _pad; /* Top half of a 64 bit pointer? */
} PAC_BUFFER;
typedef [public,flag(NDR_ALIGN8)] struct {
diff --git a/source4/librpc/idl/netlogon.idl b/source4/librpc/idl/netlogon.idl
index 8301a6cf40..f73dc24f47 100644
--- a/source4/librpc/idl/netlogon.idl
+++ b/source4/librpc/idl/netlogon.idl
@@ -140,6 +140,10 @@ interface netlogon
uint8 key[8];
} netr_LMSessionKey;
+ /* Flags for user_flags below */
+ const int NETLOGON_EXTRA_SIDS = 0x0020;
+ const int NETLOGON_RESOURCE_GROUPS = 0x0200;
+
typedef struct {
NTTIME last_logon;
NTTIME last_logoff;
@@ -157,7 +161,7 @@ interface netlogon
uint16 bad_password_count;
uint32 rid;
uint32 primary_gid;
- samr_RidWithTypeArray groups;
+ samr_RidWithAttributeArray groups;
uint32 user_flags;
netr_UserSessionKey key;
netr_String logon_server;
diff --git a/source4/librpc/idl/samr.idl b/source4/librpc/idl/samr.idl
index cf61011387..a989d09486 100644
--- a/source4/librpc/idl/samr.idl
+++ b/source4/librpc/idl/samr.idl
@@ -357,6 +357,10 @@
[out,ref] policy_handle *group_handle
);
+ /* Group attributes */
+ const int SE_GROUP_MANDATORY = 0x0001;
+ const int SE_GROUP_ENABLED_BY_DEFAULT = 0x0002;
+ const int SE_GROUP_ENABLED = 0x0004;
/************************/
/* Function 0x14 */
@@ -816,17 +820,17 @@
typedef [public] struct {
uint32 rid;
- uint32 type;
- } samr_RidWithType;
+ uint32 attributes;
+ } samr_RidWithAttribute;
typedef [public] struct {
uint32 count;
- [size_is(count)] samr_RidWithType *rids;
- } samr_RidWithTypeArray;
+ [size_is(count)] samr_RidWithAttribute *rids;
+ } samr_RidWithAttributeArray;
NTSTATUS samr_GetGroupsForUser(
[in,ref] policy_handle *user_handle,
- [out] samr_RidWithTypeArray *rids
+ [out] samr_RidWithAttributeArray *rids
);
/************************/
diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index 4dd8312df5..1317ea31a9 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -503,64 +503,9 @@ static NTSTATUS netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_
nt_status = auth_check_password(auth_context, mem_ctx, user_info, &server_info);
NT_STATUS_NOT_OK_RETURN(nt_status);
- sam = talloc_zero(mem_ctx, struct netr_SamBaseInfo);
- NT_STATUS_HAVE_NO_MEMORY(sam);
-
- sam->last_logon = server_info->last_logon;
- sam->last_logoff = server_info->last_logoff;
- sam->acct_expiry = server_info->acct_expiry;
- sam->last_password_change = server_info->last_password_change;
- sam->allow_password_change = server_info->allow_password_change;
- sam->force_password_change = server_info->force_password_change;
-
- sam->account_name.string = server_info->account_name;
- sam->full_name.string = server_info->full_name;
- sam->logon_script.string = server_info->logon_script;
- sam->profile_path.string = server_info->profile_path;
- sam->home_directory.string = server_info->home_directory;
- sam->home_drive.string = server_info->home_drive;
-
- sam->logon_count = server_info->logon_count;
- sam->bad_password_count = sam->bad_password_count;
- sam->rid = server_info->account_sid->sub_auths[server_info->account_sid->num_auths-1];
- sam->primary_gid = server_info->primary_group_sid->sub_auths[server_info->primary_group_sid->num_auths-1];
-
- sam->groups.count = 0;
- sam->groups.rids = NULL;
-
- if (server_info->n_domain_groups > 0) {
- int i;
- sam->groups.rids = talloc_array(mem_ctx, struct samr_RidWithType,
- server_info->n_domain_groups);
-
- if (sam->groups.rids == NULL)
- return NT_STATUS_NO_MEMORY;
-
- for (i=0; i<server_info->n_domain_groups; i++) {
-
- struct dom_sid *group_sid = server_info->domain_groups[i];
- sam->groups.rids[sam->groups.count].rid =
- group_sid->sub_auths[group_sid->num_auths-1];
- sam->groups.rids[sam->groups.count].type = 7;
- sam->groups.count += 1;
- }
- }
-
- sam->user_flags = 0; /* TODO: w2k3 uses 0x120 - what is this? */
- sam->acct_flags = server_info->acct_flags;
- sam->logon_server.string = lp_netbios_name();
- sam->domain.string = server_info->domain_name;
-
- sam->domain_sid = dom_sid_dup(mem_ctx, server_info->account_sid);
- NT_STATUS_HAVE_NO_MEMORY(sam->domain_sid);
- sam->domain_sid->num_auths--;
-
- ZERO_STRUCT(sam->unknown);
+ nt_status = auth_convert_server_info_sambaseinfo(mem_ctx, server_info, &sam);
- ZERO_STRUCT(sam->key);
- if (server_info->user_session_key.length == sizeof(sam->key.key)) {
- memcpy(sam->key.key, server_info->user_session_key.data, sizeof(sam->key.key));
- }
+ NT_STATUS_NOT_OK_RETURN(nt_status);
/* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
/* It appears that level 6 is not individually encrypted */
@@ -576,12 +521,6 @@ static NTSTATUS netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_
}
}
- ZERO_STRUCT(sam->LMSessKey);
- if (server_info->lm_session_key.length == sizeof(sam->LMSessKey.key)) {
- memcpy(sam->LMSessKey.key, server_info->lm_session_key.data,
- sizeof(sam->LMSessKey.key));
- }
-
/* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
/* It appears that level 6 is not individually encrypted */
if ((r->in.validation_level != 6)
diff --git a/source4/rpc_server/samr/dcesrv_samr.c b/source4/rpc_server/samr/dcesrv_samr.c
index cce446533d..66f327b6f9 100644
--- a/source4/rpc_server/samr/dcesrv_samr.c
+++ b/source4/rpc_server/samr/dcesrv_samr.c
@@ -2757,7 +2757,7 @@ static NTSTATUS samr_GetGroupsForUser(struct dcesrv_call_state *dce_call, TALLOC
struct samr_domain_state *d_state;
struct ldb_message **res;
const char * const attrs[2] = { "objectSid", NULL };
- struct samr_RidWithTypeArray *array;
+ struct samr_RidWithAttributeArray *array;
int count;
DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER);
@@ -2774,7 +2774,7 @@ static NTSTATUS samr_GetGroupsForUser(struct dcesrv_call_state *dce_call, TALLOC
if (count < 0)
return NT_STATUS_INTERNAL_DB_CORRUPTION;
- array = talloc(mem_ctx, struct samr_RidWithTypeArray);
+ array = talloc(mem_ctx, struct samr_RidWithAttributeArray);
if (array == NULL)
return NT_STATUS_NO_MEMORY;
@@ -2783,7 +2783,7 @@ static NTSTATUS samr_GetGroupsForUser(struct dcesrv_call_state *dce_call, TALLOC
if (count > 0) {
int i;
- array->rids = talloc_array(mem_ctx, struct samr_RidWithType,
+ array->rids = talloc_array(mem_ctx, struct samr_RidWithAttribute,
count);
if (array->rids == NULL)
@@ -2801,7 +2801,7 @@ static NTSTATUS samr_GetGroupsForUser(struct dcesrv_call_state *dce_call, TALLOC
array->rids[array->count].rid =
group_sid->sub_auths[group_sid->num_auths-1];
- array->rids[array->count].type = 7;
+ array->rids[array->count].attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED;
array->count += 1;
}
}
diff --git a/source4/torture/rpc/samsync.c b/source4/torture/rpc/samsync.c
index 652fef15c3..29e66ec4c3 100644
--- a/source4/torture/rpc/samsync.c
+++ b/source4/torture/rpc/samsync.c
@@ -629,8 +629,8 @@ static BOOL samsync_handle_user(TALLOC_CTX *mem_ctx, struct samsync_state *samsy
for (j = 0; j < count; j++) {
if ((getgroups.out.rids->rids[i].rid ==
info3->base.groups.rids[j].rid)
- && (getgroups.out.rids->rids[i].type ==
- info3->base.groups.rids[j].type)) {
+ && (getgroups.out.rids->rids[i].attributes ==
+ info3->base.groups.rids[j].attributes)) {
matched[i] = True;
}
}