auth/credentials: handle situations without a configured (default) realm
authorStefan Metzmacher <metze@samba.org>
Thu, 15 Dec 2016 10:04:02 +0000 (11:04 +0100)
committerAndrew Bartlett <abartlet@samba.org>
Tue, 20 Dec 2016 00:11:24 +0000 (01:11 +0100)
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 <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
auth/credentials/credentials.c
python/samba/tests/credentials.py

index e0244287ad5b5f68de78821136a820f566af6583..a0f91e92b732d1ff79c86ceb2f90d63987f0d0bc 100644 (file)
@@ -213,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;
@@ -816,6 +837,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")) {
@@ -828,10 +850,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);
index 0a64179d1022b7ff0e034701be1c37357d30a228..1cbd540eac9dbeb959db1077bb066160377487e4 100644 (file)
@@ -60,10 +60,12 @@ class CredentialsTests(samba.tests.TestCaseInTempDir):
     def test_set_domain(self):
         self.creds.set_domain("ABMAS")
         self.assertEqual("ABMAS", self.creds.get_domain())
+        self.assertEqual(self.creds.get_principal(), None)
 
     def test_set_realm(self):
         self.creds.set_realm("myrealm")
         self.assertEqual("MYREALM", self.creds.get_realm())
+        self.assertEqual(self.creds.get_principal(), None)
 
     def test_parse_string_anon(self):
         self.creds.parse_string("%")
@@ -140,7 +142,8 @@ class CredentialsTests(samba.tests.TestCaseInTempDir):
         creds.guess(lp)
         self.assertEqual(creds.get_username(), "env_user")
         self.assertEqual(creds.get_domain(), lp.get("workgroup").upper())
-        self.assertEqual(creds.get_realm(), lp.get("realm").upper())
+        self.assertEqual(creds.get_realm(), None)
+        self.assertEqual(creds.get_principal(), "env_user@%s" % creds.get_domain())
         self.assertEqual(creds.is_anonymous(), False)
         self.assertEqual(creds.authentication_requested(), False)
 
@@ -153,6 +156,7 @@ class CredentialsTests(samba.tests.TestCaseInTempDir):
         self.assertEqual(creds.get_username(), "")
         self.assertEqual(creds.get_domain(), "")
         self.assertEqual(creds.get_realm(), None)
+        self.assertEqual(creds.get_principal(), None)
         self.assertEqual(creds.is_anonymous(), True)
         self.assertEqual(creds.authentication_requested(), False)
 
@@ -186,7 +190,8 @@ class CredentialsTests(samba.tests.TestCaseInTempDir):
         creds.parse_string("user")
         self.assertEqual(creds.get_username(), "user")
         self.assertEqual(creds.get_domain(), lp.get("workgroup").upper())
-        self.assertEqual(creds.get_realm(), lp.get("realm").upper())
+        self.assertEqual(creds.get_realm(), None)
+        self.assertEqual(creds.get_principal(), "user@%s" % lp.get("workgroup").upper())
         self.assertEqual(creds.is_anonymous(), False)
         self.assertEqual(creds.authentication_requested(), True)
 
@@ -198,7 +203,8 @@ class CredentialsTests(samba.tests.TestCaseInTempDir):
         creds.parse_string("domain\user")
         self.assertEqual(creds.get_username(), "user")
         self.assertEqual(creds.get_domain(), "DOMAIN")
-        self.assertEqual(creds.get_realm(), lp.get("realm").upper())
+        self.assertEqual(creds.get_realm(), None)
+        self.assertEqual(creds.get_principal(), "user@DOMAIN")
         self.assertEqual(creds.is_anonymous(), False)
         self.assertEqual(creds.authentication_requested(), True)
 
@@ -211,6 +217,7 @@ class CredentialsTests(samba.tests.TestCaseInTempDir):
         self.assertEqual(creds.get_username(), "env_user")
         self.assertEqual(creds.get_domain(), lp.get("workgroup").upper())
         self.assertEqual(creds.get_realm(), "SAMBA.ORG")
+        self.assertEqual(creds.get_principal(), "user@samba.org")
         self.assertEqual(creds.is_anonymous(), False)
         self.assertEqual(creds.authentication_requested(), True)
 
@@ -223,7 +230,8 @@ class CredentialsTests(samba.tests.TestCaseInTempDir):
         self.assertEqual(creds.get_username(), "user")
         self.assertEqual(creds.get_password(), "pass")
         self.assertEqual(creds.get_domain(), lp.get("workgroup"))
-        self.assertEqual(creds.get_realm(), lp.get("realm"))
+        self.assertEqual(creds.get_realm(), None)
+        self.assertEqual(creds.get_principal(), "user@%s" % lp.get("workgroup"))
         self.assertEqual(creds.is_anonymous(), False)
         self.assertEqual(creds.authentication_requested(), True)
 
@@ -236,7 +244,8 @@ class CredentialsTests(samba.tests.TestCaseInTempDir):
         self.assertEqual(creds.get_username(), "user")
         self.assertEqual(creds.get_domain(), "DOMAIN")
         self.assertEqual(creds.get_password(), "pass")
-        self.assertEqual(creds.get_realm(), lp.get("realm"))
+        self.assertEqual(creds.get_realm(), None)
+        self.assertEqual(creds.get_principal(), "user@DOMAIN")
         self.assertEqual(creds.is_anonymous(), False)
         self.assertEqual(creds.authentication_requested(), True)