auth/credentials: let cli_credentials_parse_string() always reset principal and realm
authorStefan Metzmacher <metze@samba.org>
Wed, 14 Dec 2016 15:47:57 +0000 (16:47 +0100)
committerAndrew Bartlett <abartlet@samba.org>
Tue, 20 Dec 2016 00:11:24 +0000 (01:11 +0100)
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@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
auth/credentials/credentials.c

index cca772d9f41c1acccd6b64b680731acf4d8984a7..14c84034ac6e39e6ff62fc5374da71eaa78d6092 100644 (file)
@@ -797,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);
 }