The branch, master has been updated
via 0bb3490 s3:user_auth_info: let struct user_auth_info use struct
cli_credentials internally
via 4fb0e65 s3:popt_common: let POPT_COMMON_CREDENTIALS imply logfile
and conffile loading
via d7fb3bb tests/credentials.py: demonstrate the last 'username' line
of creds.parse_file() beats other lines
via 05e8bfd auth/credentials: change the parsing order of
cli_credentials_parse_file()
via 250df9d tests/credentials.py: verify the new
cli_credentials_parse_file() 'username' parsing
via d487591 auth/credentials: let cli_credentials_parse_file() handle
'username' with cli_credentials_parse_string()
via 6b6c07f tests/credentials.py: add tests to verify realm/principal
behaviour of cli_credentials_parse_string()
via eaf3d44 auth/credentials: let cli_credentials_parse_string() always
reset principal and realm
via 6b18ac6 auth/credentials: let cli_credentials_parse_string() always
reset username and domain
via 86558b5 tests/credentials.py: add tests with a realm from smb.conf
via dab9456 auth/credentials: handle situations without a configured
(default) realm
via 7c344fb auth/credentials: add python bindings for enum
credentials_obtained
via 9fa7f59 tests/credentials.py: add very simple test for
py_creds_parse_file
via df652c3 auth/credentials: add py_creds_parse_file()
via 63dabd2 tests/credentials.py: verify the difference of
parse_string("someone") and parse_string("someone%")
via d29f7dc tests/credentials.py: add test for
cli_credentials_set_password_will_be_nt_hash()
via 1565469 auth/credentials: add
cli_credentials_set_password_will_be_nt_hash() and the related logic
via a3f03df auth/credentials: let cli_credentials_set_password() fail
if talloc_strdup() fails
via 8415cca auth/credentials: make use of talloc_zero() in
cli_credentials_init()
via 787cf39 s4-rpc_server: Add braces to better follow coding style
via abbd0a8 s4-netlogon: Push the netlogon server in the AD DC into
multiple processes
via 86e706a selftest: Use 'rpc server port:netlogon' and 'rpc server
port' smb.conf option
via b81cf02 s4-rpc_server: Do not check association groups for NETLOGON
via 6dc14b0 s4-rpc_server: Allow listener for RPC servers to use
multiple processes
via ffb8b50 s4-rpc_server: Allow each interface to declare if it uses
handles
via 5ea6708 s4-rpc_server: Add comments explaining the control flow
around dcesrv_bind()
from b38f1ae s3:utils: Use cli_cm_force_encryption() instead of
cli_force_encryption()
https://git.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit 0bb3490329310e81147c56f42fa7b07350cfb384
Author: Stefan Metzmacher <[email protected]>
Date: Fri Oct 28 12:14:37 2016 +0200
s3:user_auth_info: let struct user_auth_info use struct cli_credentials
internally
This way we can have a very simple get_cmdline_auth_info_creds() function,
which can be used pass cli_credentials down the stack instead of
constantly translating from user_auth_info to cli_credentials, while
loosing information.
Signed-off-by: Stefan Metzmacher <[email protected]>
Reviewed-by: Andrew Bartlett <[email protected]>
Autobuild-User(master): Andrew Bartlett <[email protected]>
Autobuild-Date(master): Tue Dec 20 04:57:05 CET 2016 on sn-devel-144
commit 4fb0e65a857f601562da72c6d6087d86ba3196a0
Author: Stefan Metzmacher <[email protected]>
Date: Fri Dec 9 16:04:38 2016 +0100
s3:popt_common: let POPT_COMMON_CREDENTIALS imply logfile and conffile
loading
All users of POPT_COMMON_CREDENTIALS basically need the same logic,
while some ignore a broken smb.conf and some complain about it.
This will allow the future usage of config options in the
credential post processing.
Signed-off-by: Stefan Metzmacher <[email protected]>
Reviewed-by: Andrew Bartlett <[email protected]>
commit d7fb3bb5721f3903fd985d2121f893a42761fc07
Author: Stefan Metzmacher <[email protected]>
Date: Thu Dec 15 15:30:28 2016 +0100
tests/credentials.py: demonstrate the last 'username' line of
creds.parse_file() beats other lines
Signed-off-by: Stefan Metzmacher <[email protected]>
Reviewed-by: Andrew Bartlett <[email protected]>
commit 05e8bfdc95437c4a0ac087f1767bae7f5b930283
Author: Stefan Metzmacher <[email protected]>
Date: Thu Dec 15 12:41:58 2016 +0100
auth/credentials: change the parsing order of cli_credentials_parse_file()
We now first just remember the domain, realm, username, password values
(the last value wins).
At the end we call cli_credentials_set_{realm,domain,password}()
followed by cli_credentials_parse_string() for 'username'.
It means the last 'username' line beats the domain, realm or password
lines, e.g.:
username=USERDOMAIN\username
domain=DOMAIN
will result in cli_credentials_get_domain() returning "USERDOMAIN" instead
of
DOMAIN.
Signed-off-by: Stefan Metzmacher <[email protected]>
Reviewed-by: Andrew Bartlett <[email protected]>
commit 250df9d6374b690daea2839ba7eecb350a42d8e6
Author: Stefan Metzmacher <[email protected]>
Date: Thu Dec 15 14:01:35 2016 +0100
tests/credentials.py: verify the new cli_credentials_parse_file()
'username' parsing
Signed-off-by: Stefan Metzmacher <[email protected]>
Reviewed-by: Andrew Bartlett <[email protected]>
commit d487591f0b8e875093d77edfba66435705240161
Author: Stefan Metzmacher <[email protected]>
Date: Sun Dec 11 22:50:53 2016 +0100
auth/credentials: let cli_credentials_parse_file() handle 'username' with
cli_credentials_parse_string()
Some existing source3 tests (test_smbclient_s3.sh test_auth_file()) use a
credentials file
that looks like this:
username=DOMAIN/username
password=password
domain=DOMAIN
This change allows us to parse the same.
Signed-off-by: Stefan Metzmacher <[email protected]>
Reviewed-by: Andrew Bartlett <[email protected]>
commit 6b6c07f61f439c37e8b226660b23486b8fa546f2
Author: Stefan Metzmacher <[email protected]>
Date: Thu Dec 15 14:12:31 2016 +0100
tests/credentials.py: add tests to verify realm/principal behaviour of
cli_credentials_parse_string()
Signed-off-by: Stefan Metzmacher <[email protected]>
Reviewed-by: Andrew Bartlett <[email protected]>
commit eaf3d44641370514169b74f7e564122354b6cfdf
Author: Stefan Metzmacher <[email protected]>
Date: Wed Dec 14 16:47:57 2016 +0100
auth/credentials: let cli_credentials_parse_string() always reset principal
and realm
If we reset username we need to reset principal if it was set at the same
level.
If domain is reset we also need to use it as realm if realm
was set at the same level. Otherwise we'd build a principal
that belongs to a different user, which would not work
and only increment the wrong lockout counter and result
in wrong authorization tokens to be used.
Signed-off-by: Stefan Metzmacher <[email protected]>
Reviewed-by: Andrew Bartlett <[email protected]>
commit 6b18ac69156de588ec44d812e74ec8391c07d633
Author: Stefan Metzmacher <[email protected]>
Date: Fri Dec 9 12:20:19 2016 +0100
auth/credentials: let cli_credentials_parse_string() always reset username
and domain
If cli_credentials_parse_string() is used we should no longer use
any guessed values and need to make sure username and domain
are reset if principal and realm are set.
Signed-off-by: Stefan Metzmacher <[email protected]>
Reviewed-by: Andrew Bartlett <[email protected]>
commit 86558b5ce8c4df9a6e5b86536c81cd584cdeb20e
Author: Stefan Metzmacher <[email protected]>
Date: Thu Dec 15 14:49:18 2016 +0100
tests/credentials.py: add tests with a realm from smb.conf
As we don't want to create a new smb.conf file
we just simulate it with "creds.set_realm(realm,
credentials.UNINITIALISED)".
That's basically the same as the cli_credentials_set_conf() behaviour
if a realm is specified in the configuration.
Signed-off-by: Stefan Metzmacher <[email protected]>
Reviewed-by: Andrew Bartlett <[email protected]>
commit dab9456cfc4f42e4a7d95443e02460e59816ecbd
Author: Stefan Metzmacher <[email protected]>
Date: Thu Dec 15 11:04:02 2016 +0100
auth/credentials: handle situations without a configured (default) realm
We should not have cli_credentials_get_realm() return "" without a
configured (default) realm in smb.conf.
Note that the existing tests with creds.get_realm() == lp.get("realm")
also work with "" as string.
At the same time we should never let cli_credentials_get_principal()
return "@REALM.EXAMPLE.COM" nor "username@".
If cli_credentials_parse_string() gets "OTHERDOMAIN\username"
we must not use cli_credentials_get_realm() to generate
a principal unless cli_credentials_get_domain() returns
also "OTHERDOMAIN". What we need to do is using
username@OTHERDOMAIN as principal, whild we still
use cli_credentials_get_realm to get a default kdc,
(which may route us to the correct kdc with WRONG_REALM
messages).
Signed-off-by: Stefan Metzmacher <[email protected]>
Reviewed-by: Andrew Bartlett <[email protected]>
commit 7c344fbbe0568734beb982bb6e0f3c81e6eb5843
Author: Stefan Metzmacher <[email protected]>
Date: Thu Dec 15 11:37:33 2016 +0100
auth/credentials: add python bindings for enum credentials_obtained
Signed-off-by: Stefan Metzmacher <[email protected]>
Reviewed-by: Andrew Bartlett <[email protected]>
commit 9fa7f59f88cb0350c0616d6f0a6a06b4e7a52228
Author: Stefan Metzmacher <[email protected]>
Date: Thu Dec 15 10:30:29 2016 +0100
tests/credentials.py: add very simple test for py_creds_parse_file
Signed-off-by: Stefan Metzmacher <[email protected]>
Reviewed-by: Andrew Bartlett <[email protected]>
commit df652c3ede181576f63ae20ccd993203b744952d
Author: Stefan Metzmacher <[email protected]>
Date: Thu Dec 15 10:06:25 2016 +0100
auth/credentials: add py_creds_parse_file()
Signed-off-by: Stefan Metzmacher <[email protected]>
Reviewed-by: Andrew Bartlett <[email protected]>
commit 63dabd2f35224a7ee7468d435e67baa0e059358c
Author: Stefan Metzmacher <[email protected]>
Date: Thu Dec 15 09:42:20 2016 +0100
tests/credentials.py: verify the difference of parse_string("someone") and
parse_string("someone%")
Signed-off-by: Stefan Metzmacher <[email protected]>
Reviewed-by: Andrew Bartlett <[email protected]>
commit d29f7dc13bb705a0cab6de2aeac70c42d83a7af8
Author: Stefan Metzmacher <[email protected]>
Date: Thu Dec 15 09:34:45 2016 +0100
tests/credentials.py: add test for
cli_credentials_set_password_will_be_nt_hash()
Signed-off-by: Stefan Metzmacher <[email protected]>
Reviewed-by: Andrew Bartlett <[email protected]>
commit 1565469bf22cb8aee7467ab76ba64fb5c54b59fe
Author: Stefan Metzmacher <[email protected]>
Date: Wed Dec 14 10:02:10 2016 +0100
auth/credentials: add cli_credentials_set_password_will_be_nt_hash() and
the related logic
Signed-off-by: Stefan Metzmacher <[email protected]>
Reviewed-by: Andrew Bartlett <[email protected]>
commit a3f03df706f3dc8d7875226aa162154a0194f331
Author: Stefan Metzmacher <[email protected]>
Date: Wed Dec 14 08:52:12 2016 +0100
auth/credentials: let cli_credentials_set_password() fail if
talloc_strdup() fails
Signed-off-by: Stefan Metzmacher <[email protected]>
Reviewed-by: Andrew Bartlett <[email protected]>
commit 8415cca557cc556c0524cdf5ef66820d22577fb0
Author: Stefan Metzmacher <[email protected]>
Date: Wed Dec 14 08:50:51 2016 +0100
auth/credentials: make use of talloc_zero() in cli_credentials_init()
Signed-off-by: Stefan Metzmacher <[email protected]>
Reviewed-by: Andrew Bartlett <[email protected]>
commit 787cf39ce6cb6695b7eeee88e1dee32d33853884
Author: Andrew Bartlett <[email protected]>
Date: Wed Dec 14 11:58:48 2016 +1300
s4-rpc_server: Add braces to better follow coding style
Signed-off-by: Andrew Bartlett <[email protected]>
Reviewed-by: Stefan Metzmacher <[email protected]>
commit abbd0a88dee8715dbddc1a2478fe18aafefa385c
Author: Andrew Bartlett <[email protected]>
Date: Mon Nov 21 13:31:39 2016 +1300
s4-netlogon: Push the netlogon server in the AD DC into multiple processes
This allows the NETLOGON server to scale better, as it is often a bottleneck
What we are doing here is keeping the forced single process only for
other servers that declare they use DCE/RPC handles.
Signed-off-by: Andrew Bartlett <[email protected]>
Reviewed-by: Stefan Metzmacher <[email protected]>
commit 86e706a32dbd2259a428009f7097e7ea6c3f4f8d
Author: Andrew Bartlett <[email protected]>
Date: Mon Nov 14 10:15:39 2016 +1300
selftest: Use 'rpc server port:netlogon' and 'rpc server port' smb.conf
option
We need this because once we make NETLOGON run in multiple processes,
it will need its own port, and socket_wrapper can not currently allocate
and ephemeral port. It also tests the option, which others have asked be
made available to firewall drsuapi.
Likewise the 'rpc server port' option is used to confirm it
functions for the default port'.
Signed-off-by: Andrew Bartlett <[email protected]>
Reviewed-by: Garming Sam <[email protected]>
commit b81cf02834bdd5b0925949cc9d42897aa3054746
Author: Andrew Bartlett <[email protected]>
Date: Mon Nov 14 10:11:05 2016 +1300
s4-rpc_server: Do not check association groups for NETLOGON
If this RPC server is not going to use handles (actually a generic
flag) then do not check the assocation group provided. This in turn
allows us to easily make NETLOGON run in multiple processes.
Signed-off-by: Andrew Bartlett <[email protected]>
Reviewed-by: Stefan Metzmacher <[email protected]>
commit 6dc14b0a5d225ca8752088a1ee25edee46c1f956
Author: Andrew Bartlett <[email protected]>
Date: Tue Oct 18 10:36:51 2016 +1300
s4-rpc_server: Allow listener for RPC servers to use multiple processes
To do this we must get the ncacn_ip_tcp listener to split out (for example)
netlogon onto a distinct port, so we change the registration code to split
up each
ncacn_ip_tcp registration to create a new interface for indicated services.
The new option "rpc server port" allows control of the default port and
"rpc server port:netlogon" (also valid for any other pipe from the IDL name)
allows us to both work around limitations in socket_wrapper against
double-binding and allows specification of the port by the administrator.
Signed-off-by: Andrew Bartlett <[email protected]>
Reviewed-by: Stefan Metzmacher <[email protected]>
commit ffb8b50e3c07c833fb7b1a583d21f9dc1166a0a6
Author: Andrew Bartlett <[email protected]>
Date: Mon Nov 14 11:24:03 2016 +1300
s4-rpc_server: Allow each interface to declare if it uses handles
This will allow the NETLOGON server in the AD DC to declare that it does
not use
handles, and so allow some more flexibility with association groups
Signed-off-by: Andrew Bartlett <[email protected]>
Reviewed-by: Stefan Metzmacher <[email protected]>
commit 5ea6708d819c392096413e53196d65108b1e9283
Author: Andrew Bartlett <[email protected]>
Date: Wed Dec 14 09:38:28 2016 +1300
s4-rpc_server: Add comments explaining the control flow around dcesrv_bind()
Signed-off-by: Andrew Bartlett <[email protected]>
Reviewed-by: Stefan Metzmacher <[email protected]>
-----------------------------------------------------------------------
Summary of changes:
auth/credentials/credentials.c | 348 +++++++++++++++++--------
auth/credentials/credentials.h | 2 +
auth/credentials/credentials_internal.h | 2 +
auth/credentials/credentials_ntlm.c | 19 ++
auth/credentials/pycredentials.c | 63 ++++-
docs-xml/smbdotconf/protocol/rpcserverport.xml | 14 +
pidl/lib/Parse/Pidl/Samba4/NDR/Server.pm | 21 +-
python/samba/tests/credentials.py | 243 ++++++++++++++++-
selftest/target/Samba4.pm | 4 +
source3/client/client.c | 11 +-
source3/include/auth_info.h | 6 +
source3/include/popt_common.h | 1 +
source3/lib/popt_common.c | 197 ++------------
source3/lib/util_cmdline.c | 346 ++++++++++++++++--------
source3/rpcclient/rpcclient.c | 15 --
source3/utils/regedit.c | 5 -
source3/utils/smbcacls.c | 5 +-
source3/utils/smbcquotas.c | 12 -
source3/utils/smbtree.c | 5 +-
source4/rpc_server/dcerpc_server.c | 198 ++++++++++++--
source4/rpc_server/dcerpc_server.h | 10 +
source4/rpc_server/dcesrv_mgmt.c | 10 +
source4/rpc_server/handles.c | 10 +
source4/rpc_server/netlogon/dcerpc_netlogon.c | 9 +
source4/rpc_server/remote/dcesrv_remote.c | 1 +
source4/rpc_server/service_rpc.c | 46 +++-
26 files changed, 1102 insertions(+), 501 deletions(-)
create mode 100644 docs-xml/smbdotconf/protocol/rpcserverport.xml
Changeset truncated at 500 lines:
diff --git a/auth/credentials/credentials.c b/auth/credentials/credentials.c
index c8f86ba..9a935c6 100644
--- a/auth/credentials/credentials.c
+++ b/auth/credentials/credentials.c
@@ -36,85 +36,11 @@
*/
_PUBLIC_ struct cli_credentials *cli_credentials_init(TALLOC_CTX *mem_ctx)
{
- struct cli_credentials *cred = talloc(mem_ctx, struct cli_credentials);
+ struct cli_credentials *cred = talloc_zero(mem_ctx, struct
cli_credentials);
if (cred == NULL) {
return cred;
}
- cred->workstation_obtained = CRED_UNINITIALISED;
- cred->username_obtained = CRED_UNINITIALISED;
- cred->password_obtained = CRED_UNINITIALISED;
- cred->domain_obtained = CRED_UNINITIALISED;
- cred->realm_obtained = CRED_UNINITIALISED;
- cred->ccache_obtained = CRED_UNINITIALISED;
- cred->client_gss_creds_obtained = CRED_UNINITIALISED;
- cred->principal_obtained = CRED_UNINITIALISED;
- cred->keytab_obtained = CRED_UNINITIALISED;
- cred->server_gss_creds_obtained = CRED_UNINITIALISED;
-
- cred->ccache_threshold = CRED_UNINITIALISED;
- cred->client_gss_creds_threshold = CRED_UNINITIALISED;
-
- cred->workstation = NULL;
- cred->username = NULL;
- cred->password = NULL;
- cred->old_password = NULL;
- cred->domain = NULL;
- cred->realm = NULL;
- cred->principal = NULL;
- cred->salt_principal = NULL;
- cred->impersonate_principal = NULL;
- cred->self_service = NULL;
- cred->target_service = NULL;
-
- cred->bind_dn = NULL;
-
- cred->nt_hash = NULL;
- cred->old_nt_hash = NULL;
-
- cred->lm_response.data = NULL;
- cred->lm_response.length = 0;
- cred->nt_response.data = NULL;
- cred->nt_response.length = 0;
-
- cred->ccache = NULL;
- cred->client_gss_creds = NULL;
- cred->keytab = NULL;
- cred->server_gss_creds = NULL;
-
- cred->workstation_cb = NULL;
- cred->password_cb = NULL;
- cred->username_cb = NULL;
- cred->domain_cb = NULL;
- cred->realm_cb = NULL;
- cred->principal_cb = NULL;
-
- cred->priv_data = NULL;
-
- cred->netlogon_creds = NULL;
- cred->secure_channel_type = SEC_CHAN_NULL;
-
- cred->kvno = 0;
-
- cred->password_last_changed_time = 0;
-
- cred->smb_krb5_context = NULL;
-
- cred->machine_account_pending = false;
- cred->machine_account_pending_lp_ctx = NULL;
-
- cred->machine_account = false;
-
- cred->password_tries = 0;
-
- cred->callback_running = false;
-
- cli_credentials_set_kerberos_state(cred, CRED_AUTO_USE_KERBEROS);
- cli_credentials_set_gensec_features(cred, 0);
- cli_credentials_set_krb_forwardable(cred, CRED_AUTO_KRB_FORWARDABLE);
-
- cred->forced_sasl_mech = NULL;
-
cred->winbind_separator = '\\';
return cred;
@@ -287,16 +213,37 @@ _PUBLIC_ const char
*cli_credentials_get_principal_and_obtained(struct cli_crede
if (cred->principal_obtained < cred->username_obtained
|| cred->principal_obtained < MAX(cred->domain_obtained,
cred->realm_obtained)) {
+ const char *effective_username = NULL;
+ const char *effective_realm = NULL;
+ enum credentials_obtained effective_obtained;
+
+ effective_username = cli_credentials_get_username(cred);
+ if (effective_username == NULL || strlen(effective_username) ==
0) {
+ *obtained = cred->username_obtained;
+ return NULL;
+ }
+
if (cred->domain_obtained > cred->realm_obtained) {
- *obtained = MIN(cred->domain_obtained,
cred->username_obtained);
- return talloc_asprintf(mem_ctx, "%s@%s",
-
cli_credentials_get_username(cred),
-
cli_credentials_get_domain(cred));
+ effective_realm = cli_credentials_get_domain(cred);
+ effective_obtained = MIN(cred->domain_obtained,
+ cred->username_obtained);
} else {
- *obtained = MIN(cred->realm_obtained,
cred->username_obtained);
+ effective_realm = cli_credentials_get_realm(cred);
+ effective_obtained = MIN(cred->realm_obtained,
+ cred->username_obtained);
+ }
+
+ if (effective_realm == NULL || strlen(effective_realm) == 0) {
+ effective_realm = cli_credentials_get_domain(cred);
+ effective_obtained = MIN(cred->domain_obtained,
+ cred->username_obtained);
+ }
+
+ if (effective_realm != NULL && strlen(effective_realm) != 0) {
+ *obtained = effective_obtained;
return talloc_asprintf(mem_ctx, "%s@%s",
-
cli_credentials_get_username(cred),
- cli_credentials_get_realm(cred));
+ effective_username,
+ effective_realm);
}
}
*obtained = cred->principal_obtained;
@@ -392,7 +339,8 @@ _PUBLIC_ const char *cli_credentials_get_password(struct
cli_credentials *cred)
}
if (cred->password_obtained == CRED_CALLBACK &&
- !cred->callback_running) {
+ !cred->callback_running &&
+ !cred->password_will_be_nt_hash) {
cred->callback_running = true;
cred->password = cred->password_cb(cred);
cred->callback_running = false;
@@ -413,18 +361,54 @@ _PUBLIC_ bool cli_credentials_set_password(struct
cli_credentials *cred,
enum credentials_obtained obtained)
{
if (obtained >= cred->password_obtained) {
+
+ cred->lm_response = data_blob_null;
+ cred->nt_response = data_blob_null;
+ cred->nt_hash = NULL;
+ cred->password = NULL;
+
+ cli_credentials_invalidate_ccache(cred, obtained);
+
cred->password_tries = 0;
+
+ if (val == NULL) {
+ cred->password_obtained = obtained;
+ return true;
+ }
+
+ if (cred->password_will_be_nt_hash) {
+ struct samr_Password *nt_hash = NULL;
+ size_t val_len = strlen(val);
+ size_t converted;
+
+ nt_hash = talloc(cred, struct samr_Password);
+ if (nt_hash == NULL) {
+ return false;
+ }
+
+ converted = strhex_to_str((char *)nt_hash->hash,
+ sizeof(nt_hash->hash),
+ val, val_len);
+ if (converted != sizeof(nt_hash->hash)) {
+ TALLOC_FREE(nt_hash);
+ return false;
+ }
+
+ cred->nt_hash = nt_hash;
+ cred->password_obtained = obtained;
+ return true;
+ }
+
cred->password = talloc_strdup(cred, val);
- if (cred->password) {
- /* Don't print the actual password in talloc memory
dumps */
- talloc_set_name_const(cred->password, "password set via
cli_credentials_set_password");
+ if (cred->password == NULL) {
+ return false;
}
+
+ /* Don't print the actual password in talloc memory dumps */
+ talloc_set_name_const(cred->password,
+ "password set via cli_credentials_set_password");
cred->password_obtained = obtained;
- cli_credentials_invalidate_ccache(cred,
cred->password_obtained);
- cred->nt_hash = NULL;
- cred->lm_response = data_blob(NULL, 0);
- cred->nt_response = data_blob(NULL, 0);
return true;
}
@@ -485,32 +469,85 @@ _PUBLIC_ bool cli_credentials_set_old_password(struct
cli_credentials *cred,
_PUBLIC_ struct samr_Password *cli_credentials_get_nt_hash(struct
cli_credentials *cred,
TALLOC_CTX *mem_ctx)
{
+ enum credentials_obtained password_obtained;
+ enum credentials_obtained ccache_threshold;
+ enum credentials_obtained client_gss_creds_threshold;
+ bool password_is_nt_hash;
const char *password = NULL;
+ struct samr_Password *nt_hash = NULL;
if (cred->nt_hash != NULL) {
- struct samr_Password *nt_hash = talloc(mem_ctx, struct
samr_Password);
- if (!nt_hash) {
- return NULL;
- }
+ /*
+ * If we already have a hash it's easy.
+ */
+ goto return_hash;
+ }
- *nt_hash = *cred->nt_hash;
+ /*
+ * This is a bit tricky, with password_will_be_nt_hash
+ * we still need to get the value via the password_callback
+ * but if we did that we should not remember it's state
+ * in the long run so we need to undo it.
+ */
- return nt_hash;
- }
+ password_obtained = cred->password_obtained;
+ ccache_threshold = cred->ccache_threshold;
+ client_gss_creds_threshold = cred->client_gss_creds_threshold;
+ password_is_nt_hash = cred->password_will_be_nt_hash;
+ cred->password_will_be_nt_hash = false;
password = cli_credentials_get_password(cred);
- if (password) {
- struct samr_Password *nt_hash = talloc(mem_ctx, struct
samr_Password);
- if (!nt_hash) {
- return NULL;
- }
+ cred->password_will_be_nt_hash = password_is_nt_hash;
+ if (password_is_nt_hash && password_obtained == CRED_CALLBACK) {
+ /*
+ * We got the nt_hash as string via the callback,
+ * so we need to undo the state change.
+ *
+ * And also don't remember it as plaintext password.
+ */
+ cred->client_gss_creds_threshold = client_gss_creds_threshold;
+ cred->ccache_threshold = ccache_threshold;
+ cred->password_obtained = password_obtained;
+ cred->password = NULL;
+ }
+
+ if (password == NULL) {
+ return NULL;
+ }
+
+ nt_hash = talloc(cred, struct samr_Password);
+ if (nt_hash == NULL) {
+ return NULL;
+ }
+
+ if (password_is_nt_hash) {
+ size_t password_len = strlen(password);
+ size_t converted;
+
+ converted = strhex_to_str((char *)nt_hash->hash,
+ sizeof(nt_hash->hash),
+ password, password_len);
+ if (converted != sizeof(nt_hash->hash)) {
+ TALLOC_FREE(nt_hash);
+ return false;
+ }
+ } else {
E_md4hash(password, nt_hash->hash);
+ }
- return nt_hash;
+ cred->nt_hash = nt_hash;
+ nt_hash = NULL;
+
+return_hash:
+ nt_hash = talloc(mem_ctx, struct samr_Password);
+ if (nt_hash == NULL) {
+ return NULL;
}
- return NULL;
+ *nt_hash = *cred->nt_hash;
+
+ return nt_hash;
}
/**
@@ -744,6 +781,14 @@ _PUBLIC_ void cli_credentials_parse_string(struct
cli_credentials *credentials,
}
if ((p = strchr_m(uname,'@'))) {
+ /*
+ * We also need to set username and domain
+ * in order to undo the effect of
+ * cli_credentials_guess().
+ */
+ cli_credentials_set_username(credentials, uname, obtained);
+ cli_credentials_set_domain(credentials, "", obtained);
+
cli_credentials_set_principal(credentials, uname, obtained);
*p = 0;
cli_credentials_set_realm(credentials, p+1, obtained);
@@ -752,9 +797,40 @@ _PUBLIC_ void cli_credentials_parse_string(struct
cli_credentials *credentials,
|| (p = strchr_m(uname, '/'))
|| (p = strchr_m(uname, credentials->winbind_separator)))
{
+ const char *domain = NULL;
+
+ domain = uname;
*p = 0;
- cli_credentials_set_domain(credentials, uname, obtained);
uname = p+1;
+
+ if (obtained == credentials->realm_obtained &&
+ !strequal_m(credentials->domain, domain))
+ {
+ /*
+ * We need to undo a former set with the same level
+ * in order to get the expected result from
+ * cli_credentials_get_principal().
+ *
+ * But we only need to do that if the domain
+ * actually changes.
+ */
+ cli_credentials_set_realm(credentials, domain,
obtained);
+ }
+ cli_credentials_set_domain(credentials, domain, obtained);
+ }
+ if (obtained == credentials->principal_obtained &&
+ !strequal_m(credentials->username, uname))
+ {
+ /*
+ * We need to undo a former set with the same level
+ * in order to get the expected result from
+ * cli_credentials_get_principal().
+ *
+ * But we only need to do that if the username
+ * actually changes.
+ */
+ credentials->principal_obtained = CRED_UNINITIALISED;
+ credentials->principal = NULL;
}
cli_credentials_set_username(credentials, uname, obtained);
}
@@ -800,6 +876,7 @@ _PUBLIC_ void cli_credentials_set_conf(struct
cli_credentials *cred,
struct loadparm_context *lp_ctx)
{
const char *sep = NULL;
+ const char *realm = lpcfg_realm(lp_ctx);
cli_credentials_set_username(cred, "", CRED_UNINITIALISED);
if (lpcfg_parm_is_cmdline(lp_ctx, "workgroup")) {
@@ -812,10 +889,13 @@ _PUBLIC_ void cli_credentials_set_conf(struct
cli_credentials *cred,
} else {
cli_credentials_set_workstation(cred,
lpcfg_netbios_name(lp_ctx), CRED_UNINITIALISED);
}
+ if (realm != NULL && strlen(realm) == 0) {
+ realm = NULL;
+ }
if (lpcfg_parm_is_cmdline(lp_ctx, "realm")) {
- cli_credentials_set_realm(cred, lpcfg_realm(lp_ctx),
CRED_SPECIFIED);
+ cli_credentials_set_realm(cred, realm, CRED_SPECIFIED);
} else {
- cli_credentials_set_realm(cred, lpcfg_realm(lp_ctx),
CRED_UNINITIALISED);
+ cli_credentials_set_realm(cred, realm, CRED_UNINITIALISED);
}
sep = lpcfg_winbind_separator(lp_ctx);
@@ -1037,6 +1117,10 @@ _PUBLIC_ bool cli_credentials_parse_file(struct
cli_credentials *cred, const cha
char *ptr, *val, *param;
char **lines;
int i, numlines;
+ const char *realm = NULL;
+ const char *domain = NULL;
+ const char *password = NULL;
+ const char *username = NULL;
lines = file_lines_load(file, &numlines, 0, NULL);
@@ -1067,17 +1151,57 @@ _PUBLIC_ bool cli_credentials_parse_file(struct
cli_credentials *cred, const cha
val++;
if (strwicmp("password", param) == 0) {
- cli_credentials_set_password(cred, val, obtained);
+ password = val;
} else if (strwicmp("username", param) == 0) {
- cli_credentials_set_username(cred, val, obtained);
+ username = val;
} else if (strwicmp("domain", param) == 0) {
- cli_credentials_set_domain(cred, val, obtained);
+ domain = val;
} else if (strwicmp("realm", param) == 0) {
- cli_credentials_set_realm(cred, val, obtained);
+ realm = val;
}
- memset(lines[i], 0, len);
+
+ /*
+ * We need to readd '=' in order to let
+ * the strlen() work in the last loop
+ * that clears the memory.
+ */
+ *ptr = '=';
+ }
+
+ if (realm != NULL && strlen(realm) != 0) {
+ /*
+ * only overwrite with a valid string
+ */
+ cli_credentials_set_realm(cred, realm, obtained);
}
+ if (domain != NULL && strlen(domain) != 0) {
+ /*
+ * only overwrite with a valid string
+ */
+ cli_credentials_set_domain(cred, domain, obtained);
+ }
+
+ if (password != NULL) {
+ /*
+ * Here we allow "".
+ */
+ cli_credentials_set_password(cred, password, obtained);
+ }
+
+ if (username != NULL) {
+ /*
+ * The last "username" line takes preference
+ * if the string also contains domain, realm or
+ * password.
+ */
+ cli_credentials_parse_string(cred, username, obtained);
+ }
+
+ for (i = 0; i < numlines; i++) {
+ len = strlen(lines[i]);
+ memset(lines[i], 0, len);
+ }
talloc_free(lines);
return true;
diff --git a/auth/credentials/credentials.h b/auth/credentials/credentials.h
index 523793f..6b0d83b 100644
--- a/auth/credentials/credentials.h
+++ b/auth/credentials/credentials.h
@@ -201,6 +201,8 @@ bool cli_credentials_set_utf16_password(struct
cli_credentials *cred,
enum credentials_obtained obtained);
bool cli_credentials_set_old_utf16_password(struct cli_credentials *cred,
const DATA_BLOB *password_utf16);
+void cli_credentials_set_password_will_be_nt_hash(struct cli_credentials *cred,
+ bool val);
bool cli_credentials_set_nt_hash(struct cli_credentials *cred,
const struct samr_Password *nt_hash,
enum credentials_obtained obtained);
diff --git a/auth/credentials/credentials_internal.h
b/auth/credentials/credentials_internal.h
index f88ae70..68f1f25 100644
--- a/auth/credentials/credentials_internal.h
+++ b/auth/credentials/credentials_internal.h
@@ -115,6 +115,8 @@ struct cli_credentials {
bool callback_running;
char winbind_separator;
+
+ bool password_will_be_nt_hash;
};
#endif /* __CREDENTIALS_INTERNAL_H__ */
diff --git a/auth/credentials/credentials_ntlm.c
b/auth/credentials/credentials_ntlm.c
index 2a4c141..e6859bf 100644
--- a/auth/credentials/credentials_ntlm.c
+++ b/auth/credentials/credentials_ntlm.c
@@ -301,6 +301,8 @@ _PUBLIC_ bool cli_credentials_set_utf16_password(struct
cli_credentials *cred,
const DATA_BLOB
*password_utf16,
enum credentials_obtained
obtained)
{
+ cred->password_will_be_nt_hash = false;
+
if (password_utf16 == NULL) {
--
Samba Shared Repository