cracknames: Fix DoS (NULL pointer de-ref) when not servicePrincipalName is set on...
authorAndrew Bartlett <abartlet@samba.org>
Mon, 30 Jul 2018 02:00:18 +0000 (14:00 +1200)
committerKarolin Seeger <kseeger@samba.org>
Tue, 14 Aug 2018 15:02:38 +0000 (17:02 +0200)
This regression was introduced in Samba 4.7 by bug 12842 and in
master git commit eb2e77970e41c1cb62c041877565e939c78ff52d.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=13552

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Gary Lockyer <gary@catalyst.net.nz>
Autobuild-User(master): Karolin Seeger <kseeger@samba.org>
Autobuild-Date(master): Tue Aug 14 17:02:38 CEST 2018 on sn-devel-144

source4/dsdb/samdb/cracknames.c
source4/torture/drs/python/cracknames.py

index d8fe0975d1570e681cb0ce442e8da72109c55638..1f8cad75579582dc7abee1e1bce0b7a717e21f9b 100644 (file)
@@ -1253,7 +1253,13 @@ static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_
                return WERR_OK;
        }
        case DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL: {
-               if (result->elements[0].num_values > 1) {
+               struct ldb_message_element *el
+                       = ldb_msg_find_element(result,
+                                              "servicePrincipalName");
+               if (el == NULL) {
+                       info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
+                       return WERR_OK;
+               } else if (el->num_values > 1) {
                        info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE;
                        return WERR_OK;
                }
index d8c8ae53d60904b060722162c6f11a6151c5f710..9bf90f9c9973d67ef9ceee3bcf8b22e2724a8d62 100644 (file)
@@ -149,6 +149,44 @@ class DrsCracknamesTestCase(drs_base.DrsBaseTestCase):
 
         self.ldb_dc1.delete(user)
 
+    def test_NoSPNAttribute(self):
+        """
+        Verifies that, if we try and cracknames with the desired output
+        being an SPN, it returns
+        DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE.
+        """
+        username = "Cracknames_no_SPN"
+        user = "cn=%s,%s" % (username, self.ou)
+
+        user_record = {
+            "dn": user,
+            "objectclass": "user",
+            "sAMAccountName" : username,
+            "userPrincipalName" : "test4@test.com",
+            "displayName" : "test4"}
+
+        self.ldb_dc1.add(user_record)
+
+        (result, ctr) = self._do_cracknames(user,
+                                            drsuapi.DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
+                                            drsuapi.DRSUAPI_DS_NAME_FORMAT_GUID)
+
+        self.assertEquals(ctr.count, 1)
+        self.assertEquals(ctr.array[0].status,
+                          drsuapi.DRSUAPI_DS_NAME_STATUS_OK)
+
+        user_guid = ctr.array[0].result_name
+
+        (result, ctr) = self._do_cracknames(user_guid,
+                                            drsuapi.DRSUAPI_DS_NAME_FORMAT_GUID,
+                                            drsuapi.DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL)
+
+        self.assertEquals(ctr.count, 1)
+        self.assertEquals(ctr.array[0].status,
+                          drsuapi.DRSUAPI_DS_NAME_STATUS_NOT_FOUND)
+
+        self.ldb_dc1.delete(user)
+
     def _do_cracknames(self, name, format_offered, format_desired):
         req = drsuapi.DsNameRequest1()
         names = drsuapi.DsNameString()