r6469: Add CreateDomainGroup, GetAliasMembership.
[samba.git] / source / 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     result = result + '-%u' % \
9              (dcerpc.uint8_array_getitem(sid.id_auth, 5) +
10               (dcerpc.uint8_array_getitem(sid.id_auth, 4) << 8) + 
11               (dcerpc.uint8_array_getitem(sid.id_auth, 3) << 16) +
12               (dcerpc.uint8_array_getitem(sid.id_auth, 2) << 24))
13     
14     for i in range(0, sid.num_auths):
15         result = result + '-%u' % \
16                  dcerpc.uint32_array_getitem(sid.sub_auths, i)
17
18     return result
19
20
21 def string_to_sid(string):
22     """Convert a string SID to a Python dictionary SID.  Throws a
23     ValueError if the SID string was badly formed."""
24
25     if string[0] != 'S':
26         raise ValueError('Bad SID format')
27
28     string = string[1:]
29
30     import re
31
32     match = re.match('-\d+', string)
33
34     if not match:
35         raise ValueError('Bad SID format')
36
37     try:
38         sid_rev_num = int(string[match.start()+1:match.end()])
39     except ValueError:
40         raise ValueError('Bad SID format')
41
42     string = string[match.end():]
43
44     match = re.match('-\d+', string)
45
46     if not match:
47         raise ValueError('Bad SID format')
48
49     try:
50         ia = int(string[match.start()+1:match.end()])
51     except ValueError:
52         raise ValueError('Bad SID format')
53
54     string = string[match.end():]
55
56     id_auth = [0, 0, (ia >> 24) & 0xff, (ia >> 16) & 0xff,
57                (ia >> 8) & 0xff, ia & 0xff]
58
59     num_auths = 0
60     sub_auths = []
61     
62     while len(string):
63
64         match = re.match('-\d+', string)
65
66         if not match:
67             raise ValueError('Bad SID format')
68
69         try:
70             sa = int(string[match.start() + 1 : match.end()])
71         except ValueError:
72             raise ValueError('Bad SID format')
73
74         num_auths = num_auths + 1
75         sub_auths.append(int(sa))
76
77         string = string[match.end():]
78
79     sid = dcerpc.dom_sid()
80     sid.sid_rev_num = sid_rev_num
81     sid.id_auth = dcerpc.new_uint8_array(6)
82     for i in range(6):
83         dcerpc.uint8_array_setitem(sid.id_auth, i, id_auth[i])
84     sid.num_auths = num_auths
85     sid.sub_auths = dcerpc.new_uint32_array(num_auths)
86     for i in range(num_auths):
87         dcerpc.uint32_array_setitem(sid.sub_auths, i, sub_auths[i])
88
89     return sid
90
91
92 def call_fn(fn, pipe, args):
93     """Wrap up a RPC call and throw an exception is an error was returned."""
94     
95     result = fn(pipe, args);
96
97     if result & 0xc0000000L:
98         raise dcerpc.NTSTATUS(result, dcerpc.nt_errstr(result));
99
100     return result;
101
102     
103 class SamrHandle:
104
105     def __init__(self, pipe, handle):
106
107         self.pipe = pipe
108         self.handle = handle
109
110     def __del__(self):
111
112         if self.handle is not None:
113             self.Close()
114
115     def Close(self):
116                     
117         r = dcerpc.samr_Close()
118         r.data_in.handle = self.handle
119
120         call_fn(dcerpc.dcerpc_samr_Close, self.pipe, r)
121
122         self.handle = None
123
124     def QuerySecurity(self, sec_info = 7):
125
126         r = dcerpc.samr_QuerySecurity()
127         r.data_in.handle = self.handle
128         r.data_in.sec_info = sec_info
129
130         call_fn(dcerpc.dcerpc_samr_QuerySecurity, self.pipe, r)
131
132         return r.data_out.sdbuf
133
134     def SetSecurity(self, sdbuf, sec_info = 7):
135
136         r = dcerpc.samr_SetSecurity()
137         r.data_in.handle = self.handle
138         r.data_in.sec_info = sec_info
139         r.data_in.sdbuf = sdbuf
140
141         call_fn(dcerpc.dcerpc_samr_SetSecurity, self.pipe, r)
142
143         
144 class ConnectHandle(SamrHandle):
145
146     def EnumDomains(self):
147
148         r = dcerpc.samr_EnumDomains()
149         r.data_in.connect_handle = self.handle
150         r.data_in.resume_handle = 0
151         r.data_in.buf_size = -1
152
153         domains = []
154
155         while 1:
156
157             call_fn(dcerpc.dcerpc_samr_EnumDomains, self.pipe, r)
158
159             for i in range(r.data_out.sam.count):
160                 domains.append(dcerpc.samr_SamEntry_array_getitem(
161                     r.data_out.sam.entries, i).name.string)
162
163             # TODO: Handle more entries here
164
165             break
166
167         return domains
168
169     def LookupDomain(self, domain_name):
170
171         r = dcerpc.samr_LookupDomain()
172         r.data_in.connect_handle = self.handle
173         r.data_in.domain_name = dcerpc.samr_String()
174         r.data_in.domain_name.string = domain_name
175
176         call_fn(dcerpc.dcerpc_samr_LookupDomain, self.pipe, r)
177
178         return sid_to_string(r.data_out.sid);
179
180     def OpenDomain(self, domain_sid, access_mask = 0x02000000):
181
182         r = dcerpc.samr_OpenDomain()
183         r.data_in.connect_handle = self.handle
184         r.data_in.access_mask = access_mask
185         r.data_in.sid = string_to_sid(domain_sid)
186
187         call_fn(dcerpc.dcerpc_samr_OpenDomain, self.pipe, r)
188
189         return DomainHandle(self.pipe, r.data_out.domain_handle)
190
191     def Shutdown(self):
192
193         r = dcerpc.samr_Shutdown()
194         r.data_in.connect_handle = self.handle
195
196         call_fn(dcerpc.dcerpc_samr_Shutdown, self.pipe, r)
197
198     def GetDomPwInfo(self, system_name):
199
200         r = dcerpc.samr_GetDomPwInfo()
201         r.data_in.domain_name = dcerpc.samr_String()
202         r.data_in.domain_name.string = system_name
203
204         call_fn(dcerpc.dcerpc_samr_GetDomPwInfo, self.pipe, r)
205
206         return r.data_out.info
207
208
209 class DomainHandle(SamrHandle):
210
211     def QueryDomainInfo(self, level = 2):
212
213         r = dcerpc.samr_QueryDomainInfo()
214         r.data_in.domain_handle = self.handle
215         r.data_in.level = level
216
217         call_fn(dcerpc.dcerpc_samr_QueryDomainInfo, self.pipe, r)
218
219         return getattr(r.data_out.info, 'info%d' % level)
220
221     def QueryDomainInfo2(self, level = 2):
222
223         r = dcerpc.samr_QueryDomainInfo2()
224         r.data_in.domain_handle = self.handle
225         r.data_in.level = level
226
227         call_fn(dcerpc.dcerpc_samr_QueryDomainInfo2, self.pipe, r)
228
229         return getattr(r.data_out.info, 'info%d' % level)       
230
231     def EnumDomainGroups(self):
232
233         r = dcerpc.samr_EnumDomainGroups()
234         r.data_in.domain_handle = self.handle
235         r.data_in.resume_handle = 0
236         r.data_in.max_size = 1000
237
238         call_fn(dcerpc.dcerpc_samr_EnumDomainGroups, self.pipe, r)
239
240         groups = []
241
242         if r.data_out.sam.entries:
243             for i in range(r.data_out.sam.count):
244                 groups.append(dcerpc.samr_SamEntry_array_getitem(
245                     r.data_out.sam.entries, i).name.string)
246
247         return groups
248
249     def EnumDomainAliases(self):
250
251         r = dcerpc.samr_EnumDomainAliases()
252         r.data_in.domain_handle = self.handle
253         r.data_in.resume_handle = 0
254         # acct_flags in SamrEnumerateAliasesInDomain has probably
255         # no meaning so use 0xffffffff like W2K
256         r.data_in.acct_flags = 0xffffffffL
257
258         call_fn(dcerpc.dcerpc_samr_EnumDomainAliases, self.pipe, r)
259
260         aliases = []
261
262         if r.data_out.sam.entries:
263             for i in range(r.data_out.sam.count):
264                 aliases.append(dcerpc.samr_SamEntry_array_getitem(
265                     r.data_out.sam.entries, i).name.string)
266
267         return aliases
268
269     def EnumDomainUsers(self, user_account_flags = 16):
270
271         r = dcerpc.samr_EnumDomainUsers()
272         r.data_in.domain_handle = self.handle
273         r.data_in.resume_handle = 0
274         r.data_in.acct_flags = user_account_flags
275         r.data_in.max_size = 1000
276
277         call_fn(dcerpc.dcerpc_samr_EnumDomainUsers, self.pipe, r)
278
279         users = []
280
281         if r.data_out.sam.entries:
282             for i in range(r.data_out.sam.count):
283                 users.append(dcerpc.samr_SamEntry_array_getitem(
284                     r.data_out.sam.entries, i).name.string)
285
286         return users
287
288     def CreateUser(self, account_name, access_mask = 0x02000000):
289
290         r = dcerpc.samr_CreateUser()
291         r.data_in.domain_handle = self.handle
292         r.data_in.account_name = dcerpc.samr_String()
293         r.data_in.account_name.string = account_name
294         r.data_in.access_mask = access_mask
295
296         call_fn(dcerpc.dcerpc_samr_CreateUser, self.pipe, r)
297
298         return (r.data_out.user_handle,
299                 dcerpc.uint32_array_getitem(r.data_out.rid, 0))
300
301     def CreateUser2(self, account_name, acct_flags = 0x00000010,
302                     access_mask = 0x02000000):
303
304         r = dcerpc.samr_CreateUser2()
305         r.data_in.domain_handle = self.handle
306         r.data_in.account_name = dcerpc.samr_String()
307         r.data_in.account_name.string = account_name
308         r.data_in.acct_flags = acct_flags
309         r.data_in.access_mask = access_mask
310
311         call_fn(dcerpc.dcerpc_samr_CreateUser2, self.pipe, r)
312
313         return (r.data_out.user_handle,
314                 dcerpc.uint32_array_getitem(r.data_out.access_granted, 0),
315                 dcerpc.uint32_array_getitem(r.data_out.rid, 0))
316
317     def OpenUser(self, rid, access_mask = 0x02000000):
318
319         r = dcerpc.samr_OpenUser()
320         r.data_in.domain_handle = self.handle
321         r.data_in.access_mask = access_mask
322         r.data_in.rid = rid
323
324         call_fn(dcerpc.dcerpc_samr_OpenUser, self.pipe, r)
325
326         return UserHandle(self.pipe, r.data_out.user_handle)
327
328     def OpenGroup(self, rid, access_mask = 0x02000000):
329
330         r = dcerpc.samr_OpenGroup()
331         r.data_in.domain_handle = self.handle
332         r.data_in.access_mask = access_mask
333         r.data_in.rid = rid
334
335         call_fn(dcerpc.dcerpc_samr_OpenGroup, self.pipe, r)
336
337         return GroupHandle(pipe, r.data_out.group_handle)
338
339     def OpenAlias(self, rid, access_mask = 0x02000000):
340
341         r = dcerpc.samr_OpenAlias()
342         r.data_in.domain_handle = self.handle
343         r.data_in.access_mask = access_mask
344         r.data_in.rid = rid
345
346         call_fn(dcerpc.dcerpc_samr_OpenAlias, self.pipe, r)
347
348         return AliasHandle(self.pipe, r.data_out.alias_handle)
349
350     def CreateDomAlias(self, alias_name, access_mask = 0x02000000):
351
352         r = dcerpc.samr_CreateDomAlias()
353         r.data_in.domain_handle = self.handle
354         r.data_in.alias_name = dcerpc.samr_String()
355         r.data_in.alias_name.string = alias_name
356         r.data_in.access_mask = access_mask
357
358         call_fn(dcerpc.dcerpc_samr_CreateDomAlias, self.pipe, r)
359
360         return (AliasHandle(self.pipe, r.data_out.alias_handle),
361                 r.data_out.rid)    
362
363     def RidToSid(self, rid):
364
365         r = dcerpc.samr_RidToSid()
366         r.data_in.domain_handle = self.handle
367
368         call_fn(dcerpc.dcerpc_samr_RidToSid, self.pipe, r)
369
370         return sid_to_string(r.data_out.sid)
371
372     def RemoveMemberFromForeignDomain(self, sid):
373
374         r = dcerpc.samr_RemoveMemberFromForeignDomain()
375         r.data_in.domain_handle = self.handle
376         r.data_in.sid = sid
377
378         call_fn(dcerpc.dcerpc_samr_RemoveMemberFromForeignDomain, self.pipe, r)
379
380     def LookupNames(self, names):
381
382         r = dcerpc.samr_LookupNames()
383         r.data_in.domain_handle = self.handle
384         r.data_in.num_names = len(names)
385         r.data_in.names = dcerpc.new_samr_String_array(len(names))
386
387         for i in range(len(names)):
388             s = dcerpc.samr_String()
389             s.string = names[i]
390             dcerpc.samr_String_array_setitem(r.data_in.names, i, s)
391
392         call_fn(dcerpc.dcerpc_samr_LookupNames, self.pipe, r)
393
394         return ([dcerpc.uint32_array_getitem(r.data_out.rids.ids, i) for i in range(r.data_out.rids.count)],
395                 [dcerpc.uint32_array_getitem(r.data_out.types.ids, i) for i in range(r.data_out.types.count)])
396
397     def CreateDomainGroup(self, domain_name, access_mask = 0x02000000):
398
399         r = dcerpc.samr_CreateDomainGroup()
400         r.data_in.domain_handle = self.handle
401         r.data_in.name = dcerpc.samr_String()
402         r.data_in.name.string = domain_name
403         r.data_in.access_mask = access_mask
404
405         call_fn(dcerpc.dcerpc_samr_CreateDomainGroup, self.pipe, r)
406
407     def GetAliasMembership(self, sids):
408
409         r = dcerpc.samr_GetAliasMembership()
410         r.data_in.domain_handle = self.handle
411         r.data_in.sids = dcerpc.lsa_SidArray()
412         r.data_in.sids.num_sids = len(sids)
413         r.data_in.sids.sids = dcerpc.new_lsa_SidPtr_array(len(sids))
414
415         for i in range(len(sids)):
416             s = dcerpc.lsa_SidPtr()
417             s.sid = string_to_sid(sids[i])
418             dcerpc.lsa_SidPtr_array_setitem(r.data_in.sids.sids, i, s)
419
420         call_fn(dcerpc.dcerpc_samr_GetAliasMembership, self.pipe, r)
421
422         return [r.ids[x] x in range(r.count)]
423
424 class UserHandle(SamrHandle):
425
426     def DeleteUser(self):
427
428         r = dcerpc.samr_DeleteUser()
429         r.data_in.user_handle = self.handle
430         
431         call_fn(dcerpc.dcerpc_samr_DeleteUser, self.pipe, r)
432
433         self.handle = None
434     
435
436 class GroupHandle(SamrHandle):
437     pass
438     
439
440 class AliasHandle(SamrHandle):
441
442     def DeleteDomAlias(self):
443
444         r = dcerpc.samr_DeleteDomAlias()
445         r.data_in.alias_handle = self.handle
446
447         call_fn(dcerpc.dcerpc_samr_DeleteDomAlias, self.pipe, r)
448
449         self.handle = None
450
451     def QueryAliasInfo(self, level = 1):
452
453         r = dcerpc.samr_QueryAliasInfo()
454         r.data_in.alias_handle = self.handle
455         r.data_in.level = level
456
457         call_fn(dcerpc.dcerpc_samr_QueryAliasInfo, self.pipe, r)
458
459         return r.data_out.info
460
461     def SetAliasInfo(self, level, info):
462
463         r = dcerpc.samr_SetAliasInfo()
464         r.data_in.alias_handle = self.handle
465         r.data_in.level = level
466         r.data_in.info = info
467
468         call_fn(dcerpc.dcerpc_samr_SetAliasInfo, self.pipe, r)
469
470     def AddAliasMember(self, sid):
471
472         r = dcerpc.samr_AddAliasMember()
473         r.data_in.alias_handle = self.handle
474         r.data_in.sid = string_to_sid(sid)
475
476         call_fn(dcerpc.dcerpc_samr_AddAliasMember, self.pipe, r)
477
478     def AddMultipleMembersToAlias(self, sids):
479
480         r = dcerpc.samr_AddMultipleMembersToAlias()
481         r.data_in.alias_handle = self.handle
482         r.data_in.sids = dcerpc.lsa_SidArray()
483         r.data_in.sids.num_sids = len(sids)
484         r.data_in.sids.sids = dcerpc.new_lsa_SidPtr_array(len(sids))
485
486         for i in range(len(sids)):
487             s = dcerpc.lsa_SidPtr()
488             s.sid = string_to_sid(sids[i])
489             dcerpc.lsa_SidPtr_array_setitem(r.data_in.sids.sids, i, s)
490
491         call_fn(dcerpc.dcerpc_samr_AddMultipleMembersToAlias, self.pipe, r)
492
493 def Connect(pipe, access_mask = 0x02000000):
494
495     r = dcerpc.samr_Connect()
496     r.data_in.system_name = dcerpc.new_uint16_array(1)
497     dcerpc.uint16_array_setitem(r.data_in.system_name, 0, ord('\\'))
498     r.data_in.access_mask = access_mask
499
500     call_fn(dcerpc.dcerpc_samr_Connect, pipe, r)
501
502     return ConnectHandle(pipe, r.data_out.connect_handle)
503
504
505 def Connect2(pipe, system_name = '', access_mask = 0x02000000):
506     """Connect to the SAMR pipe."""
507
508     r = dcerpc.samr_Connect2()
509     r.data_in.system_name = system_name
510     r.data_in.access_mask = access_mask
511
512     call_fn(dcerpc.dcerpc_samr_Connect2, pipe, r)
513
514     return ConnectHandle(pipe, r.data_out.connect_handle)
515
516
517 def Connect3(pipe, system_name = '', access_mask = 0x02000000):
518
519     r = dcerpc.samr_Connect3()
520     r.data_in.system_name = system_name
521     r.data_in.unknown = 0
522     r.data_in.access_mask = access_mask
523
524     call_fn(dcerpc.dcerpc_samr_Connect3, pipe, r)
525
526     return ConnectHandle(pipe, r.data_out.connect_handle)
527
528
529 def Connect4(pipe, system_name = '', access_mask = 0x02000000):
530
531     r = dcerpc.samr_Connect4()
532     r.data_in.system_name = system_name
533     r.data_in.unknown = 0
534     r.data_in.access_mask = access_mask
535
536     call_fn(dcerpc.dcerpc_samr_Connect4, pipe, r)
537
538     return ConnectHandle(pipe, r.data_out.connect_handle)
539
540
541 def Connect5(pipe, system_name = '', access_mask = 0x02000000):
542
543     r = dcerpc.samr_Connect5()
544     r.data_in.system_name = system_name
545     r.data_in.access_mask = access_mask
546     r.data_in.level = 1
547     r.data_in.info = dcerpc.new_samr_ConnectInfo_array(1)
548     r.data_in.info.unknown1 = 0
549     r.data_in.info.unknown2 = 0
550
551     call_fn(dcerpc.dcerpc_samr_Connect5, pipe, r)
552
553     return ConnectHandle(pipe, r.data_out.connect_handle)
554     
555 # QueryGroupInfo
556 # SetGroupInfo
557 # AddGroupMember
558 # DeleteDomainGroup
559 # DeleteGroupMember
560 # QueryGroupMember
561 # SetMemberAttributesofGroup
562 # AddAliasMember
563 # DeleteAliasMember
564 # GetMembersinAlias
565 # QueryUserInfo
566 # SetUserInfo
567 # ChangePasswordUser
568 # GetGroupsForUser
569 # QueryDisplayInfo
570 # GetDisplayEnumerationIndex
571 # TestPrivateFunctionsDomain
572 # TestPrivateFunctionsUser
573 # GetUserPwInfo
574 # RemoveMemberFromForeignDomain
575 # QueryDomainInfo2
576 # QueryUserInfo2
577 # QueryDisplayInfo2
578 # GetDisplayEnumerationIndex2
579 # QueryDisplayInfo3
580 # RemoveMultipleMembersFromAlias
581 # OemChangePasswordUser2
582 # ChangePasswordUser2
583 # SetUserInfo2
584 # SetBootKeyInformation
585 # GetBootKeyInformation
586 # ChangePasswordUser3
587 # SetDsrmPassword
588 # ValidatePassword