diff options
-rw-r--r-- | source4/auth/auth_sam_reply.c | 109 | ||||
-rw-r--r-- | source4/auth/config.mk | 1 | ||||
-rw-r--r-- | source4/auth/gensec/config.mk | 4 | ||||
-rw-r--r-- | source4/auth/gensec/gensec_krb5.c | 6 | ||||
-rw-r--r-- | source4/auth/kerberos/config.mk | 1 | ||||
-rw-r--r-- | source4/auth/kerberos/kerberos.h | 7 | ||||
-rw-r--r-- | source4/auth/kerberos/kerberos_pac.c | 182 | ||||
-rw-r--r-- | source4/auth/kerberos/kerberos_verify.c | 17 | ||||
-rw-r--r-- | source4/heimdal_build/config.mk | 4 | ||||
-rw-r--r-- | source4/kdc/config.mk | 3 | ||||
-rw-r--r-- | source4/kdc/hdb-ldb.c | 10 | ||||
-rw-r--r-- | source4/kdc/kdc.c | 4 | ||||
-rw-r--r-- | source4/kdc/kdc.h | 4 | ||||
-rw-r--r-- | source4/kdc/pac-glue.c | 79 | ||||
-rw-r--r-- | source4/librpc/idl/krb5pac.idl | 16 | ||||
-rw-r--r-- | source4/librpc/idl/netlogon.idl | 6 | ||||
-rw-r--r-- | source4/librpc/idl/samr.idl | 14 | ||||
-rw-r--r-- | source4/rpc_server/netlogon/dcerpc_netlogon.c | 65 | ||||
-rw-r--r-- | source4/rpc_server/samr/dcesrv_samr.c | 8 | ||||
-rw-r--r-- | source4/torture/rpc/samsync.c | 4 |
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 00000000000..2ff071f7374 --- /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 37c6ddc9319..405f7768302 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 34587e2e45b..03f7f24848b 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 c8367d33f79..bd705531bd1 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 62710f3cc46..56ce64fdb13 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 ca0bbbed0ee..1fd48197f8a 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 9d57245798e..e1d05b99498 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 01b8a75c952..b140eb6ae99 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 a376ceb9e4f..8d46c536f1b 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 b1de650faa5..ce655dea82d 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 231d7db436b..0875803be00 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 8a7e497913e..a1958b54fa6 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 25f643eadd5..d59fa3e2e70 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 00000000000..40d11d31e9a --- /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 16524197c57..e3395f89610 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 8301a6cf405..f73dc24f474 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 cf610113873..a989d09486c 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 4dd8312df58..1317ea31a95 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 cce446533d0..66f327b6f96 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 652fef15c3b..29e66ec4c30 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; } } |