diff options
-rw-r--r-- | source4/Makefile | 1 | ||||
-rw-r--r-- | source4/auth/kerberos/kerberos_pac.c | 10 | ||||
-rw-r--r-- | source4/build/m4/public.m4 | 12 | ||||
-rw-r--r-- | source4/build/smb_build/main.pl | 6 | ||||
-rw-r--r-- | source4/dynconfig/config.mk | 3 | ||||
-rw-r--r-- | source4/dynconfig/version.c | 27 | ||||
-rw-r--r-- | source4/heimdal/lib/krb5/crypto.c | 102 | ||||
-rw-r--r-- | source4/kdc/kdc.c | 112 | ||||
-rw-r--r-- | source4/lib/zlib.mk | 27 | ||||
-rw-r--r-- | source4/librpc/idl/irpc.idl | 17 | ||||
-rw-r--r-- | source4/librpc/idl/krb5pac.idl | 2 | ||||
-rw-r--r-- | source4/rpc_server/netlogon/dcerpc_netlogon.c | 45 | ||||
-rw-r--r-- | source4/samba4-skip | 1 | ||||
-rw-r--r-- | source4/scripting/python/misc.i | 14 | ||||
-rw-r--r-- | source4/scripting/python/misc_wrap.c | 9 | ||||
-rw-r--r-- | source4/torture/rpc/remote_pac.c | 181 |
16 files changed, 474 insertions, 95 deletions
diff --git a/source4/Makefile b/source4/Makefile index b0aa009edd..d91d08a252 100644 --- a/source4/Makefile +++ b/source4/Makefile @@ -49,6 +49,7 @@ endif include $(srcdir)/build/make/rules.mk include $(srcdir)/build/make/python.mk +zlibsrcdir := lib/zlib dynconfigsrcdir := dynconfig heimdalsrcdir := heimdal dsdbsrcdir := dsdb diff --git a/source4/auth/kerberos/kerberos_pac.c b/source4/auth/kerberos/kerberos_pac.c index 9ebace32cb..2943e05b18 100644 --- a/source4/auth/kerberos/kerberos_pac.c +++ b/source4/auth/kerberos/kerberos_pac.c @@ -32,11 +32,11 @@ #include "auth/auth_sam_reply.h" #include "param/param.h" -static krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx, - DATA_BLOB pac_data, - struct PAC_SIGNATURE_DATA *sig, - krb5_context context, - const krb5_keyblock *keyblock) +krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx, + DATA_BLOB pac_data, + struct PAC_SIGNATURE_DATA *sig, + krb5_context context, + const krb5_keyblock *keyblock) { krb5_error_code ret; krb5_crypto crypto; diff --git a/source4/build/m4/public.m4 b/source4/build/m4/public.m4 index d932f09a69..d61e00b22e 100644 --- a/source4/build/m4/public.m4 +++ b/source4/build/m4/public.m4 @@ -155,16 +155,22 @@ SMB_INFO_ENABLES="$SMB_INFO_ENABLES \$enabled{$1} = \"$2\";" ]) -dnl SMB_WRITE_MAKEVARS(path) +dnl SMB_WRITE_MAKEVARS(path, skip_vars) AC_DEFUN([SMB_WRITE_MAKEVARS], [ echo "configure: creating $1" cat >$1<<CEOF # $1 - Autogenerated by configure, DO NOT EDIT! -AC_FOREACH([AC_Var], m4_defn([_AC_SUBST_VARS]), [ -AC_Var = $AC_Var]) $MAKE_SETTINGS CEOF +skip_vars=" $2 " +for ac_var in $ac_subst_vars +do + eval ac_val=\$$ac_var + if echo "$skip_vars" | grep -v " $ac_var " >/dev/null 2>/dev/null; then + echo "$ac_var = $ac_val" >> $1 + fi +done ]) dnl SMB_WRITE_PERLVARS(path) diff --git a/source4/build/smb_build/main.pl b/source4/build/smb_build/main.pl index f8a0cb004f..3c84a91a59 100644 --- a/source4/build/smb_build/main.pl +++ b/source4/build/smb_build/main.pl @@ -31,7 +31,9 @@ my $mkfile = smb_build::config_mk::run_config_mk($INPUT, $config::config{srcdir} my $subsys_output_type = ["MERGED_OBJ"]; my $library_output_type; -if ($config::config{USESHARED} eq "true") { +my $useshared = (defined($ENV{USESHARED})?$ENV{USESHARED}:$config::config{USESHARED}); + +if ($useshared eq "true") { $library_output_type = ["SHARED_LIBRARY", "MERGED_OBJ"]; } else { $library_output_type = ["MERGED_OBJ"]; @@ -40,7 +42,7 @@ if ($config::config{USESHARED} eq "true") { } my $module_output_type; -if ($config::config{USESHARED} eq "true") { +if ($useshared eq "true") { $module_output_type = ["SHARED_LIBRARY"]; } else { $module_output_type = ["MERGED_OBJ"]; diff --git a/source4/dynconfig/config.mk b/source4/dynconfig/config.mk index 4956fda519..b10018384f 100644 --- a/source4/dynconfig/config.mk +++ b/source4/dynconfig/config.mk @@ -1,7 +1,6 @@ [SUBSYSTEM::DYNCONFIG] -DYNCONFIG_OBJ_FILES = $(dynconfigsrcdir)/dynconfig.o \ - $(dynconfigsrcdir)/version.o +DYNCONFIG_OBJ_FILES = $(dynconfigsrcdir)/dynconfig.o # set these to where to find various files # These can be overridden by command line switches (see smbd(8)) diff --git a/source4/dynconfig/version.c b/source4/dynconfig/version.c deleted file mode 100644 index e81f463586..0000000000 --- a/source4/dynconfig/version.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Samba Version functions - - Copyright (C) Stefan Metzmacher 2003 - - 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 3 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, see <http://www.gnu.org/licenses/>. -*/ - -#include "includes.h" -#include "version.h" - -const char *samba_version_string(void) -{ - return SAMBA_VERSION_STRING; -} diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c index 6675647736..9379c6fdf1 100644 --- a/source4/heimdal/lib/krb5/crypto.c +++ b/source4/heimdal/lib/krb5/crypto.c @@ -2678,37 +2678,6 @@ krb5_enctype_to_keytype(krb5_context context, } krb5_error_code KRB5_LIB_FUNCTION -krb5_keytype_to_enctypes (krb5_context context, - krb5_keytype keytype, - unsigned *len, - krb5_enctype **val) -{ - int i; - unsigned n = 0; - krb5_enctype *ret; - - for (i = num_etypes - 1; i >= 0; --i) { - if (etypes[i]->keytype->type == keytype - && !(etypes[i]->flags & F_PSEUDO)) - ++n; - } - ret = malloc(n * sizeof(*ret)); - if (ret == NULL && n != 0) { - krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); - return ENOMEM; - } - n = 0; - for (i = num_etypes - 1; i >= 0; --i) { - if (etypes[i]->keytype->type == keytype - && !(etypes[i]->flags & F_PSEUDO)) - ret[n++] = etypes[i]->type; - } - *len = n; - *val = ret; - return 0; -} - -krb5_error_code KRB5_LIB_FUNCTION krb5_enctype_valid(krb5_context context, krb5_enctype etype) { @@ -2728,6 +2697,44 @@ krb5_enctype_valid(krb5_context context, return 0; } +/** + * Return the coresponding encryption type for a checksum type. + * + * @param context Kerberos context + * @param ctype The checksum type to get the result enctype for + * @param etype The returned encryption, when the matching etype is + * not found, etype is set to ETYPE_NULL. + * + * @return Return an error code for an failure or 0 on success. + * @ingroup krb5_crypto + */ + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cksumtype_to_enctype(krb5_context context, + krb5_cksumtype ctype, + krb5_enctype *etype) +{ + int i; + + *etype = ETYPE_NULL; + + for(i = 0; i < num_etypes; i++) { + if(etypes[i]->keyed_checksum && + etypes[i]->keyed_checksum->type == ctype) + { + *etype = etypes[i]->type; + return 0; + } + } + + krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, + "ckecksum type %d not supported", + (int)ctype); + return KRB5_PROG_SUMTYPE_NOSUPP; +} + + krb5_error_code KRB5_LIB_FUNCTION krb5_cksumtype_valid(krb5_context context, krb5_cksumtype ctype) @@ -3491,7 +3498,6 @@ krb5_decrypt_iov_ivec(krb5_context context, return 0; } - size_t KRB5_LIB_FUNCTION krb5_crypto_length(krb5_context context, krb5_crypto crypto, @@ -4562,4 +4568,36 @@ krb5_string_to_keytype(krb5_context context, "key type %s not supported", string); return KRB5_PROG_KEYTYPE_NOSUPP; } + +krb5_error_code KRB5_LIB_FUNCTION +krb5_keytype_to_enctypes (krb5_context context, + krb5_keytype keytype, + unsigned *len, + krb5_enctype **val) +{ + int i; + unsigned n = 0; + krb5_enctype *ret; + + for (i = num_etypes - 1; i >= 0; --i) { + if (etypes[i]->keytype->type == keytype + && !(etypes[i]->flags & F_PSEUDO)) + ++n; + } + ret = malloc(n * sizeof(*ret)); + if (ret == NULL && n != 0) { + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); + return ENOMEM; + } + n = 0; + for (i = num_etypes - 1; i >= 0; --i) { + if (etypes[i]->keytype->type == keytype + && !(etypes[i]->flags & F_PSEUDO)) + ret[n++] = etypes[i]->type; + } + *len = n; + *val = ret; + return 0; +} + #endif diff --git a/source4/kdc/kdc.c b/source4/kdc/kdc.c index dfd62c55a4..5d7b48afe4 100644 --- a/source4/kdc/kdc.c +++ b/source4/kdc/kdc.c @@ -33,9 +33,12 @@ #include "lib/messaging/irpc.h" #include "lib/stream/packet.h" #include "librpc/gen_ndr/samr.h" +#include "librpc/gen_ndr/ndr_irpc.h" +#include "librpc/gen_ndr/ndr_krb5pac.h" #include "lib/socket/netif.h" #include "param/param.h" #include "kdc/kdc.h" +#include "librpc/gen_ndr/ndr_misc.h" /* Disgusting hack to get a mem_ctx and lp_ctx into the hdb plugin, when @@ -555,6 +558,108 @@ static struct krb5plugin_windc_ftable windc_plugin_table = { }; +static NTSTATUS kdc_check_generic_kerberos(struct irpc_message *msg, + struct kdc_check_generic_kerberos *r) +{ + struct PAC_Validate pac_validate; + DATA_BLOB srv_sig; + struct PAC_SIGNATURE_DATA kdc_sig; + struct kdc_server *kdc = talloc_get_type(msg->private, struct kdc_server); + enum ndr_err_code ndr_err; + krb5_enctype etype; + int ret; + hdb_entry_ex ent; + krb5_principal principal; + krb5_keyblock keyblock; + Key *key; + + /* There is no reply to this request */ + r->out.generic_reply = data_blob(NULL, 0); + + ndr_err = ndr_pull_struct_blob(&r->in.generic_request, msg, + lp_iconv_convenience(kdc->task->lp_ctx), + &pac_validate, + (ndr_pull_flags_fn_t)ndr_pull_PAC_Validate); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + return NT_STATUS_INVALID_PARAMETER; + } + +#if 0 + /* Windows does not check this */ + if (pac_validate.MessageType != 3) { + /* We don't implement any other message types - such as certificate validation - yet */ + return NT_STATUS_INVALID_PARAMETER; + } +#endif + if (pac_validate.ChecksumAndSignature.length != (pac_validate.ChecksumLength + pac_validate.SignatureLength) + || pac_validate.ChecksumAndSignature.length < pac_validate.ChecksumLength + || pac_validate.ChecksumAndSignature.length < pac_validate.SignatureLength ) { + return NT_STATUS_INVALID_PARAMETER; + } + + srv_sig = data_blob_const(pac_validate.ChecksumAndSignature.data, + pac_validate.ChecksumLength); + + if (pac_validate.SignatureType == CKSUMTYPE_HMAC_MD5) { + etype = ETYPE_ARCFOUR_HMAC_MD5; + } else { + ret = krb5_cksumtype_to_enctype(kdc->smb_krb5_context->krb5_context, pac_validate.SignatureType, + &etype); + if (ret != 0) { + return NT_STATUS_LOGON_FAILURE; + } + } + + ret = krb5_make_principal(kdc->smb_krb5_context->krb5_context, &principal, + lp_realm(kdc->task->lp_ctx), + "krbtgt", lp_realm(kdc->task->lp_ctx), + NULL); + + if (ret != 0) { + return NT_STATUS_NO_MEMORY; + } + + ret = kdc->config->db[0]->hdb_fetch(kdc->smb_krb5_context->krb5_context, + kdc->config->db[0], + principal, + HDB_F_GET_KRBTGT | HDB_F_DECRYPT, + &ent); + + if (ret != 0) { + hdb_free_entry(kdc->smb_krb5_context->krb5_context, &ent); + krb5_free_principal(kdc->smb_krb5_context->krb5_context, principal); + + return NT_STATUS_LOGON_FAILURE; + } + + ret = hdb_enctype2key(kdc->smb_krb5_context->krb5_context, &ent.entry, etype, &key); + + if (ret != 0) { + hdb_free_entry(kdc->smb_krb5_context->krb5_context, &ent); + krb5_free_principal(kdc->smb_krb5_context->krb5_context, principal); + return NT_STATUS_LOGON_FAILURE; + } + + keyblock = key->key; + + kdc_sig.type = pac_validate.SignatureType; + kdc_sig.signature = data_blob_const(&pac_validate.ChecksumAndSignature.data[pac_validate.ChecksumLength], + pac_validate.SignatureLength); + ret = check_pac_checksum(msg, srv_sig, &kdc_sig, + kdc->smb_krb5_context->krb5_context, &keyblock); + + hdb_free_entry(kdc->smb_krb5_context->krb5_context, &ent); + krb5_free_principal(kdc->smb_krb5_context->krb5_context, principal); + + if (ret != 0) { + return NT_STATUS_LOGON_FAILURE; + } + + return NT_STATUS_OK; +} + + + /* startup the kdc task */ @@ -656,6 +761,13 @@ static void kdc_task_init(struct task_server *task) return; } + status = IRPC_REGISTER(task->msg_ctx, irpc, KDC_CHECK_GENERIC_KERBEROS, + kdc_check_generic_kerberos, kdc); + if (!NT_STATUS_IS_OK(status)) { + task_server_terminate(task, "nbtd failed to setup monitoring"); + return; + } + irpc_add_name(task->msg_ctx, "kdc_server"); } diff --git a/source4/lib/zlib.mk b/source4/lib/zlib.mk index 095f129feb..5c5e6e69ba 100644 --- a/source4/lib/zlib.mk +++ b/source4/lib/zlib.mk @@ -1,17 +1,16 @@ [SUBSYSTEM::ZLIB] -CFLAGS = -Ilib/zlib +CFLAGS = -I$(zlibsrcdir) -libzlibsrcdir := lib/zlib ZLIB_OBJ_FILES = \ - $(libzlibsrcdir)/adler32.o \ - $(libzlibsrcdir)/compress.o \ - $(libzlibsrcdir)/crc32.o \ - $(libzlibsrcdir)/gzio.o \ - $(libzlibsrcdir)/uncompr.o \ - $(libzlibsrcdir)/deflate.o \ - $(libzlibsrcdir)/trees.o \ - $(libzlibsrcdir)/zutil.o \ - $(libzlibsrcdir)/inflate.o \ - $(libzlibsrcdir)/infback.o \ - $(libzlibsrcdir)/inftrees.o \ - $(libzlibsrcdir)/inffast.o + $(zlibsrcdir)/adler32.o \ + $(zlibsrcdir)/compress.o \ + $(zlibsrcdir)/crc32.o \ + $(zlibsrcdir)/gzio.o \ + $(zlibsrcdir)/uncompr.o \ + $(zlibsrcdir)/deflate.o \ + $(zlibsrcdir)/trees.o \ + $(zlibsrcdir)/zutil.o \ + $(zlibsrcdir)/inflate.o \ + $(zlibsrcdir)/infback.o \ + $(zlibsrcdir)/inftrees.o \ + $(zlibsrcdir)/inffast.o diff --git a/source4/librpc/idl/irpc.idl b/source4/librpc/idl/irpc.idl index 2c659aa785..e3ea7e55e1 100644 --- a/source4/librpc/idl/irpc.idl +++ b/source4/librpc/idl/irpc.idl @@ -52,6 +52,9 @@ import "misc.idl", "security.idl", "nbt.idl"; [out,switch_is(level)] nbtd_info info ); + /* Send a GetDCName from the privilaged port (owned by nbtd), + * and await a reply */ + void nbtd_getdcname( [in] astring domainname, [in] astring ip_address, @@ -78,6 +81,20 @@ import "misc.idl", "security.idl", "nbt.idl"; [in] nbtd_proxy_wins_addr addrs[num_addrs] ); + /* + Generic Kerberos package call (on the NETLOGON pipe, as a SamLogon) + + The normal use for this call is to check the PAC signature in the KDC + + The KDC has the routines to check this, so it is easier to + proxy the request over by IRPC than set up the environment + */ + + void kdc_check_generic_kerberos( + [in] DATA_BLOB generic_request, + [out] DATA_BLOB generic_reply + ); + /****************************************************** management calls for the smb server ******************************************************/ diff --git a/source4/librpc/idl/krb5pac.idl b/source4/librpc/idl/krb5pac.idl index dcee280150..bddba04165 100644 --- a/source4/librpc/idl/krb5pac.idl +++ b/source4/librpc/idl/krb5pac.idl @@ -105,7 +105,7 @@ interface krb5pac typedef [public] struct { [value(NETLOGON_GENERIC_KRB5_PAC_VALIDATE)] uint32 MessageType; uint32 ChecksumLength; - uint32 SignatureType; + int32 SignatureType; uint32 SignatureLength; [flag(NDR_REMAINING)] DATA_BLOB ChecksumAndSignature; } PAC_Validate; diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 763e6a327e..36ac650b08 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -34,6 +34,8 @@ #include "auth/gensec/schannel_state.h" #include "libcli/security/security.h" #include "param/param.h" +#include "lib/messaging/irpc.h" +#include "librpc/gen_ndr/ndr_irpc.h" struct server_pipe_state { struct netr_Credential client_challenge; @@ -488,7 +490,48 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_cal case NetlogonGenericInformation: { - /* Until we get enough information for an implemetnation */ + if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) { + creds_arcfour_crypt(creds, + r->in.logon.generic->data, r->in.logon.generic->length); + } else { + /* Using DES to verify kerberos tickets makes no sense */ + return NT_STATUS_INVALID_PARAMETER; + } + + if (strcmp(r->in.logon.generic->package_name.string, "Kerberos") == 0) { + NTSTATUS status; + struct server_id *kdc; + struct kdc_check_generic_kerberos check; + struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2); + NT_STATUS_HAVE_NO_MEMORY(generic); + r->out.authoritative = 1; + + /* TODO: Describe and deal with these flags */ + r->out.flags = 0; + + r->out.validation.generic = generic; + + kdc = irpc_servers_byname(dce_call->msg_ctx, mem_ctx, "kdc_server"); + if ((kdc == NULL) || (kdc[0].id == 0)) { + return NT_STATUS_NO_LOGON_SERVERS; + } + + check.in.generic_request = + data_blob_const(r->in.logon.generic->data, + r->in.logon.generic->length); + + status = irpc_call(dce_call->msg_ctx, kdc[0], + &ndr_table_irpc, NDR_KDC_CHECK_GENERIC_KERBEROS, + &check, mem_ctx); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + generic->length = check.out.generic_reply.length; + generic->data = check.out.generic_reply.data; + return NT_STATUS_OK; + } + + /* Until we get an implemetnation of these other packages */ return NT_STATUS_INVALID_PARAMETER; } default: diff --git a/source4/samba4-skip b/source4/samba4-skip index 35b274f63f..b1313adea0 100644 --- a/source4/samba4-skip +++ b/source4/samba4-skip @@ -41,7 +41,6 @@ ntvfs.cifs.raw.context ntvfs.cifs.raw.qfileinfo.ipc rpc.dssync rpc.samsync -rpc.pac # Not finished yet ldap.uptodatevector # Segfaults rpc.remact # Not provided by Samba 4 rpc.oxidresolve # Not provided by Samba 4 diff --git a/source4/scripting/python/misc.i b/source4/scripting/python/misc.i index f0bc156abd..81be7d5c16 100644 --- a/source4/scripting/python/misc.i +++ b/source4/scripting/python/misc.i @@ -26,6 +26,7 @@ #include "dsdb/samdb/samdb.h" #include "lib/ldb-samba/ldif_handlers.h" #include "librpc/ndr/libndr.h" +#include "version.h" %} %import "stdint.i" @@ -77,10 +78,15 @@ bool samdb_set_domain_sid(struct ldb_context *ldb, WERROR dsdb_attach_schema_from_ldif_file(struct ldb_context *ldb, const char *pf, const char *df); -%feature("docstring") samba_version_string "version()\n" - "Obtain the Samba version."; -%rename(version) samba_version_string; -const char *samba_version_string(void); +%feature("docstring") version "version()\n" + "Obtain the Samba version."; + +%inline { +const char *version(void) +{ + return SAMBA_VERSION_STRING; +} +} int dsdb_set_global_schema(struct ldb_context *ldb); %feature("docstring") ldb_register_samba_handlers "register_samba_handlers()\n" "Register Samba-specific LDB modules and schemas."; diff --git a/source4/scripting/python/misc_wrap.c b/source4/scripting/python/misc_wrap.c index 4b5bfb0174..3aee83f72c 100644 --- a/source4/scripting/python/misc_wrap.c +++ b/source4/scripting/python/misc_wrap.c @@ -2558,6 +2558,7 @@ static swig_module_info swig_module = {swig_types, 27, 0, 0, 0, 0}; #include "dsdb/samdb/samdb.h" #include "lib/ldb-samba/ldif_handlers.h" #include "librpc/ndr/libndr.h" +#include "version.h" #include "libcli/util/pyerrors.h" @@ -2813,6 +2814,12 @@ SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc) +const char *version(void) +{ + return SAMBA_VERSION_STRING; +} + + #define SWIG_From_long PyInt_FromLong @@ -3109,7 +3116,7 @@ SWIGINTERN PyObject *_wrap_version(PyObject *SWIGUNUSEDPARM(self), PyObject *arg char *result = 0 ; if (!SWIG_Python_UnpackTuple(args,"version",0,0,0)) SWIG_fail; - result = (char *)samba_version_string(); + result = (char *)version(); resultobj = SWIG_FromCharPtr((const char *)result); return resultobj; fail: diff --git a/source4/torture/rpc/remote_pac.c b/source4/torture/rpc/remote_pac.c index 58c8ba0ee0..6419e40014 100644 --- a/source4/torture/rpc/remote_pac.c +++ b/source4/torture/rpc/remote_pac.c @@ -68,6 +68,8 @@ static bool test_PACVerify(struct torture_context *tctx, TALLOC_CTX *tmp_ctx = talloc_new(tctx); + int i; + torture_assert(tctx, tmp_ctx != NULL, "talloc_new() failed"); if (!test_SetupCredentials2(p, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, @@ -157,6 +159,9 @@ static bool test_PACVerify(struct torture_context *tctx, torture_assert(tctx, (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR), "not willing to even try a PACValidate without RC4 encryption"); creds_arcfour_crypt(creds, pac_wrapped.data, pac_wrapped.length); + generic.length = pac_wrapped.length; + generic.data = pac_wrapped.data; + /* Validate it over the netlogon pipe */ generic.identity_info.parameter_control = 0; @@ -167,8 +172,6 @@ static bool test_PACVerify(struct torture_context *tctx, generic.identity_info.workstation.string = TEST_MACHINE_NAME; generic.package_name.string = "Kerberos"; - generic.length = pac_wrapped.length; - generic.data = pac_wrapped.data; ZERO_STRUCT(auth2); creds_client_authenticator(creds, &auth); @@ -184,9 +187,183 @@ static bool test_PACVerify(struct torture_context *tctx, torture_assert_ntstatus_ok(tctx, status, "LogonSamLogon failed"); + /* This will break the signature nicely (even in the crypto wrapping), check we get a logon failure */ + generic.data[generic.length-1]++; + + ZERO_STRUCT(auth2); + creds_client_authenticator(creds, &auth); + r.in.credential = &auth; + r.in.return_authenticator = &auth2; + r.in.logon_level = NetlogonGenericInformation; + r.in.logon.generic = &generic; + r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p)); + r.in.computer_name = cli_credentials_get_workstation(credentials); + r.in.validation_level = NetlogonValidationGenericInfo2; + + status = dcerpc_netr_LogonSamLogon(p, tctx, &r); + + torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOGON_FAILURE, "LogonSamLogon failed"); + + torture_assert(tctx, creds_client_check(creds, &r.out.return_authenticator->cred), + "Credential chaining failed"); + + /* This will break message type, check that however we still get NT_STATUS_OK */ + for (i=0; i < 256; i++) { + pac_wrapped_struct.MessageType = i; + pac_wrapped_struct.ChecksumLength = session_info->server_info->pac_srv_sig.signature.length; + pac_wrapped_struct.SignatureType = session_info->server_info->pac_kdc_sig.type; + pac_wrapped_struct.SignatureLength = session_info->server_info->pac_kdc_sig.signature.length; + pac_wrapped_struct.ChecksumAndSignature = payload + = data_blob_talloc(tmp_ctx, NULL, + pac_wrapped_struct.ChecksumLength + + pac_wrapped_struct.SignatureLength); + memcpy(&payload.data[0], + session_info->server_info->pac_srv_sig.signature.data, + pac_wrapped_struct.ChecksumLength); + memcpy(&payload.data[pac_wrapped_struct.ChecksumLength], + session_info->server_info->pac_kdc_sig.signature.data, + pac_wrapped_struct.SignatureLength); + + ndr_err = ndr_push_struct_blob(&pac_wrapped, tmp_ctx, lp_iconv_convenience(tctx->lp_ctx), &pac_wrapped_struct, + (ndr_push_flags_fn_t)ndr_push_PAC_Validate); + torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "ndr_push_struct_blob of PACValidate structure failed"); + + torture_assert(tctx, (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR), "not willing to even try a PACValidate without RC4 encryption"); + creds_arcfour_crypt(creds, pac_wrapped.data, pac_wrapped.length); + + generic.length = pac_wrapped.length; + generic.data = pac_wrapped.data; + + ZERO_STRUCT(auth2); + creds_client_authenticator(creds, &auth); + r.in.credential = &auth; + r.in.return_authenticator = &auth2; + r.in.logon_level = NetlogonGenericInformation; + r.in.logon.generic = &generic; + r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p)); + r.in.computer_name = cli_credentials_get_workstation(credentials); + r.in.validation_level = NetlogonValidationGenericInfo2; + + status = dcerpc_netr_LogonSamLogon(p, tctx, &r); + + torture_assert_ntstatus_ok(tctx, status, "LogonSamLogon failed"); + + torture_assert(tctx, creds_client_check(creds, &r.out.return_authenticator->cred), + "Credential chaining failed"); + } + + /* This will break the parsing nicely (even in the crypto wrapping), check we get INVALID_PARAMETER */ + generic.length--; + + ZERO_STRUCT(auth2); + creds_client_authenticator(creds, &auth); + r.in.credential = &auth; + r.in.return_authenticator = &auth2; + r.in.logon_level = NetlogonGenericInformation; + r.in.logon.generic = &generic; + r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p)); + r.in.computer_name = cli_credentials_get_workstation(credentials); + r.in.validation_level = NetlogonValidationGenericInfo2; + + status = dcerpc_netr_LogonSamLogon(p, tctx, &r); + + torture_assert_ntstatus_equal(tctx, status, NT_STATUS_INVALID_PARAMETER, "LogonSamLogon failed"); + + torture_assert(tctx, creds_client_check(creds, &r.out.return_authenticator->cred), + "Credential chaining failed"); + + pac_wrapped_struct.MessageType = 0x3; + pac_wrapped_struct.ChecksumLength = session_info->server_info->pac_srv_sig.signature.length; + pac_wrapped_struct.SignatureType = session_info->server_info->pac_kdc_sig.type; + + /* Break the SignatureType */ + pac_wrapped_struct.SignatureType++; + + pac_wrapped_struct.SignatureLength = session_info->server_info->pac_kdc_sig.signature.length; + pac_wrapped_struct.ChecksumAndSignature = payload + = data_blob_talloc(tmp_ctx, NULL, + pac_wrapped_struct.ChecksumLength + + pac_wrapped_struct.SignatureLength); + memcpy(&payload.data[0], + session_info->server_info->pac_srv_sig.signature.data, + pac_wrapped_struct.ChecksumLength); + memcpy(&payload.data[pac_wrapped_struct.ChecksumLength], + session_info->server_info->pac_kdc_sig.signature.data, + pac_wrapped_struct.SignatureLength); + + ndr_err = ndr_push_struct_blob(&pac_wrapped, tmp_ctx, lp_iconv_convenience(tctx->lp_ctx), &pac_wrapped_struct, + (ndr_push_flags_fn_t)ndr_push_PAC_Validate); + torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "ndr_push_struct_blob of PACValidate structure failed"); + + torture_assert(tctx, (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR), "not willing to even try a PACValidate without RC4 encryption"); + creds_arcfour_crypt(creds, pac_wrapped.data, pac_wrapped.length); + + generic.length = pac_wrapped.length; + generic.data = pac_wrapped.data; + + ZERO_STRUCT(auth2); + creds_client_authenticator(creds, &auth); + r.in.credential = &auth; + r.in.return_authenticator = &auth2; + r.in.logon_level = NetlogonGenericInformation; + r.in.logon.generic = &generic; + r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p)); + r.in.computer_name = cli_credentials_get_workstation(credentials); + r.in.validation_level = NetlogonValidationGenericInfo2; + + status = dcerpc_netr_LogonSamLogon(p, tctx, &r); + + torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOGON_FAILURE, "LogonSamLogon failed"); + torture_assert(tctx, creds_client_check(creds, &r.out.return_authenticator->cred), "Credential chaining failed"); + + pac_wrapped_struct.MessageType = 0x3; + pac_wrapped_struct.ChecksumLength = session_info->server_info->pac_srv_sig.signature.length; + pac_wrapped_struct.SignatureType = session_info->server_info->pac_kdc_sig.type; + pac_wrapped_struct.SignatureLength = session_info->server_info->pac_kdc_sig.signature.length; + + pac_wrapped_struct.ChecksumAndSignature = payload + = data_blob_talloc(tmp_ctx, NULL, + pac_wrapped_struct.ChecksumLength + + pac_wrapped_struct.SignatureLength); + memcpy(&payload.data[0], + session_info->server_info->pac_srv_sig.signature.data, + pac_wrapped_struct.ChecksumLength); + memcpy(&payload.data[pac_wrapped_struct.ChecksumLength], + session_info->server_info->pac_kdc_sig.signature.data, + pac_wrapped_struct.SignatureLength); + + /* Break the signature length */ + pac_wrapped_struct.SignatureLength++; + + ndr_err = ndr_push_struct_blob(&pac_wrapped, tmp_ctx, lp_iconv_convenience(tctx->lp_ctx), &pac_wrapped_struct, + (ndr_push_flags_fn_t)ndr_push_PAC_Validate); + torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "ndr_push_struct_blob of PACValidate structure failed"); + + torture_assert(tctx, (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR), "not willing to even try a PACValidate without RC4 encryption"); + creds_arcfour_crypt(creds, pac_wrapped.data, pac_wrapped.length); + + generic.length = pac_wrapped.length; + generic.data = pac_wrapped.data; + + ZERO_STRUCT(auth2); + creds_client_authenticator(creds, &auth); + r.in.credential = &auth; + r.in.return_authenticator = &auth2; + r.in.logon_level = NetlogonGenericInformation; + r.in.logon.generic = &generic; + r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p)); + r.in.computer_name = cli_credentials_get_workstation(credentials); + r.in.validation_level = NetlogonValidationGenericInfo2; + + status = dcerpc_netr_LogonSamLogon(p, tctx, &r); + + torture_assert_ntstatus_equal(tctx, status, NT_STATUS_INVALID_PARAMETER, "LogonSamLogon failed"); + + torture_assert(tctx, creds_client_check(creds, &r.out.return_authenticator->cred), + "Credential chaining failed"); return true; } |