[SCM] Samba Shared Repository - branch master updated

Andrew Bartlett abartlet at samba.org
Tue Dec 20 06:02:50 UTC 2016


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 <metze at samba.org>
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 <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    
    Autobuild-User(master): Andrew Bartlett <abartlet at samba.org>
    Autobuild-Date(master): Tue Dec 20 04:57:05 CET 2016 on sn-devel-144

commit 4fb0e65a857f601562da72c6d6087d86ba3196a0
Author: Stefan Metzmacher <metze at samba.org>
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 <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit d7fb3bb5721f3903fd985d2121f893a42761fc07
Author: Stefan Metzmacher <metze at samba.org>
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 <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 05e8bfdc95437c4a0ac087f1767bae7f5b930283
Author: Stefan Metzmacher <metze at samba.org>
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 <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 250df9d6374b690daea2839ba7eecb350a42d8e6
Author: Stefan Metzmacher <metze at samba.org>
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 <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit d487591f0b8e875093d77edfba66435705240161
Author: Stefan Metzmacher <metze at samba.org>
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 <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 6b6c07f61f439c37e8b226660b23486b8fa546f2
Author: Stefan Metzmacher <metze at samba.org>
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 <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit eaf3d44641370514169b74f7e564122354b6cfdf
Author: Stefan Metzmacher <metze at samba.org>
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 <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 6b18ac69156de588ec44d812e74ec8391c07d633
Author: Stefan Metzmacher <metze at samba.org>
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 <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 86558b5ce8c4df9a6e5b86536c81cd584cdeb20e
Author: Stefan Metzmacher <metze at samba.org>
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 <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit dab9456cfc4f42e4a7d95443e02460e59816ecbd
Author: Stefan Metzmacher <metze at samba.org>
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 at 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 <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 7c344fbbe0568734beb982bb6e0f3c81e6eb5843
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Dec 15 11:37:33 2016 +0100

    auth/credentials: add python bindings for enum credentials_obtained
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 9fa7f59f88cb0350c0616d6f0a6a06b4e7a52228
Author: Stefan Metzmacher <metze at samba.org>
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 <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit df652c3ede181576f63ae20ccd993203b744952d
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Dec 15 10:06:25 2016 +0100

    auth/credentials: add py_creds_parse_file()
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 63dabd2f35224a7ee7468d435e67baa0e059358c
Author: Stefan Metzmacher <metze at samba.org>
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 <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit d29f7dc13bb705a0cab6de2aeac70c42d83a7af8
Author: Stefan Metzmacher <metze at samba.org>
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 <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 1565469bf22cb8aee7467ab76ba64fb5c54b59fe
Author: Stefan Metzmacher <metze at samba.org>
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 <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit a3f03df706f3dc8d7875226aa162154a0194f331
Author: Stefan Metzmacher <metze at samba.org>
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 <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 8415cca557cc556c0524cdf5ef66820d22577fb0
Author: Stefan Metzmacher <metze at samba.org>
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 <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 787cf39ce6cb6695b7eeee88e1dee32d33853884
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Wed Dec 14 11:58:48 2016 +1300

    s4-rpc_server: Add braces to better follow coding style
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit abbd0a88dee8715dbddc1a2478fe18aafefa385c
Author: Andrew Bartlett <abartlet at samba.org>
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 <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit 86e706a32dbd2259a428009f7097e7ea6c3f4f8d
Author: Andrew Bartlett <abartlet at samba.org>
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 <abartlet at samba.org>
    Reviewed-by: Garming Sam <garming at samba.org>

commit b81cf02834bdd5b0925949cc9d42897aa3054746
Author: Andrew Bartlett <abartlet at samba.org>
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 <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit 6dc14b0a5d225ca8752088a1ee25edee46c1f956
Author: Andrew Bartlett <abartlet at samba.org>
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 <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit ffb8b50e3c07c833fb7b1a583d21f9dc1166a0a6
Author: Andrew Bartlett <abartlet at samba.org>
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 <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit 5ea6708d819c392096413e53196d65108b1e9283
Author: Andrew Bartlett <abartlet at samba.org>
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 <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

-----------------------------------------------------------------------

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



More information about the samba-cvs mailing list