The branch, master has been updated via 31637d40371 WHATSNEW: Add entry for "samba-tool user get-kerberos-ticket" via 7c9fa2804b8 selftest: Add tests for "samba-tool user get-kerberos-ticket" via d8b3b1fed9a python/netcmd: Improve documentation for "samba-tool user getpassword" via 8eadc19f35e python/netcmd: Add "samba-tool user get-kerberos-ticket" to get a ticket for a gMSA via a39e19dfa75 WHATSNEW: Add entry for "samba-tool user getpassword" changes via 128710c2f3c python: tests: blackbox test for GMSA via 339e7ae186d samba-tool: document that -H can be used with gMSA accounts via 72f0c99a7aa samba-tool: fix some grammar in getpassword docstrings via 113d2aab30f samba-tool: Make samba-tool user getpassword support a ';previous=1' option via 2c54a754842 samba-tool user getpassword: Prepare to support a ;previous=1 option, change behaviour for ;rounds= via 175a13ca134 selftest: Modify expected output of 'samba-tool user getpassword' to be more consistant via 562bde91b44 selftest: fix failing user setpassword test via 8b67a86584d samba-tool: Add support for getting the generated unicodePwd for a gMSA account via 9557140f196 netcmd: user: samba-tool support to allow non-windows use of GMSA accounts (show password) via 23326105cd6 samba-tool user getpassword: Use UTF16_MUNGED charcnv to map "UTF16" to UTF8 via f89a2065a68 samba-tool: Prepare to allow samba-tool user getpasswords to operate against a remote server via c5a2d57e5fa netcmd: models: add object sid field to User model via bf37d538e63 netcmd: getpassword: print OK message on stderr via 587642a63ad selftest: Avoid assertTrue() and assertFalse() where a better test exists via ba29bb54cad selftest: require named parameters for callers of connect_samdb() and connect_samdb_ex() via 5e823724389 selftest: add get_env_credentials() via 18fd2e4ff35 selftest: make get_loadparm a classmethod via 9f8786f0edc selftest: make _get_attribute use parse_ldif via a30657d42f4 selftest: make _get_attribute a method on base class via 6ed2b445f55 selftest: pep8: fix incorrect number of blank lines via 2f5b06253bb selftest: remove unused imports from virtualCryptSHA tests via b236856a3e3 selftest: function _get_attribute() was in two places from 8cfc6ea9232 Revert "rpc_server:srvsvc - retrieve share ACL via root context"
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 31637d403719613a536028ef35ef8504288b8946 Author: Andrew Bartlett <abart...@samba.org> Date: Mon Dec 18 17:24:26 2023 +1300 WHATSNEW: Add entry for "samba-tool user get-kerberos-ticket" Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Autobuild-User(master): Douglas Bagnall <dbagn...@samba.org> Autobuild-Date(master): Thu Dec 21 03:04:12 UTC 2023 on atb-devel-224 commit 7c9fa2804b8e0ef3cef0365da58a8bae4f170840 Author: Andrew Bartlett <abart...@samba.org> Date: Fri Dec 15 17:10:42 2023 +1300 selftest: Add tests for "samba-tool user get-kerberos-ticket" Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit d8b3b1fed9a30edd16d04b2094ceaf8e3571a7de Author: Andrew Bartlett <abart...@samba.org> Date: Thu Dec 14 14:50:05 2023 +1300 python/netcmd: Improve documentation for "samba-tool user getpassword" Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 8eadc19f35ee90ca318c43a90fef7fcdbec263bd Author: Andrew Bartlett <abart...@samba.org> Date: Thu Dec 14 14:43:44 2023 +1300 python/netcmd: Add "samba-tool user get-kerberos-ticket" to get a ticket for a gMSA Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit a39e19dfa759c62cd59545da8ead13d2ae49e6e0 Author: Andrew Bartlett <abart...@samba.org> Date: Mon Dec 18 17:14:27 2023 +1300 WHATSNEW: Add entry for "samba-tool user getpassword" changes Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 128710c2f3c1ee3dd73eba8d755ea7caeb9f3196 Author: Rob van der Linde <r...@catalyst.net.nz> Date: Thu Dec 7 15:53:01 2023 +1300 python: tests: blackbox test for GMSA Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 339e7ae186d5fe3569652f173988858b7e9651e4 Author: Rob van der Linde <r...@catalyst.net.nz> Date: Fri Dec 15 15:12:42 2023 +1300 samba-tool: document that -H can be used with gMSA accounts Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 72f0c99a7aa4f44cbb1b96be73e14d1f506fff7b Author: Rob van der Linde <r...@catalyst.net.nz> Date: Fri Dec 15 15:10:39 2023 +1300 samba-tool: fix some grammar in getpassword docstrings Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 113d2aab30fc84e5434d5475982ae579d8433b70 Author: Andrew Bartlett <abart...@samba.org> Date: Mon Dec 11 20:56:16 2023 +1300 samba-tool: Make samba-tool user getpassword support a ';previous=1' option Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 2c54a754842e0deb6e6a4944fde6dec37d7742a2 Author: Andrew Bartlett <abart...@samba.org> Date: Mon Dec 11 20:55:10 2023 +1300 samba-tool user getpassword: Prepare to support a ;previous=1 option, change behaviour for ;rounds= This will return the previous password, but the pattern is to include the option in the returned attribute name, so we need to use vatter["raw_attr"], not 'a'. This changes the behaviour for the ;rounds= option used when we hold the plaintext password (possibly under GPG encryption). This is now consistant with other parameters in the LDAP attribute, and is now included in the returned attribute name. Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 175a13ca134a2c990ae20df83f80ed4194055c96 Author: Andrew Bartlett <abart...@samba.org> Date: Mon Dec 11 21:40:44 2023 +1300 selftest: Modify expected output of 'samba-tool user getpassword' to be more consistant This is consistant with ;format= support for time attributes and other users of this parameter style elsewhere in LDAP. Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 562bde91b44620a475923b90d76eb2eaf5109141 Author: Rob van der Linde <r...@catalyst.net.nz> Date: Fri Dec 15 12:36:14 2023 +1300 selftest: fix failing user setpassword test A side effect of being able to generate at read time unicodePwd for a gMSA is that we can also generate the unicodePwd from a virtualSambaGPG password. Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 8b67a86584d20b59a1e2af7c37f342870a505192 Author: Andrew Bartlett <abart...@samba.org> Date: Mon Dec 11 20:49:44 2023 +1300 samba-tool: Add support for getting the generated unicodePwd for a gMSA account This pre-hashed value may be more practical to use than the random "UTF-16" password. In particular it is easy to compare with the DB values. Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 9557140f1969650192569da2168677195de01933 Author: Rob van der Linde <r...@catalyst.net.nz> Date: Fri Dec 1 16:14:16 2023 +1300 netcmd: user: samba-tool support to allow non-windows use of GMSA accounts (show password) Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 23326105cd612d8c1fea1a4d7f1f3c5117d5a674 Author: Andrew Bartlett <abart...@samba.org> Date: Tue Dec 12 16:38:13 2023 +1300 samba-tool user getpassword: Use UTF16_MUNGED charcnv to map "UTF16" to UTF8 This copes with random invalid UTF-16 as seen with gMSA accounts. Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit f89a2065a686a20532813e8b2e80987da61333e1 Author: Andrew Bartlett <abart...@samba.org> Date: Mon Dec 11 16:54:57 2023 +1300 samba-tool: Prepare to allow samba-tool user getpasswords to operate against a remote server While passwords are not normally available for read, Group Managed Service Account passwords are, as this is how they are distributed. Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit c5a2d57e5fa8d42e3a1028a4274163b56a16f079 Author: Rob van der Linde <r...@catalyst.net.nz> Date: Thu Dec 7 15:29:27 2023 +1300 netcmd: models: add object sid field to User model Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit bf37d538e63791d740a9a0bc50557915e7401c0e Author: Rob van der Linde <r...@catalyst.net.nz> Date: Thu Dec 7 15:28:04 2023 +1300 netcmd: getpassword: print OK message on stderr This makes it easier to machine parse the output in tests Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 587642a63ad3d35718e0d789a8227bcac4debe36 Author: Andrew Bartlett <abart...@samba.org> Date: Mon Dec 11 17:41:21 2023 +1300 selftest: Avoid assertTrue() and assertFalse() where a better test exists This allows the unittest framework to show the strings that the value was not found in. Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit ba29bb54cada2e0d01a8b6f7a7587696d44fa1f9 Author: Rob van der Linde <r...@catalyst.net.nz> Date: Wed Dec 13 14:03:14 2023 +1300 selftest: require named parameters for callers of connect_samdb() and connect_samdb_ex() Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 5e823724389984379ae1f624cf1051a77179ef28 Author: Rob van der Linde <r...@catalyst.net.nz> Date: Wed Dec 13 14:00:45 2023 +1300 selftest: add get_env_credentials() This is like get_credentials but works for tests that are based on environment variable for usernames and passwords. Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 18fd2e4ff35e4ec3491a1836c1896c1417126b08 Author: Rob van der Linde <r...@catalyst.net.nz> Date: Wed Dec 13 14:00:00 2023 +1300 selftest: make get_loadparm a classmethod Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 9f8786f0edc3427361a6777a7f1868a66ed4cc83 Author: Rob van der Linde <r...@catalyst.net.nz> Date: Thu Dec 14 12:57:09 2023 +1300 selftest: make _get_attribute use parse_ldif Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit a30657d42f4368027fe699e817228d35391244b5 Author: Rob van der Linde <r...@catalyst.net.nz> Date: Wed Dec 13 16:50:18 2023 +1300 selftest: make _get_attribute a method on base class Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 6ed2b445f5508fce69fe9080ff21cf1a71595f08 Author: Rob van der Linde <r...@catalyst.net.nz> Date: Wed Dec 13 16:41:11 2023 +1300 selftest: pep8: fix incorrect number of blank lines Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 2f5b06253bb01e56518d1f7fdfb8a7b542f19609 Author: Rob van der Linde <r...@catalyst.net.nz> Date: Wed Dec 13 16:40:17 2023 +1300 selftest: remove unused imports from virtualCryptSHA tests Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit b236856a3e38a390ffd980fb9bd507801df826c1 Author: Rob van der Linde <r...@catalyst.net.nz> Date: Wed Dec 13 16:39:06 2023 +1300 selftest: function _get_attribute() was in two places Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> ----------------------------------------------------------------------- Summary of changes: WHATSNEW.txt | 42 +++++ docs-xml/manpages/samba-tool.8.xml | 5 + python/samba/netcmd/domain/models/user.py | 3 +- python/samba/netcmd/user/__init__.py | 7 +- python/samba/netcmd/user/readpasswords/__init__.py | 1 + python/samba/netcmd/user/readpasswords/common.py | 118 +++++++++---- .../user/readpasswords/get_kerberos_ticket.py | 146 +++++++++++++++ .../samba/netcmd/user/readpasswords/getpassword.py | 38 ++-- .../netcmd/user/readpasswords/syncpasswords.py | 6 +- python/samba/netcmd/user/setexpiry.py | 2 +- python/samba/tests/__init__.py | 31 +++- python/samba/tests/samba_tool/user.py | 9 +- .../tests/samba_tool/user_get_kerberos_ticket.py | 195 +++++++++++++++++++++ .../tests/samba_tool/user_getpassword_gmsa.py | 171 ++++++++++++++++++ .../samba/tests/samba_tool/user_virtualCryptSHA.py | 100 +++++------ .../tests/samba_tool/user_virtualCryptSHA_base.py | 30 +--- .../tests/samba_tool/user_virtualCryptSHA_gpg.py | 105 +++++------ .../user_virtualCryptSHA_userPassword.py | 59 ++++--- python/samba/tests/samba_tool/user_wdigest.py | 5 +- .../samba-tool-user-get-kerberos-ticket | 5 + selftest/knownfail.d/user_getpassword_gmsa | 1 + source4/selftest/tests.py | 5 + 22 files changed, 847 insertions(+), 237 deletions(-) create mode 100644 python/samba/netcmd/user/readpasswords/get_kerberos_ticket.py create mode 100644 python/samba/tests/samba_tool/user_get_kerberos_ticket.py create mode 100644 python/samba/tests/samba_tool/user_getpassword_gmsa.py create mode 100644 selftest/knownfail.d/samba-tool-user-get-kerberos-ticket create mode 100644 selftest/knownfail.d/user_getpassword_gmsa Changeset truncated at 500 lines: diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 12dff08271c..aba6726840c 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -38,6 +38,48 @@ source tree. While there will be some differences - due to features chosen by packagers - comparing these lists with the build dependencies in a package may locate other dependencies we no longer require. +samba-tool user getpassword / syncpasswords ;rounds= change +----------------------------------------------------------- + +The password access tool "samba-tool user getpassword" and the +password sync tool "samba-tool user syncpasswords" allow attributes to +be chosen for output, and accept parameters like +pwdLastSet;format=GeneralizedTime + +These attributes then appear, in the same format, as the attributes in +the LDIF output. This was not the case for the ;rounds= parameter of +virtualCryptSHA256 and virtualCryptSHA512, for example as +--attributes="virtualCryptSHA256;rounds=50000" + +This release makes the behaviour consistent between these two +features. Installations using GPG-encrypted passwords (or plaintext +storage) and the rounds= option, will find the output has changed + +from: +virtualCryptSHA256: {CRYPT}$5$rounds=2561$hXem.M9onhM9Vuix$dFdSBwF + +to: +virtualCryptSHA256;rounds=2561: {CRYPT}$5$rounds=2561$hXem.M9onhM9Vuix$dFdSBwF + +Group Managed service account client-side features +-------------------------------------------------- + +samba-tool has been extended to provide client-side support for Group +Managed Service accounts. These accounts have passwords that change +automatically, giving the advantages of service isolation without risk +of poor, unchanging passwords. + +Where possible, Samba's existing samba-tool password handling +commands, which in the past have only operated against the local +sam.ldb have been extended to permit operation against a remote server +with authenticated access to "-H ldap://$DCNAME" + +Supported operations include: + - reading the current and previous gMSA password via + "samba-tool user getpassword" + - writing a Kerberos Ticket Granting Ticket (TGT) to a local + credentials cache with a new command + "samba-tool user get-kerberos-ticket" REMOVED FEATURES ================ diff --git a/docs-xml/manpages/samba-tool.8.xml b/docs-xml/manpages/samba-tool.8.xml index 6b3a73020e3..3471b0e1991 100644 --- a/docs-xml/manpages/samba-tool.8.xml +++ b/docs-xml/manpages/samba-tool.8.xml @@ -2743,6 +2743,11 @@ <para>Gets the password of a user account.</para> </refsect3> +<refsect3> + <title>user get-kerberos-ticket <replaceable>username</replaceable> [options]</title> + <para>Gets a Kerberos Ticket Granting Ticket as the account.</para> +</refsect3> + <refsect3> <title>user syncpasswords <replaceable>--cache-ldb-initialize</replaceable> [options]</title> <para>Syncs the passwords of all user accounts, using an optional script.</para> diff --git a/python/samba/netcmd/domain/models/user.py b/python/samba/netcmd/domain/models/user.py index 79e30453532..7b0785a0fb3 100644 --- a/python/samba/netcmd/domain/models/user.py +++ b/python/samba/netcmd/domain/models/user.py @@ -24,7 +24,7 @@ from ldb import Dn from samba.dsdb import DS_GUID_USERS_CONTAINER -from .fields import DnField, StringField +from .fields import DnField, SIDField, StringField from .model import Model @@ -32,6 +32,7 @@ class User(Model): username = StringField("sAMAccountName") assigned_policy = DnField("msDS-AssignedAuthNPolicy") assigned_silo = DnField("msDS-AssignedAuthNPolicySilo") + object_sid = SIDField("objectSid") def __str__(self): """Return username rather than cn for User model.""" diff --git a/python/samba/netcmd/user/__init__.py b/python/samba/netcmd/user/__init__.py index 6175e651ed9..fab657c2278 100644 --- a/python/samba/netcmd/user/__init__.py +++ b/python/samba/netcmd/user/__init__.py @@ -30,8 +30,10 @@ from .getgroups import cmd_user_getgroups from .list import cmd_user_list from .move import cmd_user_move from .password import cmd_user_password -from .readpasswords import (cmd_user_getpassword, cmd_user_show, - cmd_user_syncpasswords) +from .readpasswords import (cmd_user_getpassword, + cmd_user_show, + cmd_user_syncpasswords, + cmd_user_get_kerberos_ticket) from .rename import cmd_user_rename from .sensitive import cmd_user_sensitive from .setexpiry import cmd_user_setexpiry @@ -57,6 +59,7 @@ class cmd_user(SuperCommand): subcommands["setprimarygroup"] = cmd_user_setprimarygroup() subcommands["setpassword"] = cmd_user_setpassword() subcommands["getpassword"] = cmd_user_getpassword() + subcommands["get-kerberos-ticket"] = cmd_user_get_kerberos_ticket() subcommands["syncpasswords"] = cmd_user_syncpasswords() subcommands["edit"] = cmd_user_edit() subcommands["show"] = cmd_user_show() diff --git a/python/samba/netcmd/user/readpasswords/__init__.py b/python/samba/netcmd/user/readpasswords/__init__.py index 8ca999b0215..75ba31365b7 100644 --- a/python/samba/netcmd/user/readpasswords/__init__.py +++ b/python/samba/netcmd/user/readpasswords/__init__.py @@ -22,3 +22,4 @@ from .getpassword import cmd_user_getpassword from .show import cmd_user_show from .syncpasswords import cmd_user_syncpasswords +from .get_kerberos_ticket import cmd_user_get_kerberos_ticket diff --git a/python/samba/netcmd/user/readpasswords/common.py b/python/samba/netcmd/user/readpasswords/common.py index 02f7d36f5fc..6d44881823d 100644 --- a/python/samba/netcmd/user/readpasswords/common.py +++ b/python/samba/netcmd/user/readpasswords/common.py @@ -30,7 +30,7 @@ import ldb from samba import credentials, nttime2float from samba.auth import system_session from samba.common import get_bytes, get_string -from samba.dcerpc import drsblobs, security +from samba.dcerpc import drsblobs, security, gmsa from samba.ndr import ndr_unpack from samba.netcmd import Command, CommandError from samba.samdb import SamDB @@ -99,6 +99,9 @@ virtual_attributes = { "virtualSambaGPG": { "flags": ldb.ATTR_FLAG_FORCE_BASE64_LDIF, }, + "unicodePwd": { + "flags": ldb.ATTR_FLAG_FORCE_BASE64_LDIF, + }, } @@ -188,23 +191,23 @@ class GetPasswordCommand(Command): flags = ldb.ATTR_FLAG_HIDDEN | virtual_attributes[a].get("flags", 0) samdb.schema_attribute_add(a, flags, ldb.SYNTAX_OCTET_STRING) - def connect_system_samdb(self, url, allow_local=False, verbose=False): + def connect_for_passwords(self, url, + creds=None, + require_ldapi=True, + verbose=False): # using anonymous here, results in no authentication # which means we can get system privileges via # the privileged ldapi socket - creds = credentials.Credentials() - creds.set_anonymous() + anon_creds = credentials.Credentials() + anon_creds.set_anonymous() - if url is None and allow_local: + if url is None and not require_ldapi: pass elif url.lower().startswith("ldapi://"): + creds = anon_creds pass - elif url.lower().startswith("ldap://"): - raise CommandError("--url ldap:// is not supported for this command") - elif url.lower().startswith("ldaps://"): - raise CommandError("--url ldaps:// is not supported for this command") - elif not allow_local: + elif require_ldapi: raise CommandError("--url requires an ldapi:// url for this command") if verbose: @@ -213,19 +216,20 @@ class GetPasswordCommand(Command): samdb = SamDB(url=url, session_info=system_session(), credentials=creds, lp=self.lp) - try: - # - # Make sure we're connected as SYSTEM - # - res = samdb.search(base='', scope=ldb.SCOPE_BASE, attrs=["tokenGroups"]) - assert len(res) == 1 - sids = res[0].get("tokenGroups") - assert len(sids) == 1 - sid = ndr_unpack(security.dom_sid, sids[0]) - assert str(sid) == security.SID_NT_SYSTEM - except Exception as msg: - raise CommandError("You need to specify an URL that gives privileges as SID_NT_SYSTEM(%s)" % - (security.SID_NT_SYSTEM)) + if require_ldapi or url is None: + try: + # + # Make sure we're connected as SYSTEM + # + res = samdb.search(base='', scope=ldb.SCOPE_BASE, attrs=["tokenGroups"]) + assert len(res) == 1 + sids = res[0].get("tokenGroups") + assert len(sids) == 1 + sid = ndr_unpack(security.dom_sid, sids[0]) + assert str(sid) == security.SID_NT_SYSTEM + except Exception as msg: + raise CommandError("You need to specify an URL that gives privileges as SID_NT_SYSTEM(%s)" % + (security.SID_NT_SYSTEM)) self.inject_virtual_attributes(samdb) @@ -322,6 +326,7 @@ class GetPasswordCommand(Command): required_attrs = [ "supplementalCredentials", "unicodePwd", + "msDS-ManagedPassword", ] for required_attr in required_attrs: a = parse_raw_attr(required_attr, is_hidden=True) @@ -349,6 +354,8 @@ class GetPasswordCommand(Command): raise CommandError("Failed to get password for user '%s': %s" % (username or filter, msg)) obj = res[0] + calculated = {} + sc = None unicodePwd = None if "supplementalCredentials" in obj: @@ -356,6 +363,17 @@ class GetPasswordCommand(Command): sc = ndr_unpack(drsblobs.supplementalCredentialsBlob, sc_blob) if "unicodePwd" in obj: unicodePwd = obj["unicodePwd"][0] + if "msDS-ManagedPassword" in obj: + # unpack a GMSA managed password as if we could read the + # hidden password attributes. + managed_password = obj["msDS-ManagedPassword"][0] + unpacked_managed_password = ndr_unpack(gmsa.MANAGEDPASSWORD_BLOB, + managed_password) + calculated["Primary:CLEARTEXT"] = \ + unpacked_managed_password.passwords.current + calculated["OLDCLEARTEXT"] = \ + unpacked_managed_password.passwords.previous + account_name = str(obj["sAMAccountName"][0]) if "userPrincipalName" in obj: account_upn = str(obj["userPrincipalName"][0]) @@ -363,8 +381,6 @@ class GetPasswordCommand(Command): realm = samdb.domain_dns_name() account_upn = "%s@%s" % (account_name, realm.lower()) - calculated = {} - def get_package(name, min_idx=0): if name in calculated: return calculated[name] @@ -383,6 +399,17 @@ class GetPasswordCommand(Command): return binascii.a2b_hex(p.data) return None + def get_cleartext(attr_opts): + param = get_option(attr_opts, "previous") + if param: + if param != "1": + raise CommandError( + f"Invalid attribute parameter ;previous={param}, " + "only supported value is previous=1") + return calculated.get("OLDCLEARTEXT") + else: + return get_package("Primary:CLEARTEXT") + def get_kerberos_ctr(): primary_krb5 = get_package("Primary:Kerberos-Newer-Keys") if primary_krb5 is None: @@ -453,14 +480,14 @@ class GetPasswordCommand(Command): username or account_name, e)) def get_utf8(a, b, username): - try: - u = str(get_bytes(b), 'utf-16-le') - except UnicodeDecodeError as e: - self.outf.write("WARNING: '%s': CLEARTEXT is invalid UTF-16-LE unable to generate %s\n" % ( - username, a)) - return None - u8 = u.encode('utf-8') - return u8 + creds_for_charcnv = credentials.Credentials() + creds_for_charcnv.set_anonymous() + creds_for_charcnv.set_utf16_password(get_bytes(b)) + + # This can't fail due to character conversion issues as it + # includes a built-in fallback (UTF16_MUNGED) matching + # exactly what we need. + return creds_for_charcnv.get_password().encode() # Extract the WDigest hash for the value specified by i. # Builds an htdigest compatible value @@ -582,7 +609,7 @@ class GetPasswordCommand(Command): 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") + b = get_cleartext(attr_opts) if b is not None: u8 = get_utf8(a, b, username or account_name) if u8 is not None: @@ -650,6 +677,14 @@ class GetPasswordCommand(Command): except ValueError: return 0 + def get_unicode_pwd_hash(pwd): + # We can't read unicodePwd directly, but we can regenerate + # it from msDS-ManagedPassword + tmp = credentials.Credentials() + tmp.set_anonymous() + tmp.set_utf16_password(pwd) + return tmp.get_nt_hash() + # We use sort here in order to have a predictable processing order for a in sorted(virtual_attributes.keys()): vattr = None @@ -665,7 +700,7 @@ class GetPasswordCommand(Command): attr_opts = vattr["opts"] if a == "virtualClearTextUTF8": - b = get_package("Primary:CLEARTEXT") + b = get_cleartext(attr_opts) if b is None: continue u8 = get_utf8(a, b, username or account_name) @@ -673,11 +708,11 @@ class GetPasswordCommand(Command): continue v = u8 elif a == "virtualClearTextUTF16": - v = get_package("Primary:CLEARTEXT") + v = get_cleartext(attr_opts) if v is None: continue elif a == "virtualSSHA": - b = get_package("Primary:CLEARTEXT") + b = get_cleartext(attr_opts) if b is None: continue u8 = get_utf8(a, b, username or account_name) @@ -714,6 +749,13 @@ class GetPasswordCommand(Command): v = kerberos_salt if v is None: continue + elif a == "unicodePwd" and unicodePwd is None: + if "Primary:CLEARTEXT" in calculated and not get_option(attr_opts, "previous"): + v = get_unicode_pwd_hash(calculated["Primary:CLEARTEXT"]) + elif "OLDCLEARTEXT" in calculated and get_option(attr_opts, "previous"): + v = get_unicode_pwd_hash(calculated["OLDCLEARTEXT"]) + else: + continue elif a.startswith("virtualWDigest"): primary_wdigest = get_package("Primary:WDigest") if primary_wdigest is None: @@ -730,7 +772,7 @@ class GetPasswordCommand(Command): continue else: continue - obj[a] = ldb.MessageElement(v, ldb.FLAG_MOD_REPLACE, a) + obj[a] = ldb.MessageElement(v, ldb.FLAG_MOD_REPLACE, vattr["raw_attr"]) def get_src_attrname(srcattrg): srcattrl = srcattrg.lower() diff --git a/python/samba/netcmd/user/readpasswords/get_kerberos_ticket.py b/python/samba/netcmd/user/readpasswords/get_kerberos_ticket.py new file mode 100644 index 00000000000..3a8296b187a --- /dev/null +++ b/python/samba/netcmd/user/readpasswords/get_kerberos_ticket.py @@ -0,0 +1,146 @@ +# user management +# +# user get-kerberos-ticket command - obtain a TGT for a database user +# +# Copyright Jelmer Vernooij 2010 <jel...@samba.org> +# Copyright Theresa Halloran 2011 <theresahallo...@gmail.com> +# Copyright Andrew Bartlett 2023 <abart...@samba.org> +# +# 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/>. +# + +import ldb +import samba.getopt as options +from samba.netcmd import CommandError, Option +from samba.credentials import Credentials +from .common import ( + GetPasswordCommand, + gpg_decrypt, + decrypt_samba_gpg_help, +) +from samba.dcerpc import samr + +class cmd_user_get_kerberos_ticket(GetPasswordCommand): + """Get a Kerberos Ticket Granting Ticket as a user + +This command gets a Kerberos TGT using the password for a user/computer account. + +The username specified on the command is the sAMAccountName. +The username may also be specified using the --filter option. + +The command must be run from the root user id or another authorized +user id. The '-H' or '--URL' option supports ldap:// for remote Group +Managed Service accounts, and ldapi:// or tdb:// can be used to +adjust the local path. tdb:// is used by default for a bare path. + +The --output-krb5-ccache option should point to a location for the +credentials cache. The default is a FILE: type cache if no prefix is +specified. + +The '--decrypt-samba-gpg' option triggers decryption of the +Primary:SambaGPG buffer to get the password. + +Check with '--help' if this feature is available +in your environment or not (the python-gpgme package is required). Please +note that you might need to set the GNUPGHOME environment variable. If the +decryption key has a passphrase you have to make sure that the GPG_AGENT_INFO +environment variable has been set correctly and the passphrase is already +known by the gpg-agent. + +Example1: +samba-tool user get-kerberos-ticket TestUser1 --output-krb5-ccache=/srv/service/krb5_ccache + +Example2: +samba-tool user get-kerberos-ticket --filter='(samAccountName=TestUser3)' --output-krb5-ccache=FILE:/srv/service/krb5_ccache + + """ + synopsis = "%prog (<username>|--filter <filter>) [options]" + + takes_optiongroups = { + "sambaopts": options.SambaOptions, + "versionopts": options.VersionOptions, + "credopts": options.CredentialsOptions, + "hostopts": options.HostOptions, + } + + takes_options = [ + Option("--filter", help="LDAP Filter to get Kerberos ticket for (must match single account)", type=str), + Option("--output-krb5-ccache", type=str, + help="Location of Kerberos credentials cache to write ticket into", + metavar="CCACHE", dest="output_krb5_ccache"), + Option("--decrypt-samba-gpg", + help=decrypt_samba_gpg_help, + action="store_true", default=False, dest="decrypt_samba_gpg"), + ] + + takes_args = ["username?"] + + def run(self, username=None, H=None, filter=None, + attributes=None, decrypt_samba_gpg=None, + sambaopts=None, versionopts=None, hostopts=None, + credopts=None, output_krb5_ccache=None): + self.lp = sambaopts.get_loadparm() + + if decrypt_samba_gpg and not gpg_decrypt: + raise CommandError(decrypt_samba_gpg_help) + + if filter is None and username is None: + raise CommandError("Either the username or '--filter' must be specified!") + + if filter is None: + filter = "(&(objectClass=user)(sAMAccountName=%s))" % (ldb.binary_encode(username)) + + password_attrs = ["virtualClearTextUTF16", "samAccountName", "unicodePwd"] + + creds = credopts.get_credentials(self.lp) + samdb = self.connect_for_passwords(url=hostopts.H, require_ldapi=False, creds=creds) + + obj = self.get_account_attributes(samdb, username, + basedn=None, + filter=filter, + scope=ldb.SCOPE_SUBTREE, + attrs=password_attrs, + decrypt=decrypt_samba_gpg) + + lp_ctx = sambaopts.get_loadparm() + + creds = Credentials() + creds.set_username(str(obj["samAccountName"][0])) + creds.set_realm(samdb.domain_dns_name()) + + utf16_pw = None + nt_pass = None + try: + utf16_pw = obj["virtualClearTextUTF16"][0] -- Samba Shared Repository