[SCM] Samba Shared Repository - branch master updated
Andrew Bartlett
abartlet at samba.org
Thu May 25 04:29:02 UTC 2017
The branch, master has been updated
via fa6753d libnet join: Fix error handling on provision_store_self_join failure
via 7796364 source4/provision: fix talloc_steal on unallocated memory
via 468dc02 tests net_join: use private secrets database.
via 9444bbf source4 rpc: binding.c enable DCERPC_SCHANNEL_AUTO for schannel connections
via 610919e auth pycredentials: incorrect PyArg_ParseTupleAndKeywords call
via ee0eb1d auth pycredentials: correct docstring of get_ntlm_response method
via 68ccebf auth_log: Add test that execises the SamLogon python bindings
via 6419909 tests password_hash: Add ldap based tests for WDigest
via 83fbd80 pynet: Add a hook to decrypt one attribute
via f5cd832 tests password_hash: update array indexes for readabliity
via b14bb68 samba-tool add support for userPassword
via 8a5308b samba-tool tests: add tests for userPassword
via 4b49e18 password_hash: generate and store Primary:userPassword
via de5299d tests password_hash: add tests for Primary:userPassword
via 79f027a docs: configuration options for extra password hashes
via adae071 tests password_hash: fix white space issues
via 601dbca tests password_hash: remove unused import
via 826e50a idl drsblobs: add the blobs required for Primary:userPassword
via d4bc91a samba-tool user: add rounds option to virtualCryptSHAxxx
via d512536 samba-tool tests: Tests for virtualCryptSHAxxx rounds
via 3bcd384 samba-tool user: Support for virtualWDigest attributes
via 81312ba samba-tool user: Tests for virtualWDigest attributes
from f47d331 ctdb-daemon: Add AllowMixedVersions tunable
https://git.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit fa6753d6c2f83392e9517bd3cee7d65561fb7c0c
Author: Gary Lockyer <gary at catalyst.net.nz>
Date: Tue May 23 14:11:35 2017 +1200
libnet join: Fix error handling on provision_store_self_join failure
This avoids leaving the error string NULL.
Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
Autobuild-User(master): Andrew Bartlett <abartlet at samba.org>
Autobuild-Date(master): Thu May 25 06:28:02 CEST 2017 on sn-devel-144
commit 7796364d623011343c3f19c3167a41ab569eaea0
Author: Gary Lockyer <gary at catalyst.net.nz>
Date: Tue May 23 14:13:14 2017 +1200
source4/provision: fix talloc_steal on unallocated memory
The caller will steal *error_string on failure, if it
is not NULL.
Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit 468dc02e84fedbfae2b297f716cb60dec2981ed5
Author: Gary Lockyer <gary at catalyst.net.nz>
Date: Tue May 23 13:03:03 2017 +1200
tests net_join: use private secrets database.
Tests were leaving entries in the secrets database that caused
subsequent test cases to fail.
Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit 9444bbfe1829e25f772e05c1c3f3c5aa26a16105
Author: Gary Lockyer <gary at catalyst.net.nz>
Date: Thu Apr 27 07:12:34 2017 +1200
source4 rpc: binding.c enable DCERPC_SCHANNEL_AUTO for schannel connections
Enable the DCERPC_SCHANNEL_AUTO option in dceprc bindings. If not enabled
calls to netlogon.netlogon from python fail with NT_STATUS_DOWNGRADE_DETECTED
if schannel bindings are specified.
Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
Pair-programmed-with: Garming Sam <garming at catalyst.net.nz>
commit 610919e5e665dcb23241055e8ccb11f3d3f2ae2c
Author: Gary Lockyer <gary at catalyst.net.nz>
Date: Fri Apr 28 13:14:16 2017 +1200
auth pycredentials: incorrect PyArg_ParseTupleAndKeywords call
The challenge parameter was being treated as a string rather than as a
data blob. This was causing intermittent seg faults. Removed the
server_timestamp parameter as it's not currently used.
Unable to produce a test case to reliably replicate the failure.
However auth_log_samlogon does flap
Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit ee0eb1daa349671386bae0121be6a4b8be06815d
Author: Gary Lockyer <gary at catalyst.net.nz>
Date: Fri Apr 28 13:13:28 2017 +1200
auth pycredentials: correct docstring of get_ntlm_response method
Fix copy paste error was incorrectly named "get_ntlm_username_domain"
Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit 68ccebfa59e2fc8b717c93224594f49af556ec6e
Author: Gary Lockyer <gary at catalyst.net.nz>
Date: Fri Apr 28 10:16:39 2017 +1200
auth_log: Add test that execises the SamLogon python bindings
Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit 64199090940cad9f3b4c3f5781426e61418dde9b
Author: Gary Lockyer <gary at catalyst.net.nz>
Date: Mon May 22 09:49:17 2017 +1200
tests password_hash: Add ldap based tests for WDigest
Add tests of the WDigest values using ldap. This allows the tests to be
run against Windows, to validate the calculated values.
Tests validated against Windows Server 2012 R2
Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit 83fbd80b3f11f94dc00950c270daf9288148a658
Author: Andrew Bartlett <abartlet at samba.org>
Date: Wed May 17 17:05:13 2017 +1200
pynet: Add a hook to decrypt one attribute
This will help with testing GetNCChanges and supplementalCredentials against Windows in Python
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
commit f5cd83247fa2384744873637fd2d32efe4f65ec3
Author: Gary Lockyer <gary at catalyst.net.nz>
Date: Thu May 18 14:38:37 2017 +1200
tests password_hash: update array indexes for readabliity
Use an n-1 pattern in the indexes to the digest array to simplify checking
against the documentation and samba-tool user tests.
Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit b14bb68417e34db17a9b7ba4feac7b32ef2cd39e
Author: Gary Lockyer <gary at catalyst.net.nz>
Date: Mon May 15 12:19:22 2017 +1200
samba-tool add support for userPassword
Changes to virtualCryptSHA256 and virtualCryptSHA512 attributes.
The values are now calculated as follows:
1) If a value exists in 'Primary:userPassword' with
the specified number of rounds it is returned.
2) If 'Primary:CLEARTEXT, or 'Primary:SambaGPG' with
'--decrypt-samba-gpg'. Calculate a hash with the specified number of rounds
3) Return the first {CRYPT} value in 'Primary:userPassword' with a
matching algorithm
Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit 8a5308bea054686a25aba5b933bc02ad1f2e4587
Author: Gary Lockyer <gary at catalyst.net.nz>
Date: Mon May 15 12:20:58 2017 +1200
samba-tool tests: add tests for userPassword
Tests to ensure that precomputed SHA256 and SHA512 hashes in
'supplementalCredentials Primary:userPassword' are used correctly in the
calculation of virtualCryptSHA256 and virtualCryptSHA512
Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit 4b49e18c143b67bf8f3c1377c0f61b75f507f7fc
Author: Gary Lockyer <gary at catalyst.net.nz>
Date: Tue Apr 4 16:05:08 2017 +1200
password_hash: generate and store Primary:userPassword
Generate sha256 and sha512 password hashes and store them in
supplementalCredentials
Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit de5299d1554130aef9554d2696742ceaab66daeb
Author: Gary Lockyer <gary at catalyst.net.nz>
Date: Wed Apr 12 09:12:56 2017 +1200
tests password_hash: add tests for Primary:userPassword
Add tests to verify the generation and storage of sha256 and sha512
password hashes in suplementalCredentials Primary:userPassword
Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit 79f027a6104d9022437ced8570d31857e74346ea
Author: Gary Lockyer <gary at catalyst.net.nz>
Date: Tue May 9 14:38:06 2017 +1200
docs: configuration options for extra password hashes
Add the configuration options for the generation and storage of crypt()
based sha256 and sha512 password hashes in supplementalCredentials
Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit adae071daad3f3508c389fe2933e5c7f98a45be6
Author: Gary Lockyer <gary at catalyst.net.nz>
Date: Wed Apr 12 09:09:27 2017 +1200
tests password_hash: fix white space issues
Clean up white space issues in password_hash.py
Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit 601dbca8f9617c5632601f8a8fb26ba4426f0fca
Author: Gary Lockyer <gary at catalyst.net.nz>
Date: Wed Apr 12 09:08:24 2017 +1200
tests password_hash: remove unused import
Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit 826e50a5f62146bae5827736eecdea63726ab996
Author: Gary Lockyer <gary at catalyst.net.nz>
Date: Tue Apr 4 16:00:20 2017 +1200
idl drsblobs: add the blobs required for Primary:userPassword
Add the blobs required to allow the storing of an sha256 or sha512 hash of
the password in supplemental credentials
Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit d4bc91a964725c0a0fb8f8c3aa48fcb13f4a998e
Author: Gary Lockyer <gary at catalyst.net.nz>
Date: Tue May 9 11:20:15 2017 +1200
samba-tool user: add rounds option to virtualCryptSHAxxx
Allow the number of rounds to be specified when calculating the
virtualCryptSHA256 and virtualCryptSHA512 attributes.
i.e. --attributes="virtualCryptSHA256;rounds=3000" will calculate the
hash using 3,000 rounds.
Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit d51253609de61b8c7c75d0de8febe9c2c0afdae7
Author: Gary Lockyer <gary at catalyst.net.nz>
Date: Tue May 9 11:15:19 2017 +1200
samba-tool tests: Tests for virtualCryptSHAxxx rounds
Add tests to for the new rounds option for the virtualCryptSHA256 and
virtualCryptSHA512 attributes.
Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit 3bcd384dcf0ad5ed4dd1e94e30507e75d1006e73
Author: Gary Lockyer <gary at catalyst.net.nz>
Date: Mon May 8 10:00:58 2017 +1200
samba-tool user: Support for virtualWDigest attributes
Add new virtualWDigest attributes, these return the hashes stored in
supplementalCredentials Primary:WDigest, in a form suitable for
htdigest authentication
Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit 81312ba4e2f3d34e18513e4af966fedd86077085
Author: Gary Lockyer <gary at catalyst.net.nz>
Date: Mon May 8 10:00:09 2017 +1200
samba-tool user: Tests for virtualWDigest attributes
Add tests for the new virtualWDigest attributes, these return the hashes
stored in supplementalCredentials Primary:WDigest in a form suitable for
use with htdigest authentication.
Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>
Reviewed-by: Garming Sam <garming at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
-----------------------------------------------------------------------
Summary of changes:
auth/credentials/pycredentials.c | 31 +-
.../security/passwordhashuserpasswordschemes.xml | 67 +++
librpc/idl/drsblobs.idl | 44 ++
librpc/rpc/binding.c | 2 +-
python/samba/netcmd/user.py | 327 ++++++++++++-
python/samba/provision/__init__.py | 5 +-
python/samba/tests/auth_log_samlogon.py | 181 +++++++
.../tests/{net_join_no_spnego.py => net_join.py} | 26 +-
python/samba/tests/net_join_no_spnego.py | 41 +-
python/samba/tests/password_hash.py | 169 ++++---
python/samba/tests/password_hash_fl2003.py | 98 +++-
python/samba/tests/password_hash_fl2008.py | 98 ++++
python/samba/tests/password_hash_gpgme.py | 106 ++++
python/samba/tests/password_hash_ldap.py | 132 +++++
.../samba/tests/samba_tool/user_virtualCryptSHA.py | 540 +++++++++++++++++++++
python/samba/tests/samba_tool/user_wdigest.py | 456 +++++++++++++++++
source4/dsdb/pydsdb.c | 1 +
source4/dsdb/samdb/ldb_modules/password_hash.c | 269 +++++++++-
source4/libnet/libnet_join.c | 9 +-
source4/libnet/py_net.c | 74 +++
source4/param/provision.c | 3 +
source4/selftest/tests.py | 24 +-
22 files changed, 2587 insertions(+), 116 deletions(-)
create mode 100644 docs-xml/smbdotconf/security/passwordhashuserpasswordschemes.xml
create mode 100644 python/samba/tests/auth_log_samlogon.py
copy python/samba/tests/{net_join_no_spnego.py => net_join.py} (68%)
create mode 100644 python/samba/tests/password_hash_ldap.py
create mode 100644 python/samba/tests/samba_tool/user_virtualCryptSHA.py
create mode 100644 python/samba/tests/samba_tool/user_wdigest.py
Changeset truncated at 500 lines:
diff --git a/auth/credentials/pycredentials.c b/auth/credentials/pycredentials.c
index 283a73f..fee9556 100644
--- a/auth/credentials/pycredentials.c
+++ b/auth/credentials/pycredentials.c
@@ -90,16 +90,19 @@ static PyObject *py_creds_get_ntlm_response(PyObject *self, PyObject *args, PyOb
DATA_BLOB lm_session_key = data_blob_null;
DATA_BLOB nt_session_key = data_blob_null;
const char *kwnames[] = { "flags", "challenge",
- "target_info", "server_timestamp",
+ "target_info",
NULL };
tv_now = timeval_current();
server_timestamp = timeval_to_nttime(&tv_now);
- if (!PyArg_ParseTupleAndKeywords(args, kwargs,
- "i" PYARG_BYTES_LEN "|" PYARG_BYTES_LEN "K",
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "is#|s#",
discard_const_p(char *, kwnames),
- &flags, &challenge, &target_info.data, &target_info.length)) {
+ &flags,
+ &challenge.data,
+ &challenge.length,
+ &target_info.data,
+ &target_info.length)) {
return NULL;
}
@@ -581,6 +584,20 @@ static PyObject *py_creds_get_gensec_features(PyObject *self, PyObject *args)
return PyInt_FromLong(gensec_features);
}
+static PyObject *py_creds_set_secure_channel_type(PyObject *self, PyObject *args)
+{
+ unsigned int channel_type;
+
+ if (!PyArg_ParseTuple(args, "I", &channel_type))
+ return NULL;
+
+ cli_credentials_set_secure_channel_type(
+ PyCredentials_AsCliCredentials(self),
+ channel_type);
+
+ Py_RETURN_NONE;
+}
+
static PyMethodDef py_creds_methods[] = {
{ "get_username", py_creds_get_username, METH_NOARGS,
@@ -600,8 +617,8 @@ static PyMethodDef py_creds_methods[] = {
"S.get_ntlm_username_domain() -> (domain, username)\n"
"Obtain NTLM username and domain, split up either as (DOMAIN, user) or (\"\", \"user at realm\")." },
{ "get_ntlm_response", (PyCFunction)py_creds_get_ntlm_response, METH_VARARGS | METH_KEYWORDS,
- "S.get_ntlm_username_domain"
- "(flags, challenge, target_info[, server_timestamp]) -> "
+ "S.get_ntlm_response"
+ "(flags, challenge[, target_info]) -> "
"(flags, lm_response, nt_response, lm_session_key, nt_session_key)\n"
"Obtain LM or NTLM response." },
{ "set_password", py_creds_set_password, METH_VARARGS,
@@ -683,6 +700,8 @@ static PyMethodDef py_creds_methods[] = {
{ "set_forced_sasl_mech", py_creds_set_forced_sasl_mech, METH_VARARGS,
"S.set_forced_sasl_mech(name) -> None\n"
"Set forced SASL mechanism." },
+ { "set_secure_channel_type", py_creds_set_secure_channel_type,
+ METH_VARARGS, NULL },
{ NULL }
};
diff --git a/docs-xml/smbdotconf/security/passwordhashuserpasswordschemes.xml b/docs-xml/smbdotconf/security/passwordhashuserpasswordschemes.xml
new file mode 100644
index 0000000..18a43f9
--- /dev/null
+++ b/docs-xml/smbdotconf/security/passwordhashuserpasswordschemes.xml
@@ -0,0 +1,67 @@
+<samba:parameter name="password hash userPassword schemes"
+ context="G"
+ type="cmdlist"
+ xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
+<description>
+
+<para>This parameter determines whether or not
+<citerefentry><refentrytitle>samba</refentrytitle>
+<manvolnum>8</manvolnum></citerefentry> acting as an Active
+Directory Domain Controller will attempt to store additional
+passwords hash types for the user</para>
+
+<para>The values are stored as 'Primary:userPassword' in the
+<command moreinfo="none">supplementalCredentials</command>
+attribute. The value of this option is a hash type.</para>
+
+<para>The currently supported hash types are:</para>
+<itemizedlist>
+ <listitem>
+ <para><constant>CryptSHA256</constant></para>
+ </listitem>
+ <listitem>
+ <para><constant>CryptSHA512</constant></para>
+ </listitem>
+</itemizedlist>
+
+<para>Multiple instances of a hash type may be computed and stored.
+The password hashes are calculated using the
+<citerefentry><refentrytitle>crypt</refentrytitle>
+<manvolnum>3</manvolnum></citerefentry> call.
+The number of rounds used to compute the hash can be specified by adding
+':rounds=xxxx' to the hash type, i.e. CryptSHA512:rounds=4500 would calculate
+an SHA512 hash using 4500 rounds. If not specified the Operating System
+defaults for
+<citerefentry><refentrytitle>crypt</refentrytitle>
+<manvolnum>3</manvolnum></citerefentry> are used.
+</para>
+
+<para>As password changes can occur on any domain controller,
+you should configure this on each of them. Note that this feature is
+currently available only on Samba domain controllers.</para>
+
+<para>Currently the NT Hash of the password is recorded when these hashes
+are calculated and stored. When retrieving the hashes the current value of the
+NT Hash is checked against the stored NT Hash. This detects password changes
+that have not updated the password hashes. In this case
+<command moreinfo="none">samba-tool user</command> will ignore the stored
+hash values.
+</para>
+
+<para>Being able to obtain the hashed password helps, when
+they need to be imported into other authentication systems
+later (see <command moreinfo="none">samba-tool user
+getpassword</command>) or you want to keep the passwords in
+sync with another system, e.g. an OpenLDAP server (see
+<command moreinfo="none">samba-tool user
+syncpasswords</command>).</para>
+
+<related>unix password sync</related>
+
+</description>
+
+<value type="default"></value>
+<value type="example">CryptSHA256</value>
+<value type="example">CryptSHA256 CryptSHA512</value>
+<value type="example">CryptSHA256:rounds=5000 CryptSHA512:rounds=7000</value>
+</samba:parameter>
diff --git a/librpc/idl/drsblobs.idl b/librpc/idl/drsblobs.idl
index 44f5fda..9fca2cb 100644
--- a/librpc/idl/drsblobs.idl
+++ b/librpc/idl/drsblobs.idl
@@ -323,6 +323,16 @@ interface drsblobs {
* 'Primary:CLEARTEXT':
* data contains the cleartext password
* as UTF16 string encoded as HEX string
+ *
+ * 'Primary:userPassword':
+ * ...
+ *
+ * 'Primary:SambaGPG':
+ * ...
+ *
+ * 'Primary:NTLM-Strong-NTOWF':
+ * ... Not yet implemented.
+ *
*/
[charset(DOS)] uint8 data[data_len];
} supplementalCredentialsPackage;
@@ -460,6 +470,40 @@ interface drsblobs {
[in] package_PrimarySambaGPGBlob blob
);
+ /*
+ * Password hashes stored in a scheme compatible with
+ * OpenLDAP's userPassword attribute. The Package is named
+ * Primary:userPassword each calculated hash,
+ * which is typically caclulated via crypt(), the scheme is stored.
+ * The scheme name and the {scheme} format is re-used from OpenLDAP's
+ * use for userPassword to aid interopability when exported.
+ *
+ * The currently supported scheme so far is {CRYPT}, which may
+ * be specified multiple times if both CryptSHA256 ($5$) and
+ * CryptSHA512 ($6$) are in use.
+ *
+ * current_nt_hash is either the unicodePwd or the
+ * NTLM-Strong-NTOWF, to allow us to prove this password is
+ * a valid element.
+ */
+ typedef struct {
+ [value(2*strlen_m(scheme))] uint16 scheme_len;
+ [charset(UTF16)] uint8 scheme[scheme_len];
+ [value((value?value->length:0))] uint32 value_len;
+ [relative,subcontext(0),subcontext_size(value_len),
+ flag(NDR_REMAINING)] DATA_BLOB *value;
+ } package_PrimaryUserPasswordValue;
+
+ typedef [public] struct {
+ samr_Password current_nt_hash;
+ uint16 num_hashes;
+ package_PrimaryUserPasswordValue hashes[num_hashes];
+ } package_PrimaryUserPasswordBlob;
+
+ void decode_PrimaryUserPasswordBlob(
+ [in] package_PrimaryUserPasswordBlob blob
+ );
+
typedef struct {
[value(0)] uint32 size;
} AuthInfoNone;
diff --git a/librpc/rpc/binding.c b/librpc/rpc/binding.c
index 51f89cc..63ba682 100644
--- a/librpc/rpc/binding.c
+++ b/librpc/rpc/binding.c
@@ -98,7 +98,7 @@ static const struct ncacn_option {
{"spnego", DCERPC_AUTH_SPNEGO},
{"ntlm", DCERPC_AUTH_NTLM},
{"krb5", DCERPC_AUTH_KRB5},
- {"schannel", DCERPC_SCHANNEL},
+ {"schannel", DCERPC_SCHANNEL | DCERPC_SCHANNEL_AUTO},
{"validate", DCERPC_DEBUG_VALIDATE_BOTH},
{"print", DCERPC_DEBUG_PRINT_BOTH},
{"padcheck", DCERPC_DEBUG_PAD_CHECK},
diff --git a/python/samba/netcmd/user.py b/python/samba/netcmd/user.py
index f1e17dd..53ac39f 100644
--- a/python/samba/netcmd/user.py
+++ b/python/samba/netcmd/user.py
@@ -103,7 +103,7 @@ def get_random_bytes(num):
raise ImportError(random_reason)
return get_random_bytes_fn(num)
-def get_crypt_value(alg, utf8pw):
+def get_crypt_value(alg, utf8pw, rounds=0):
algs = {
"5": {"length": 43},
"6": {"length": 86},
@@ -116,8 +116,13 @@ def get_crypt_value(alg, utf8pw):
# we can ignore the possible == at the end
# of the base64 string
# we just need to replace '+' by '.'
- b64salt = base64.b64encode(salt)
- crypt_salt = "$%s$%s$" % (alg, b64salt[0:16].replace('+', '.'))
+ b64salt = base64.b64encode(salt)[0:16].replace('+', '.')
+ crypt_salt = ""
+ if rounds != 0:
+ crypt_salt = "$%s$rounds=%s$%s$" % (alg, rounds, b64salt)
+ else:
+ crypt_salt = "$%s$%s$" % (alg, b64salt)
+
crypt_value = crypt.crypt(utf8pw, crypt_salt)
if crypt_value is None:
raise NotImplementedError("crypt.crypt(%s) returned None" % (crypt_salt))
@@ -127,6 +132,24 @@ def get_crypt_value(alg, utf8pw):
crypt_salt, len(crypt_value), expected_len))
return crypt_value
+# Extract the rounds value from the options of a virtualCrypt attribute
+# i.e. options = "rounds=20;other=ignored;" will return 20
+# if the rounds option is not found or the value is not a number, 0 is returned
+# which indicates that the default number of rounds should be used.
+def get_rounds(options):
+ if not options:
+ return 0
+
+ opts = options.split(';')
+ for o in opts:
+ if o.lower().startswith("rounds="):
+ (key, _, val) = o.partition('=')
+ try:
+ return int(val)
+ except ValueError:
+ return 0
+ return 0
+
try:
random_reason = check_random()
if random_reason is not None:
@@ -169,6 +192,10 @@ for (alg, attr) in [("5", "virtualCryptSHA256"), ("6", "virtualCryptSHA512")]:
"reason" : reason,
}
+# Add the wDigest virtual attributes, virtualWDigest01 to virtualWDigest29
+for x in range(1, 30):
+ virtual_attributes["virtualWDigest%02d" % x] = {}
+
virtual_attributes_help = "The attributes to display (comma separated). "
virtual_attributes_help += "Possible supported virtual attributes: %s" % ", ".join(sorted(virtual_attributes.keys()))
if len(disabled_virtual_attributes) != 0:
@@ -878,9 +905,19 @@ class GetPasswordCommand(Command):
def get_account_attributes(self, samdb, username, basedn, filter, scope,
attrs, decrypt):
- require_supplementalCredentials = False
- search_attrs = attrs[:]
+ raw_attrs = attrs[:]
+ search_attrs = []
+ attr_opts = {}
+ for a in raw_attrs:
+ (attr, _, opts) = a.partition(';')
+ if opts:
+ attr_opts[attr] = opts
+ else:
+ attr_opts[attr] = None
+ search_attrs.append(attr)
lower_attrs = [x.lower() for x in search_attrs]
+
+ require_supplementalCredentials = False
for a in virtual_attributes.keys():
if a.lower() in lower_attrs:
require_supplementalCredentials = True
@@ -901,6 +938,12 @@ class GetPasswordCommand(Command):
search_attrs += [a]
add_sAMAcountName = True
+ add_userPrincipalName = False
+ upn = "usePrincipalName"
+ if upn.lower() not in lower_attrs:
+ search_attrs += [upn]
+ add_userPrincipalName = True
+
if scope == ldb.SCOPE_BASE:
search_controls = ["show_deleted:1", "show_recycled:1"]
else:
@@ -932,6 +975,13 @@ class GetPasswordCommand(Command):
account_name = obj["sAMAccountName"][0]
if add_sAMAcountName:
del obj["sAMAccountName"]
+ if "userPrincipalName" in obj:
+ account_upn = obj["userPrincipalName"][0]
+ else:
+ realm = self.lp.get("realm")
+ account_upn = "%s@%s" % (account_name, realm.lower())
+ if add_userPrincipalName:
+ del obj["userPrincipalName"]
calculated = {}
def get_package(name, min_idx=0):
@@ -1002,6 +1052,168 @@ class GetPasswordCommand(Command):
u8 = u.encode('utf-8')
return u8
+ # Extract the WDigest hash for the value specified by i.
+ # Builds an htdigest compatible value
+ DIGEST = "Digest"
+ def get_wDigest(i, primary_wdigest, account_name, account_upn,
+ domain, dns_domain):
+ if i == 1:
+ user = account_name
+ realm= domain
+ elif i == 2:
+ user = account_name.lower()
+ realm = domain.lower()
+ elif i == 3:
+ user = account_name.upper()
+ realm = domain.upper()
+ elif i == 4:
+ user = account_name
+ realm = domain.upper()
+ elif i == 5:
+ user = account_name
+ realm = domain.lower()
+ elif i == 6:
+ user = account_name.upper()
+ realm = domain.lower()
+ elif i == 7:
+ user = account_name.lower()
+ realm = domain.upper()
+ elif i == 8:
+ user = account_name
+ realm = dns_domain.lower()
+ elif i == 9:
+ user = account_name.lower()
+ realm = dns_domain.lower()
+ elif i == 10:
+ user = account_name.upper()
+ realm = dns_domain.upper()
+ elif i == 11:
+ user = account_name
+ realm = dns_domain.upper()
+ elif i == 12:
+ user = account_name
+ realm = dns_domain.lower()
+ elif i == 13:
+ user = account_name.upper()
+ realm = dns_domain.lower()
+ elif i == 14:
+ user = account_name.lower()
+ realm = dns_domain.upper()
+ elif i == 15:
+ user = account_upn
+ realm = ""
+ elif i == 16:
+ user = account_upn.lower()
+ realm = ""
+ elif i == 17:
+ user = account_upn.upper()
+ realm = ""
+ elif i == 18:
+ user = "%s\\%s" % (domain, account_name)
+ realm = ""
+ elif i == 19:
+ user = "%s\\%s" % (domain.lower(), account_name.lower())
+ realm = ""
+ elif i == 20:
+ user = "%s\\%s" % (domain.upper(), account_name.upper())
+ realm = ""
+ elif i == 21:
+ user = account_name
+ realm = DIGEST
+ elif i == 22:
+ user = account_name.lower()
+ realm = DIGEST
+ elif i == 23:
+ user = account_name.upper()
+ realm = DIGEST
+ elif i == 24:
+ user = account_upn
+ realm = DIGEST
+ elif i == 25:
+ user = account_upn.lower()
+ realm = DIGEST
+ elif i == 26:
+ user = account_upn.upper()
+ realm = DIGEST
+ elif i == 27:
+ user = "%s\\%s" % (domain, account_name)
+ realm = DIGEST
+ elif i == 28:
+ # Differs from spec, see tests
+ user = "%s\\%s" % (domain.lower(), account_name.lower())
+ realm = DIGEST
+ elif i == 29:
+ # Differs from spec, see tests
+ user = "%s\\%s" % (domain.upper(), account_name.upper())
+ realm = DIGEST
+ else:
+ user = ""
+
+ digests = ndr_unpack(drsblobs.package_PrimaryWDigestBlob,
+ primary_wdigest)
+ try:
+ digest = binascii.hexlify(bytearray(digests.hashes[i-1].hash))
+ return "%s:%s:%s" % (user, realm, digest)
+ except IndexError:
+ return None
+
+
+ # get the value for a virtualCrypt attribute.
+ # look for an exact match on algorithm and rounds in supplemental creds
+ # if not found calculate using Primary:CLEARTEXT
+ # if no Primary:CLEARTEXT return the first supplementalCredential
+ # that matches the algorithm.
+ def get_virtual_crypt_value(a, algorithm, rounds, username, account_name):
+ sv = None
+ fb = None
+ b = get_package("Primary:userPassword")
+ if b is not None:
+ (sv, fb) = get_userPassword_hash(b, algorithm, rounds)
+ if sv is None:
+ # No exact match on algorithm and number of rounds
+ # try and calculate one from the Primary:CLEARTEXT
+ b = get_package("Primary:CLEARTEXT")
+ if b is not None:
+ u8 = get_utf8(a, b, username or account_name)
+ if u8 is not None:
+ sv = get_crypt_value(str(algorithm), u8, rounds)
+ if sv is None:
+ # Unable to calculate a hash with the specified
+ # number of rounds, fall back to the first hash using
+ # the specified algorithm
+ sv = fb
+ if sv is None:
+ return None
+ return "{CRYPT}" + sv
+
+ def get_userPassword_hash(blob, algorithm, rounds):
+ up = ndr_unpack(drsblobs.package_PrimaryUserPasswordBlob, blob)
+ SCHEME = "{CRYPT}"
+
+ # Check that the NT hash has not been changed without updating
+ # the user password hashes. This indicates that password has been
+ # changed without updating the supplemental credentials.
+ if unicodePwd != bytearray(up.current_nt_hash.hash):
+ return None
+
+ scheme_prefix = "$%d$" % algorithm
+ prefix = scheme_prefix
+ if rounds > 0:
+ prefix = "$%d$rounds=%d" % (algorithm, rounds)
+ scheme_match = None
+
+ for h in up.hashes:
+ if (scheme_match is None and
+ h.scheme == SCHEME and
+ h.value.startswith(scheme_prefix)):
+ scheme_match = h.value
+ if h.scheme == SCHEME and h.value.startswith(prefix):
+ return (h.value, scheme_match)
+
+ # No match on the number of rounds, return the value of the
+ # first matching scheme
+ return (None, scheme_match)
+
# We use sort here in order to have a predictable processing order
for a in sorted(virtual_attributes.keys()):
if not a.lower() in lower_attrs:
--
Samba Shared Repository
More information about the samba-cvs
mailing list