The branch, master has been updated via 7791acb074b python: Make credentials cache test run against Windows via b9006f33343 python: Fix ticket timestamp conversion when local timezone is not UTC via 66695f0f947 python: Fix erroneous increments of reference counts via 290c1dc0975 python: Ensure reference counts are properly incremented via 78a0b57b516 python: Add SMB credentials cache test via 482559436f1 pylibsmb: Add posix_whoami() via 9b96ebea5c6 libsmb: Ensure that whoami parses all the data provided to it via 9e414233c84 libsmb: Check to see that whoami is not receiving more data than it requested via 9d8aeed33d8 libsmb: Avoid undefined behaviour when parsing whoami state via db5b34c7682 libsmb: Remove overflow check via 2b487890d94 Revert "libsmb: Use sid_parse()" via 072451a033d python: Add RPC credentials cache test via 7663b5c37fa python: Add LDAP credentials cache test via c15f26ec408 python: Add credentials cache test via 2d88a6ff3db krb5: Add Python functions to create a credentials cache containing a service ticket via 1f17b1edca9 librpc: Test parsing a Kerberos 5 credentials cache with ndrdump via 74fb2cc473c krb5ccache.idl: Add definition for a Kerberos credentials cache via 6f144d49b52 Revert "s4-test: fixed ndrdump test for top level build" via 50ade4cadc7 pygensec: Fix method documentation via 2d05268aa09 auth:creds: Fix parameter in creds.set_named_ccache() via 1ea2de56183 auth:creds: Remove unused variable from 28679507219 s3: lib: Fix the solaris build. Commit 8d0ea8bafa00 added SMB_ACL_TYPE_T type to solarisacl_sys_acl_set_fd() in the .c file, but not the .h.
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 7791acb074b84ec7b571a81f15b56d33e2214ce9 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Mon May 10 15:06:06 2021 +1200 python: Make credentials cache test run against Windows Windows, unlike Samba, requires the service principal name to be set when requesting a ticket to that service. Additionally, default_realm from the libdefaults section of krb5.conf should be set so that the correct realm is used. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Autobuild-User(master): Jeremy Allison <j...@samba.org> Autobuild-Date(master): Wed May 19 02:22:01 UTC 2021 on sn-devel-184 commit b9006f33343ba8bb82ef8ffe1fd90c780961b41e Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Mon May 10 16:43:03 2021 +1200 python: Fix ticket timestamp conversion when local timezone is not UTC Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 66695f0f94775c4db24fb625fe78ff44d964b5ad Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Mon May 3 14:43:04 2021 +1200 python: Fix erroneous increments of reference counts Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 290c1dc0975867a71c02e911708323d1f38b6f96 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Mon May 3 14:42:10 2021 +1200 python: Ensure reference counts are properly incremented Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 78a0b57b51642df07deed8aeb6e39e608fafda60 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Fri Apr 30 08:58:11 2021 +1200 python: Add SMB credentials cache test Test that we can use a credentials cache with a user's service ticket obtained with our Python code to connect to a service through SMB. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 482559436f12a85adb3409433aac3ab06baa82b1 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Fri Apr 30 12:49:24 2021 +1200 pylibsmb: Add posix_whoami() Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 9b96ebea5c6966b096cf1100a0895a9c41f2aa1d Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Mon May 3 16:24:42 2021 +1200 libsmb: Ensure that whoami parses all the data provided to it Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 9e414233c84d2f2fa4a9415be9ee975eca8b9bfd Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Mon May 3 16:22:43 2021 +1200 libsmb: Check to see that whoami is not receiving more data than it requested Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 9d8aeed33d8edf7a5dc96dbe35e4e164e2baeeeb Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Mon May 3 16:16:51 2021 +1200 libsmb: Avoid undefined behaviour when parsing whoami state If num_gids is such that the gids array would overflow the rdata buffer, 'p + 8' could produce a result pointing outside the buffer, and thus result in undefined behaviour. To avoid this, we check num_gids against the size of the buffer beforehand. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit db5b34c7682e36630908356cf674fddd18d8fa1f Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Mon May 3 15:55:01 2021 +1200 libsmb: Remove overflow check Pointer overflow is undefined, so this check does not accomplish anything. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 2b487890d946df88abce67c3d07d74559f70f069 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Mon May 3 15:48:43 2021 +1200 Revert "libsmb: Use sid_parse()" This reverts commit afd5d34f5e1d13ba88448b3b94d353aa8361d1a9. This code originally used ndr_pull_struct_blob() to pull one SID from a buffer potentially containing multiple SIDs. When this was changed to use sid_parse(), it was now attempting to parse the whole buffer as a single SID with ndr_pull_struct_blob_all(), which would cause it to fail if more than one SID was present. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 072451a033da07c0cdaa005dd1020ef1c7951e99 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Apr 29 21:04:25 2021 +1200 python: Add RPC credentials cache test Test that we can use a credentials cache with a user's service ticket obtained with our Python code to connect to a service through RPC. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 7663b5c37fa3413f7c67c018107322494e4a6fd9 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Apr 29 20:58:11 2021 +1200 python: Add LDAP credentials cache test Test that we can use a credentials cache with a user's service ticket obtained with our Python code to connect to a service through LDAP. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit c15f26ec40860782b22e862f9bdf665745387718 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Wed Apr 28 11:06:33 2021 +1200 python: Add credentials cache test Test that we can use a credentials cache with a user's service ticket obtained with our Python code to connect to a service using the normal credentials system backed on to MIT/Heimdal Kerberos 5 libraries. This will allow us to validate the output of the MIT/Heimdal libraries in the future. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 2d88a6ff3dbcf650b09ef9c8c37170ca6663b533 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Wed Apr 28 11:02:47 2021 +1200 krb5: Add Python functions to create a credentials cache containing a service ticket This is a FILE: format credentials cache readable by the MIT/Heimdal Kerberos libraries. This allows us to glue the Python ASN1 Kerberos system to the MIT/Heimdal one. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 1f17b1edca9c1638ef404fadce3ca7a4d176de12 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Wed Apr 28 10:58:48 2021 +1200 librpc: Test parsing a Kerberos 5 credentials cache with ndrdump This is the format used by the FILE: credentials cache type. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 74fb2cc473cea0eebf641fc4d32d706bac8aa6f2 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Wed Apr 28 10:57:00 2021 +1200 krb5ccache.idl: Add definition for a Kerberos credentials cache Based on specifications found at https://web.mit.edu/kerberos/krb5-devel/doc/formats/ccache_file_format.html This is primarily designed for parsing and storing a single Kerberos ticket, due to the limitations of PIDL. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 6f144d49b5281a08bf7be550b949f4d91e8fe19b Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Apr 15 10:32:41 2021 +1200 Revert "s4-test: fixed ndrdump test for top level build" This essentially reverts commit b84c0a9ed6d556eb2d3797d606edcd03f9766606, but the datapath is now in the source4 directory. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 50ade4cadc766a196316fd5c5a57f8c502f0ea22 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Wed Apr 28 11:07:22 2021 +1200 pygensec: Fix method documentation This changes the docstrings to use the correct method names. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 2d05268aa0904221c452fc650fcdfb680efc20bb Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Wed Apr 28 10:55:13 2021 +1200 auth:creds: Fix parameter in creds.set_named_ccache() Use the passed-in value for 'obtained' rather than always using CRED_SPECIFIED. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 1ea2de561839ad948efab5112fbe4c1eae44d9ee Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Wed Apr 28 10:54:05 2021 +1200 auth:creds: Remove unused variable Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> ----------------------------------------------------------------------- Summary of changes: auth/credentials/pycredentials.c | 6 +- lib/talloc/pytalloc.c | 4 +- libgpo/pygpo.c | 2 +- librpc/idl/krb5ccache.idl | 115 ++ librpc/idl/wscript_build | 1 + librpc/wscript_build | 8 +- python/samba/tests/blackbox/ndrdump.py | 45 +- python/samba/tests/krb5/kdc_base_test.py | 182 ++- python/samba/tests/krb5/raw_testcase.py | 8 +- python/samba/tests/krb5/rfc4120_constants.py | 1 + python/samba/tests/krb5/test_ccache.py | 130 +++ python/samba/tests/krb5/test_ldap.py | 94 ++ python/samba/tests/krb5/test_rpc.py | 77 ++ python/samba/tests/krb5/test_smb.py | 108 ++ python/samba/tests/usage.py | 4 + source3/libsmb/clifsinfo.c | 44 +- source3/libsmb/pylibsmb.c | 139 ++- source3/passdb/py_passdb.c | 4 - source3/selftest/ktest-krb5_ccache-2.txt | 1574 ++++++++++++++++++++++++++ source3/selftest/ktest-krb5_ccache-3.txt | 832 ++++++++++++++ source4/auth/gensec/pygensec.c | 12 +- source4/librpc/ndr/py_security.c | 2 +- source4/librpc/wscript_build | 7 + source4/ntvfs/posix/python/pyposix_eadb.c | 2 +- source4/ntvfs/posix/python/pyxattr_native.c | 4 +- source4/ntvfs/posix/python/pyxattr_tdb.c | 2 +- source4/selftest/tests.py | 5 + 27 files changed, 3362 insertions(+), 50 deletions(-) create mode 100644 librpc/idl/krb5ccache.idl create mode 100755 python/samba/tests/krb5/test_ccache.py create mode 100755 python/samba/tests/krb5/test_ldap.py create mode 100755 python/samba/tests/krb5/test_rpc.py create mode 100755 python/samba/tests/krb5/test_smb.py create mode 100644 source3/selftest/ktest-krb5_ccache-2.txt create mode 100644 source3/selftest/ktest-krb5_ccache-3.txt Changeset truncated at 500 lines: diff --git a/auth/credentials/pycredentials.c b/auth/credentials/pycredentials.c index 0ba2618cec9..566405a08ee 100644 --- a/auth/credentials/pycredentials.c +++ b/auth/credentials/pycredentials.c @@ -602,8 +602,6 @@ static PyObject *py_creds_get_forced_sasl_mech(PyObject *self, PyObject *unused) static PyObject *py_creds_set_forced_sasl_mech(PyObject *self, PyObject *args) { char *newval; - enum credentials_obtained obt = CRED_SPECIFIED; - int _obt = obt; struct cli_credentials *creds = PyCredentials_AsCliCredentials(self); if (creds == NULL) { PyErr_Format(PyExc_TypeError, "Credentials expected"); @@ -613,7 +611,6 @@ static PyObject *py_creds_set_forced_sasl_mech(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "s", &newval)) { return NULL; } - obt = _obt; cli_credentials_set_forced_sasl_mech(creds, newval); Py_RETURN_NONE; @@ -801,6 +798,7 @@ static PyObject *py_creds_set_named_ccache(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "s|iO", &newval, &_obt, &py_lp_ctx)) return NULL; + obt = _obt; mem_ctx = talloc_new(NULL); if (mem_ctx == NULL) { @@ -816,7 +814,7 @@ static PyObject *py_creds_set_named_ccache(PyObject *self, PyObject *args) ret = cli_credentials_set_ccache(creds, lp_ctx, - newval, CRED_SPECIFIED, + newval, obt, &error_string); if (ret != 0) { diff --git a/lib/talloc/pytalloc.c b/lib/talloc/pytalloc.c index 15e4232f0c8..41decc45f61 100644 --- a/lib/talloc/pytalloc.c +++ b/lib/talloc/pytalloc.c @@ -41,7 +41,7 @@ static PyObject *pytalloc_report_full(PyObject *self, PyObject *args) } else { talloc_report_full(pytalloc_get_mem_ctx(py_obj), stdout); } - return Py_None; + Py_RETURN_NONE; } /* enable null tracking */ @@ -49,7 +49,7 @@ static PyObject *pytalloc_enable_null_tracking(PyObject *self, PyObject *Py_UNUSED(ignored)) { talloc_enable_null_tracking(); - return Py_None; + Py_RETURN_NONE; } /* return the number of talloc blocks */ diff --git a/libgpo/pygpo.c b/libgpo/pygpo.c index c527143ec70..b5ec85a48d4 100644 --- a/libgpo/pygpo.c +++ b/libgpo/pygpo.c @@ -41,7 +41,7 @@ static PyObject* GPO_get_##ATTR(PyObject *self, void *closure) \ if (gpo_ptr->ATTR) \ return PyUnicode_FromString(gpo_ptr->ATTR); \ else \ - return Py_None; \ + Py_RETURN_NONE; \ } GPO_getter(ds_path) GPO_getter(file_sys_path) diff --git a/librpc/idl/krb5ccache.idl b/librpc/idl/krb5ccache.idl new file mode 100644 index 00000000000..1f0cfa752a9 --- /dev/null +++ b/librpc/idl/krb5ccache.idl @@ -0,0 +1,115 @@ +/* + krb5 credentials cache (version 3 or 4) + specification: https://web.mit.edu/kerberos/krb5-devel/doc/formats/ccache_file_format.html +*/ + +#include "idl_types.h" + +[ + uuid("1702b695-99ca-4f32-93e4-1e1c4d5ddb53"), + version(0.0), + pointer_default(unique), + helpstring("KRB5 credentials cache") +] +interface krb5ccache +{ + typedef struct { + uint32 name_type; + uint32 component_count; + [flag(STR_SIZE4|STR_NOTERM|STR_UTF8)] string realm; + [flag(STR_SIZE4|STR_NOTERM|STR_UTF8)] string components[component_count]; + } PRINCIPAL; + + typedef struct { + uint16 enctype; + DATA_BLOB data; + } KEYBLOCK; + + typedef struct { + uint16 addrtype; + DATA_BLOB data; + } ADDRESS; + + typedef struct { + uint32 count; + ADDRESS data[count]; + } ADDRESSES; + + typedef struct { + uint16 ad_type; + DATA_BLOB data; + } AUTHDATUM; + + typedef struct { + uint32 count; + AUTHDATUM data[count]; + } AUTHDATA; + + typedef struct { + PRINCIPAL client; + PRINCIPAL server; + KEYBLOCK keyblock; + uint32 authtime; + uint32 starttime; + uint32 endtime; + uint32 renew_till; + uint8 is_skey; + uint32 ticket_flags; + ADDRESSES addresses; + AUTHDATA authdata; + DATA_BLOB ticket; + DATA_BLOB second_ticket; + } CREDENTIAL; + + typedef struct { + [value(0)] int32 kdc_sec_offset; + [value(0)] int32 kdc_usec_offset; + } DELTATIME_TAG; + + typedef [nodiscriminant] union { + [case(1)] DELTATIME_TAG deltatime_tag; + } FIELD; + + typedef struct { + [value(1)] uint16 tag; + [subcontext(2),switch_is(tag)] FIELD field; + } V4TAG; + + typedef struct { + V4TAG tag; + /* + * We should allow for more than one tag to be properly parsed, but that + * would require manual parsing. + */ + [flag(NDR_REMAINING)] DATA_BLOB further_tags; + } V4TAGS; + + typedef struct { + [subcontext(2)] V4TAGS v4tags; + } V4HEADER; + + typedef [nodiscriminant] union { + /* + * We don't attempt to support file format versions 1 and 2 as they + * assume native CPU byte order, which makes no sense in PIDL. + */ + [case(3)] ; + [case(4)] V4HEADER v4header; + } OPTIONAL_HEADER; + + /* Public structures. */ + + typedef [flag(NDR_NOALIGN|NDR_BIG_ENDIAN|NDR_PAHEX),public] struct { + [value(5)] uint8 pvno; + [value(4)] uint8 version; + [switch_is(version)] OPTIONAL_HEADER optional_header; + PRINCIPAL principal; + CREDENTIAL cred; + [flag(NDR_REMAINING)] DATA_BLOB further_creds; + } CCACHE; + + typedef [flag(NDR_NOALIGN|NDR_BIG_ENDIAN|NDR_PAHEX),public] struct { + CREDENTIAL cred; + [flag(NDR_REMAINING)] DATA_BLOB further_creds; + } MULTIPLE_CREDENTIALS; +} diff --git a/librpc/idl/wscript_build b/librpc/idl/wscript_build index 928f54abde0..0cbd7f8fdfc 100644 --- a/librpc/idl/wscript_build +++ b/librpc/idl/wscript_build @@ -147,6 +147,7 @@ bld.SAMBA_PIDL_LIST('PIDL', drsblobs.idl idmap.idl krb5pac.idl + krb5ccache.idl messaging.idl misc.idl nbt.idl diff --git a/librpc/wscript_build b/librpc/wscript_build index f9a889f3813..239e2895565 100644 --- a/librpc/wscript_build +++ b/librpc/wscript_build @@ -374,6 +374,11 @@ bld.SAMBA_LIBRARY('ndr-krb5pac', vnum='0.0.1' ) +bld.SAMBA_SUBSYSTEM('NDR_KRB5CCACHE', + source='gen_ndr/ndr_krb5ccache.c', + deps='ndr NDR_COMPRESSION NDR_SECURITY ndr-standard asn1util' + ) + bld.SAMBA_LIBRARY('ndr-standard', source='', vnum='0.0.1', @@ -616,7 +621,8 @@ bld.SAMBA_LIBRARY('ndr-samba', source=[], deps='''NDR_DRSBLOBS NDR_DRSUAPI NDR_IDMAP NDR_NTLMSSP NDR_NEGOEX NDR_SCHANNEL NDR_MGMT NDR_DNSSERVER NDR_EPMAPPER NDR_XATTR NDR_UNIXINFO NDR_NAMED_PIPE_AUTH NDR_DCOM - NDR_NTPRINTING NDR_FSRVP NDR_WITNESS NDR_MDSSVC NDR_OPEN_FILES NDR_SMBXSRV''', + NDR_NTPRINTING NDR_FSRVP NDR_WITNESS NDR_MDSSVC NDR_OPEN_FILES NDR_SMBXSRV + NDR_KRB5CCACHE''', private_library=True, grouping_library=True ) diff --git a/python/samba/tests/blackbox/ndrdump.py b/python/samba/tests/blackbox/ndrdump.py index 91ac076fd3a..9b2a760cbf7 100644 --- a/python/samba/tests/blackbox/ndrdump.py +++ b/python/samba/tests/blackbox/ndrdump.py @@ -24,13 +24,7 @@ import os import re from samba.tests import BlackboxTestCase, BlackboxProcessError -for p in ["../../../../../source4/librpc/tests", - "../../../../../librpc/tests"]: - data_path_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), p)) - print(data_path_dir) - if os.path.exists(data_path_dir): - break - +data_path_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../../../../source4/librpc/tests")) class NdrDumpTests(BlackboxTestCase): """Blackbox tests for ndrdump.""" @@ -325,6 +319,43 @@ dump OK # convert expected to bytes for python 3 self.assertEqual(actual, expected.encode('utf-8')) + def test_ndrdump_Krb5ccache(self): + expected = open(self.data_path("../../../source3/selftest/" + "ktest-krb5_ccache-2.txt")).read() + try: + # Specify -d1 to match the generated output file, because ndrdump + # only outputs some additional info if this parameter is specified, + # and the --configfile parameter gives us an empty smb.conf to avoid + # extraneous output. + actual = self.check_output( + "ndrdump krb5ccache CCACHE struct " + "--configfile /dev/null -d1 --validate " + + self.data_path("../../../source3/selftest/" + "ktest-krb5_ccache-2")) + except BlackboxProcessError as e: + self.fail(e) + # check_output will return bytes + # convert expected to bytes for python 3 + self.assertEqual(actual, expected.encode('utf-8')) + + expected = open(self.data_path("../../../source3/selftest/" + "ktest-krb5_ccache-3.txt")).read() + try: + # Specify -d1 to match the generated output file, because ndrdump + # only outputs some additional info if this parameter is specified, + # and the --configfile parameter gives us an empty smb.conf to avoid + # extraneous output. + actual = self.check_output( + "ndrdump krb5ccache CCACHE struct " + "--configfile /dev/null -d1 --validate " + + self.data_path("../../../source3/selftest/" + "ktest-krb5_ccache-3")) + except BlackboxProcessError as e: + self.fail(e) + # check_output will return bytes + # convert expected to bytes for python 3 + self.assertEqual(actual, expected.encode('utf-8')) + # This is a good example of a union with an empty default # and no buffers to parse. def test_ndrdump_fuzzed_spoolss_EnumForms(self): diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 1c7f05dda6d..e345f739e1c 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -1,6 +1,6 @@ # Unix SMB/CIFS implementation. # Copyright (C) Stefan Metzmacher 2020 -# Copyright (C) 2020 Catalyst.Net Ltd +# Copyright (C) 2020-2021 Catalyst.Net Ltd # # 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 @@ -18,6 +18,8 @@ import sys import os +from datetime import datetime, timezone +import tempfile sys.path.insert(0, "bin/python") os.environ["PYTHONUNBUFFERED"] = "1" @@ -26,10 +28,10 @@ import ldb from ldb import SCOPE_BASE from samba import generate_random_password from samba.auth import system_session -from samba.credentials import Credentials -from samba.dcerpc import krb5pac +from samba.credentials import Credentials, SPECIFIED, MUST_USE_KERBEROS +from samba.dcerpc import krb5pac, krb5ccache from samba.dsdb import UF_WORKSTATION_TRUST_ACCOUNT, UF_NORMAL_ACCOUNT -from samba.ndr import ndr_unpack +from samba.ndr import ndr_pack, ndr_unpack from samba.samdb import SamDB from samba.tests import delete_force @@ -38,6 +40,8 @@ import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 from samba.tests.krb5.rfc4120_constants import ( AD_IF_RELEVANT, AD_WIN2K_PAC, + AES256_CTS_HMAC_SHA1_96, + ARCFOUR_HMAC_MD5, KDC_ERR_PREAUTH_REQUIRED, KRB_AS_REP, KRB_TGS_REP, @@ -46,6 +50,8 @@ from samba.tests.krb5.rfc4120_constants import ( KU_PA_ENC_TIMESTAMP, KU_TGS_REP_ENC_PART_SUB_KEY, KU_TICKET, + NT_PRINCIPAL, + NT_SRV_HST, PADATA_ENC_TIMESTAMP, PADATA_ETYPE_INFO2, ) @@ -445,3 +451,171 @@ class KDCBaseTest(RawKerberosTest): msg = ldb.Message(dn) msg[name] = ldb.MessageElement(values, flag, name) self.ldb.modify(msg) + + def create_ccache(self, cname, ticket, enc_part): + """ Lay out a version 4 on-disk credentials cache, to be read using the + FILE: protocol. + """ + + field = krb5ccache.DELTATIME_TAG() + field.kdc_sec_offset = 0 + field.kdc_usec_offset = 0 + + v4tag = krb5ccache.V4TAG() + v4tag.tag = 1 + v4tag.field = field + + v4tags = krb5ccache.V4TAGS() + v4tags.tag = v4tag + v4tags.further_tags = b'' + + optional_header = krb5ccache.V4HEADER() + optional_header.v4tags = v4tags + + cname_string = cname['name-string'] + + cprincipal = krb5ccache.PRINCIPAL() + cprincipal.name_type = cname['name-type'] + cprincipal.component_count = len(cname_string) + cprincipal.realm = ticket['realm'] + cprincipal.components = cname_string + + sname = ticket['sname'] + sname_string = sname['name-string'] + + sprincipal = krb5ccache.PRINCIPAL() + sprincipal.name_type = sname['name-type'] + sprincipal.component_count = len(sname_string) + sprincipal.realm = ticket['realm'] + sprincipal.components = sname_string + + key = self.EncryptionKey_import(enc_part['key']) + + key_data = key.export_obj() + keyblock = krb5ccache.KEYBLOCK() + keyblock.enctype = key_data['keytype'] + keyblock.data = key_data['keyvalue'] + + addresses = krb5ccache.ADDRESSES() + addresses.count = 0 + addresses.data = [] + + authdata = krb5ccache.AUTHDATA() + authdata.count = 0 + authdata.data = [] + + # Re-encode the ticket, since it was decoded by another layer. + ticket_data = self.der_encode(ticket, asn1Spec=krb5_asn1.Ticket()) + + authtime = enc_part['authtime'] + try: + starttime = enc_part['starttime'] + except KeyError: + starttime = authtime + endtime = enc_part['endtime'] + + cred = krb5ccache.CREDENTIAL() + cred.client = cprincipal + cred.server = sprincipal + cred.keyblock = keyblock + cred.authtime = int(datetime.strptime(authtime.decode(), + "%Y%m%d%H%M%SZ") + .replace(tzinfo=timezone.utc).timestamp()) + cred.starttime = int(datetime.strptime(starttime.decode(), + "%Y%m%d%H%M%SZ") + .replace(tzinfo=timezone.utc).timestamp()) + cred.endtime = int(datetime.strptime(endtime.decode(), + "%Y%m%d%H%M%SZ") + .replace(tzinfo=timezone.utc).timestamp()) + + # Account for clock skew of up to five minutes. + self.assertLess(cred.authtime - 5*60, + datetime.now(timezone.utc).timestamp(), + "Ticket not yet valid - clocks may be out of sync.") + self.assertLess(cred.starttime - 5*60, + datetime.now(timezone.utc).timestamp(), + "Ticket not yet valid - clocks may be out of sync.") + self.assertGreater(cred.endtime - 60*60, + datetime.now(timezone.utc).timestamp(), + "Ticket already expired/about to expire - clocks may be out of sync.") + + cred.renew_till = cred.endtime + cred.is_skey = 0 + cred.ticket_flags = int(enc_part['flags'], 2) + cred.addresses = addresses + cred.authdata = authdata + cred.ticket = ticket_data + cred.second_ticket = b'' + + ccache = krb5ccache.CCACHE() + ccache.pvno = 5 + ccache.version = 4 + ccache.optional_header = optional_header + ccache.principal = cprincipal + ccache.cred = cred + + # Serialise the credentials cache structure. + result = ndr_pack(ccache) + + # Create a temporary file and write the credentials. + cachefile = tempfile.NamedTemporaryFile(dir=self.tempdir, delete=False) + cachefile.write(result) + cachefile.close() + + return cachefile + + def create_ccache_with_user(self, user_credentials, mach_name, + service="host"): + # Obtain a service ticket authorising the user and place it into a + # newly created credentials cache file. + + user_name = user_credentials.get_username() + realm = user_credentials.get_realm() + + # Do the initial AS-REQ, should get a pre-authentication required + # response + etype = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5) + cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, + names=[user_name]) + sname = self.PrincipalName_create(name_type=NT_SRV_HST, + names=["krbtgt", realm]) + + rep = self.as_req(cname, sname, realm, etype) + self.check_pre_authenication(rep) + + # Do the next AS-REQ + padata = self.get_pa_data(user_credentials, rep) + key = self.get_as_rep_key(user_credentials, rep) + rep = self.as_req(cname, sname, realm, etype, padata=padata) + self.check_as_reply(rep) + + # Request a ticket to the host service on the machine account + ticket = rep['ticket'] + enc_part = self.get_as_rep_enc_data(key, rep) + key = self.EncryptionKey_import(enc_part['key']) + cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, + names=[user_name]) + sname = self.PrincipalName_create(name_type=NT_SRV_HST, + names=[service, mach_name]) + + (rep, enc_part) = self.tgs_req( -- Samba Shared Repository