summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@samba.org>2007-12-24 14:16:40 -0600
committerStefan Metzmacher <metze@samba.org>2007-12-26 11:57:06 -0600
commit8ada900ee67fc8e1a1ff94c9e5f7a50752d11017 (patch)
tree430042a6eb3b786bfc94942c2f26284c41b223ab /source4
parenta6caca9abcf4de57901ba8ecc610cf8c13cd2821 (diff)
downloadsamba-8ada900ee67fc8e1a1ff94c9e5f7a50752d11017.tar.gz
samba-8ada900ee67fc8e1a1ff94c9e5f7a50752d11017.tar.bz2
samba-8ada900ee67fc8e1a1ff94c9e5f7a50752d11017.zip
r26590: Parsing routines for the smbpasswd file and idmap database.
(This used to be commit 0c14e16a2bc965d3319ca990089566bff98a47fe)
Diffstat (limited to 'source4')
-rw-r--r--source4/scripting/python/samba/samba3.py96
-rw-r--r--source4/scripting/python/samba/tests/samba3.py53
2 files changed, 140 insertions, 9 deletions
diff --git a/source4/scripting/python/samba/samba3.py b/source4/scripting/python/samba/samba3.py
index 509ee29c1d..b75b24ba34 100644
--- a/source4/scripting/python/samba/samba3.py
+++ b/source4/scripting/python/samba/samba3.py
@@ -108,16 +108,47 @@ class GroupMappingDatabase:
# High water mark keys
-HWM_GROUP = "GROUP HWM"
-HWM_USER = "USER HWM"
+IDMAP_HWM_GROUP = "GROUP HWM\0"
+IDMAP_HWM_USER = "USER HWM\0"
+
+IDMAP_GROUP_PREFIX = "GID "
+IDMAP_USER_PREFIX = "UID "
# idmap version determines auto-conversion
-IDMAP_VERSION = 2
+IDMAP_VERSION_V2 = 2
class IdmapDatabase:
def __init__(self, file):
self.tdb = tdb.Tdb(file, flags=os.O_RDONLY)
- assert self.tdb.fetch_int32("IDMAP_VERSION") == IDMAP_VERSION
+ assert self.tdb.fetch_int32("IDMAP_VERSION\0") == IDMAP_VERSION_V2
+
+ def uids(self):
+ for k in self.tdb.keys():
+ if k.startswith(IDMAP_USER_PREFIX):
+ yield int(k[len(IDMAP_USER_PREFIX):].rstrip("\0"))
+
+ def gids(self):
+ for k in self.tdb.keys():
+ if k.startswith(IDMAP_GROUP_PREFIX):
+ yield int(k[len(IDMAP_GROUP_PREFIX):].rstrip("\0"))
+
+ def get_user_sid(self, uid):
+ data = self.tdb.get("%s%d\0" % (IDMAP_USER_PREFIX, uid))
+ if data is None:
+ return data
+ return data.rstrip("\0")
+
+ def get_group_sid(self, gid):
+ data = self.tdb.get("%s%d\0" % (IDMAP_GROUP_PREFIX, gid))
+ if data is None:
+ return data
+ return data.rstrip("\0")
+
+ def get_user_hwm(self):
+ return self.tdb.fetch_uint32(IDMAP_HWM_USER)
+
+ def get_group_hwm(self):
+ return self.tdb.fetch_uint32(IDMAP_HWM_GROUP)
def close(self):
self.tdb.close()
@@ -181,6 +212,7 @@ class ShareInfoDatabase:
def get_secdesc(self, name):
secdesc = self.tdb.get("SECDESC/%s" % name)
# FIXME: Run ndr_pull_security_descriptor
+ return secdesc
def close(self):
self.tdb.close()
@@ -220,11 +252,65 @@ acb_info_mapping = {
' ': 0
}
+def decode_acb(text):
+ assert not "[" in text and not "]" in text
+ ret = 0
+ for x in text:
+ ret |= acb_info_mapping[x]
+ return ret
-class Smbpasswd:
+
+class SmbpasswdFile:
def __init__(self, file):
+ self.users = {}
+ f = open(file, 'r')
+ for l in f.readlines():
+ if len(l) == 0 or l[0] == "#":
+ continue # Skip comments and blank lines
+ parts = l.split(":")
+ username = parts[0]
+ uid = int(parts[1])
+ acct_ctrl = 0
+ last_change_time = None
+ if parts[2] == "NO PASSWORD":
+ acct_ctrl |= ACB_PWNOTREQ
+ lm_password = None
+ elif parts[2][0] in ("*", "X"):
+ # No password set
+ lm_password = None
+ else:
+ lm_password = parts[2]
+
+ if parts[3][0] in ("*", "X"):
+ # No password set
+ nt_password = None
+ else:
+ nt_password = parts[3]
+
+ if parts[4][0] == '[':
+ assert "]" in parts[4]
+ acct_ctrl |= decode_acb(parts[4][1:-1])
+ if parts[5].startswith("LCT-"):
+ last_change_time = int(parts[5][len("LCT-"):], 16)
+ else: # old style file
+ if username[-1] == "$":
+ acct_ctrl &= ~ACB_NORMAL
+ acct_ctrl |= ACB_WSTRUST
+
+ self.users[username] = (uid, lm_password, nt_password, acct_ctrl, last_change_time)
+
+ f.close()
+
+ def __len__(self):
+ return len(self.users)
+
+ def __getitem__(self, name):
+ return self.users[name]
+
+ def close(self): # For consistency
pass
+
TDBSAM_FORMAT_STRING_V0 = "ddddddBBBBBBBBBBBBddBBwdwdBwwd"
TDBSAM_FORMAT_STRING_V1 = "dddddddBBBBBBBBBBBBddBBwdwdBwwd"
TDBSAM_FORMAT_STRING_V2 = "dddddddBBBBBBBBBBBBddBBBwwdBwwd"
diff --git a/source4/scripting/python/samba/tests/samba3.py b/source4/scripting/python/samba/tests/samba3.py
index 92d11d11d4..580bcfa3c2 100644
--- a/source4/scripting/python/samba/tests/samba3.py
+++ b/source4/scripting/python/samba/tests/samba3.py
@@ -19,7 +19,7 @@
import unittest
from samba.samba3 import (GroupMappingDatabase, Registry, PolicyDatabase, SecretsDatabase, TdbSam,
- WinsDatabase)
+ WinsDatabase, SmbpasswdFile, ACB_NORMAL, IdmapDatabase)
import os
DATADIR=os.path.join(os.path.dirname(__file__), "../../../../../testdata/samba3")
@@ -109,6 +109,51 @@ class WinsDatabaseTestCase(unittest.TestCase):
def tearDown(self):
self.winsdb.close()
-# FIXME: smbpasswd
-# FIXME: idmapdb
-# FIXME: Shares
+class SmbpasswdTestCase(unittest.TestCase):
+ def setUp(self):
+ self.samdb = SmbpasswdFile(os.path.join(DATADIR, "smbpasswd"))
+
+ def test_length(self):
+ self.assertEquals(3, len(self.samdb))
+
+ def test_get_user(self):
+ self.assertEquals((0, "552902031BEDE9EFAAD3B435B51404EE", "878D8014606CDA29677A44EFA1353FC7", ACB_NORMAL, int(1125418267)), self.samdb["rootpw"])
+
+ def tearDown(self):
+ self.samdb.close()
+
+
+class IdmapDbTestCase(unittest.TestCase):
+ def setUp(self):
+ self.idmapdb = IdmapDatabase(os.path.join(DATADIR, "winbindd_idmap.tdb"))
+
+ def test_user_hwm(self):
+ self.assertEquals(10000, self.idmapdb.get_user_hwm())
+
+ def test_group_hwm(self):
+ self.assertEquals(10002, self.idmapdb.get_group_hwm())
+
+ def test_uids(self):
+ self.assertEquals(1, len(list(self.idmapdb.uids())))
+
+ def test_gids(self):
+ self.assertEquals(3, len(list(self.idmapdb.gids())))
+
+ def test_get_user_sid(self):
+ self.assertEquals("S-1-5-21-58189338-3053988021-627566699-501", self.idmapdb.get_user_sid(65534))
+
+ def test_get_group_sid(self):
+ self.assertEquals("S-1-5-21-2447931902-1787058256-3961074038-3007", self.idmapdb.get_group_sid(10001))
+
+ def tearDown(self):
+ self.idmapdb.close()
+
+
+class ShareInfoTestCase(unittest.TestCase):
+ def setUp(self):
+ self.shareinfodb = ShareInfoDatabase(os.path.join(DATADIR, "share_info.tdb"))
+
+ # FIXME: needs proper data so it can be tested
+
+ def tearDown(self):
+ self.shareinfodb.close()