r3590: Add some more commands to rpcclient from a patch by jbm. Add
[samba.git] / source4 / scripting / swig / samr.py
1 import dcerpc
2
3 def sid_to_string(sid):
4     """Convert a Python dictionary SID to a string SID."""
5
6     result = 'S-%d' % sid['sid_rev_num']
7
8     ia = sid['id_auth']
9     
10     result = result + '-%u' % (ia[5] + (ia[4] << 8) + (ia[3] << 16) + \
11              (ia[2] << 24))
12     
13     for i in range(0, sid['num_auths']):
14         result = result + '-%u' % sid['sub_auths'][i]
15
16     return result
17
18 def string_to_sid(string):
19     """Convert a string SID to a Python dictionary SID.  Throws a
20     ValueError if the SID string was badly formed."""
21
22     if string[0] != 'S':
23         raise ValueError('Bad SID format')
24
25     string = string[1:]
26
27     import re
28
29     match = re.match('-\d+', string)
30
31     if not match:
32         raise ValueError('Bad SID format')
33
34     try:
35         sid_rev_num = int(string[match.start()+1:match.end()])
36     except ValueError:
37         raise ValueError('Bad SID format')
38
39     string = string[match.end():]
40
41     match = re.match('-\d+', string)
42
43     if not match:
44         raise ValueError('Bad SID format')
45
46     try:
47         ia = int(string[match.start()+1:match.end()])
48     except ValueError:
49         raise ValueError('Bad SID format')
50
51     string = string[match.end():]
52
53     id_auth = [0, 0, (ia >> 24) & 0xff, (ia >> 16) & 0xff,
54                (ia >> 8) & 0xff, ia & 0xff]
55
56     num_auths = 0
57     sub_auths = []
58     
59     while len(string):
60
61         match = re.match('-\d+', string)
62
63         if not match:
64             raise ValueError('Bad SID format')
65
66         try:
67             sa = int(string[match.start() + 1 : match.end()])
68         except ValueError:
69             raise ValueError('Bad SID format')
70
71         num_auths = num_auths + 1
72         sub_auths.append(int(sa))
73
74         string = string[match.end():]
75     
76     return {'sid_rev_num': sid_rev_num, 'id_auth': id_auth,
77             'num_auths': num_auths, 'sub_auths': sub_auths}
78
79
80 class SamrHandle:
81
82     def __init__(self, pipe, handle):
83
84         self.pipe = pipe
85         self.handle = handle
86
87     def __del__(self):
88
89         r = {}
90         r['handle'] = self.handle
91
92         dcerpc.samr_Close(self.pipe, r)
93
94
95 class ConnectHandle(SamrHandle):
96
97     def EnumDomains(self):
98
99         r = {}
100         r['connect_handle'] = self.handle
101         r['resume_handle'] = 0
102         r['buf_size'] = -1
103
104         domains = []
105
106         while 1:
107
108             result = dcerpc.samr_EnumDomains(self.pipe, r)
109
110             domains = domains + result['sam']['entries']
111
112             if result['result'] == dcerpc.STATUS_MORE_ENTRIES:
113                 r['resume_handle'] = result['resume_handle']
114                 continue
115
116             break
117
118         return map(lambda x: x['name']['name'], domains)
119
120     def LookupDomain(self, domain_name):
121
122         r = {}
123         r['connect_handle'] = self.handle
124         r['domain'] = {}
125         r['domain']['name_len'] = 0
126         r['domain']['name_size'] = 0
127         r['domain']['name'] = domain_name
128
129         result = dcerpc.samr_LookupDomain(self.pipe, r)
130
131         return sid_to_string(result['sid'])
132
133     def OpenDomain(self, domain_sid, access_mask = 0x02000000):
134
135         r = {}
136         r['connect_handle'] = self.handle
137         r['access_mask'] = access_mask
138         r['sid'] = string_to_sid(domain_sid)
139
140         result = dcerpc.samr_OpenDomain(self.pipe, r)
141
142         return DomainHandle(self.pipe, result['domain_handle'])
143
144
145 class DomainHandle(SamrHandle):
146
147     def QueryDomainInfo(self, level = 2):
148
149         r = {}
150         r['domain_handle'] = self.handle
151         r['level'] = level
152
153         result = dcerpc.samr_QueryDomainInfo(self.pipe, r)
154
155         return result
156
157     def QueryDomainInfo2(self, level = 2):
158
159         r = {}
160         r['domain_handle'] = self.handle
161         r['level'] = level
162
163         result = dcerpc.samr_QueryDomainInfo2(self.pipe, r)
164
165         return result
166
167     def EnumDomainGroups(self):
168
169         r = {}
170         r['domain_handle'] = self.handle
171         r['resume_handle'] = 0
172         r['max_size'] = 1000
173
174         result = dcerpc.samr_EnumDomainGroups(self.pipe, r)
175
176         return result
177
178     def EnumDomainAliases(self):
179
180         r = {}
181         r['domain_handle'] = self.handle
182         r['resume_handle'] = 0
183         # acct_flags in SamrEnumerateAliasesInDomain has probably
184         # no meaning so use 0xffffffff like W2K
185         r['acct_flags'] = 0xffffffff
186         r['max_size'] = 1000
187
188         result = dcerpc.samr_EnumDomainAliases(self.pipe, r)
189
190         return result
191
192     def EnumDomainUsers(self, user_account_flags = 16):
193
194         r = {}
195         r['domain_handle'] = self.handle
196         r['resume_handle'] = 0
197         r['acct_flags'] = user_account_flags
198         r['max_size'] = 1000
199
200         result = dcerpc.samr_EnumDomainUsers(self.pipe, r)
201
202         return result
203
204
205 def Connect(pipe, system_name = None, access_mask = 0x02000000):
206     """Connect to the SAMR pipe."""
207
208     r = {}
209     r['system_name'] = system_name
210     r['access_mask'] = access_mask
211
212     result = dcerpc.samr_Connect2(pipe, r)
213
214     return ConnectHandle(pipe, result['connect_handle'])