4796d748eb23f589c4d13650cc3719322d81aec2
[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, domain_name):
199
200         r = dcerpc.samr_GetDomPwInfo()
201         r.data_in.domain_name = dcerpc.samr_String()
202         r.data_in.domain_name.string = domain_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 SetDomainInfo(self, level, info):
232
233         r = dcerpc.samr_SetDomainInfo()
234         r.data_in.domain_handle = self.handle
235         r.data_in.level = level
236         r.data_in.info = dcerpc.samr_DomainInfo()
237         setattr(r.data_in.info, 'info%d' % level, info)
238
239         call_fn(dcerpc.dcerpc_samr_SetDomainInfo, self.pipe, r)
240
241     def EnumDomainGroups(self):
242
243         r = dcerpc.samr_EnumDomainGroups()
244         r.data_in.domain_handle = self.handle
245         r.data_in.resume_handle = 0
246         r.data_in.max_size = 1000
247
248         call_fn(dcerpc.dcerpc_samr_EnumDomainGroups, self.pipe, r)
249
250         groups = []
251
252         if r.data_out.sam.entries:
253             for i in range(r.data_out.sam.count):
254                 groups.append(dcerpc.samr_SamEntry_array_getitem(
255                     r.data_out.sam.entries, i).name.string)
256
257         return groups
258
259     def EnumDomainAliases(self):
260
261         r = dcerpc.samr_EnumDomainAliases()
262         r.data_in.domain_handle = self.handle
263         r.data_in.resume_handle = 0
264         # acct_flags in SamrEnumerateAliasesInDomain has probably
265         # no meaning so use 0xffffffff like W2K
266         r.data_in.acct_flags = 0xffffffffL
267
268         call_fn(dcerpc.dcerpc_samr_EnumDomainAliases, self.pipe, r)
269
270         aliases = []
271
272         if r.data_out.sam.entries:
273             for i in range(r.data_out.sam.count):
274                 aliases.append(dcerpc.samr_SamEntry_array_getitem(
275                     r.data_out.sam.entries, i).name.string)
276
277         return aliases
278
279     def EnumDomainUsers(self, user_account_flags = 16):
280
281         r = dcerpc.samr_EnumDomainUsers()
282         r.data_in.domain_handle = self.handle
283         r.data_in.resume_handle = 0
284         r.data_in.acct_flags = user_account_flags
285         r.data_in.max_size = 1000
286
287         call_fn(dcerpc.dcerpc_samr_EnumDomainUsers, self.pipe, r)
288
289         users = []
290
291         if r.data_out.sam.entries:
292             for i in range(r.data_out.sam.count):
293                 users.append(dcerpc.samr_SamEntry_array_getitem(
294                     r.data_out.sam.entries, i).name.string)
295
296         return users
297
298     def CreateUser(self, account_name, access_mask = 0x02000000):
299
300         r = dcerpc.samr_CreateUser()
301         r.data_in.domain_handle = self.handle
302         r.data_in.account_name = dcerpc.samr_String()
303         r.data_in.account_name.string = account_name
304         r.data_in.access_mask = access_mask
305
306         call_fn(dcerpc.dcerpc_samr_CreateUser, self.pipe, r)
307
308         return (r.data_out.user_handle,
309                 dcerpc.uint32_array_getitem(r.data_out.rid, 0))
310
311     def CreateUser2(self, account_name, acct_flags = 0x00000010,
312                     access_mask = 0x02000000):
313
314         r = dcerpc.samr_CreateUser2()
315         r.data_in.domain_handle = self.handle
316         r.data_in.account_name = dcerpc.samr_String()
317         r.data_in.account_name.string = account_name
318         r.data_in.acct_flags = acct_flags
319         r.data_in.access_mask = access_mask
320
321         call_fn(dcerpc.dcerpc_samr_CreateUser2, self.pipe, r)
322
323         return (r.data_out.user_handle,
324                 dcerpc.uint32_array_getitem(r.data_out.access_granted, 0),
325                 dcerpc.uint32_array_getitem(r.data_out.rid, 0))
326
327     def OpenUser(self, rid, access_mask = 0x02000000):
328
329         r = dcerpc.samr_OpenUser()
330         r.data_in.domain_handle = self.handle
331         r.data_in.access_mask = access_mask
332         r.data_in.rid = rid
333
334         call_fn(dcerpc.dcerpc_samr_OpenUser, self.pipe, r)
335
336         return UserHandle(self.pipe, r.data_out.user_handle)
337
338     def OpenGroup(self, rid, access_mask = 0x02000000):
339
340         r = dcerpc.samr_OpenGroup()
341         r.data_in.domain_handle = self.handle
342         r.data_in.access_mask = access_mask
343         r.data_in.rid = rid
344
345         call_fn(dcerpc.dcerpc_samr_OpenGroup, self.pipe, r)
346
347         return GroupHandle(self.pipe, r.data_out.group_handle)
348
349     def OpenAlias(self, rid, access_mask = 0x02000000):
350
351         r = dcerpc.samr_OpenAlias()
352         r.data_in.domain_handle = self.handle
353         r.data_in.access_mask = access_mask
354         r.data_in.rid = rid
355
356         call_fn(dcerpc.dcerpc_samr_OpenAlias, self.pipe, r)
357
358         return AliasHandle(self.pipe, r.data_out.alias_handle)
359
360     def CreateDomAlias(self, alias_name, access_mask = 0x02000000):
361
362         r = dcerpc.samr_CreateDomAlias()
363         r.data_in.domain_handle = self.handle
364         r.data_in.alias_name = dcerpc.samr_String()
365         r.data_in.alias_name.string = alias_name
366         r.data_in.access_mask = access_mask
367
368         call_fn(dcerpc.dcerpc_samr_CreateDomAlias, self.pipe, r)
369
370         return (AliasHandle(self.pipe, r.data_out.alias_handle),
371                 r.data_out.rid)    
372
373     def RidToSid(self, rid):
374
375         r = dcerpc.samr_RidToSid()
376         r.data_in.domain_handle = self.handle
377
378         call_fn(dcerpc.dcerpc_samr_RidToSid, self.pipe, r)
379
380         return sid_to_string(r.data_out.sid)
381
382     def RemoveMemberFromForeignDomain(self, sid):
383
384         r = dcerpc.samr_RemoveMemberFromForeignDomain()
385         r.data_in.domain_handle = self.handle
386         r.data_in.sid = sid
387
388         call_fn(dcerpc.dcerpc_samr_RemoveMemberFromForeignDomain, self.pipe, r)
389
390     def LookupNames(self, names):
391
392         r = dcerpc.samr_LookupNames()
393         r.data_in.domain_handle = self.handle
394         r.data_in.num_names = len(names)
395         r.data_in.names = dcerpc.new_samr_String_array(len(names))
396
397         for i in range(len(names)):
398             s = dcerpc.samr_String()
399             s.string = names[i]
400             dcerpc.samr_String_array_setitem(r.data_in.names, i, s)
401
402         call_fn(dcerpc.dcerpc_samr_LookupNames, self.pipe, r)
403
404         return ([dcerpc.uint32_array_getitem(r.data_out.rids.ids, i) for i in range(r.data_out.rids.count)],
405                 [dcerpc.uint32_array_getitem(r.data_out.types.ids, i) for i in range(r.data_out.types.count)])
406
407     def CreateDomainGroup(self, domain_name, access_mask = 0x02000000):
408
409         r = dcerpc.samr_CreateDomainGroup()
410         r.data_in.domain_handle = self.handle
411         r.data_in.name = dcerpc.samr_String()
412         r.data_in.name.string = domain_name
413         r.data_in.access_mask = access_mask
414
415         call_fn(dcerpc.dcerpc_samr_CreateDomainGroup, self.pipe, r)
416
417     def GetAliasMembership(self, sids):
418
419         r = dcerpc.samr_GetAliasMembership()
420         r.data_in.domain_handle = self.handle
421         r.data_in.sids = dcerpc.lsa_SidArray()
422         r.data_in.sids.num_sids = len(sids)
423         r.data_in.sids.sids = dcerpc.new_lsa_SidPtr_array(len(sids))
424
425         for i in range(len(sids)):
426             s = dcerpc.lsa_SidPtr()
427             s.sid = string_to_sid(sids[i])
428             dcerpc.lsa_SidPtr_array_setitem(r.data_in.sids.sids, i, s)
429
430         call_fn(dcerpc.dcerpc_samr_GetAliasMembership, self.pipe, r)
431
432         return [r.ids[x] for x in range(r.count)]
433
434 class UserHandle(SamrHandle):
435
436     def DeleteUser(self):
437
438         r = dcerpc.samr_DeleteUser()
439         r.data_in.user_handle = self.handle
440         
441         call_fn(dcerpc.dcerpc_samr_DeleteUser, self.pipe, r)
442
443         self.handle = None
444     
445
446 class GroupHandle(SamrHandle):
447     pass
448     
449
450 class AliasHandle(SamrHandle):
451
452     def DeleteDomAlias(self):
453
454         r = dcerpc.samr_DeleteDomAlias()
455         r.data_in.alias_handle = self.handle
456
457         call_fn(dcerpc.dcerpc_samr_DeleteDomAlias, self.pipe, r)
458
459         self.handle = None
460
461     def QueryAliasInfo(self, level = 1):
462
463         r = dcerpc.samr_QueryAliasInfo()
464         r.data_in.alias_handle = self.handle
465         r.data_in.level = level
466
467         call_fn(dcerpc.dcerpc_samr_QueryAliasInfo, self.pipe, r)
468
469         return r.data_out.info
470
471     def SetAliasInfo(self, level, info):
472
473         r = dcerpc.samr_SetAliasInfo()
474         r.data_in.alias_handle = self.handle
475         r.data_in.level = level
476         r.data_in.info = info
477
478         call_fn(dcerpc.dcerpc_samr_SetAliasInfo, self.pipe, r)
479
480     def AddAliasMember(self, sid):
481
482         r = dcerpc.samr_AddAliasMember()
483         r.data_in.alias_handle = self.handle
484         r.data_in.sid = string_to_sid(sid)
485
486         call_fn(dcerpc.dcerpc_samr_AddAliasMember, self.pipe, r)
487
488     def AddMultipleMembersToAlias(self, sids):
489
490         r = dcerpc.samr_AddMultipleMembersToAlias()
491         r.data_in.alias_handle = self.handle
492         r.data_in.sids = dcerpc.lsa_SidArray()
493         r.data_in.sids.num_sids = len(sids)
494         r.data_in.sids.sids = dcerpc.new_lsa_SidPtr_array(len(sids))
495
496         for i in range(len(sids)):
497             s = dcerpc.lsa_SidPtr()
498             s.sid = string_to_sid(sids[i])
499             dcerpc.lsa_SidPtr_array_setitem(r.data_in.sids.sids, i, s)
500
501         call_fn(dcerpc.dcerpc_samr_AddMultipleMembersToAlias, self.pipe, r)
502
503 def Connect(pipe, access_mask = 0x02000000):
504
505     r = dcerpc.samr_Connect()
506     r.data_in.system_name = dcerpc.new_uint16_array(1)
507     dcerpc.uint16_array_setitem(r.data_in.system_name, 0, ord('\\'))
508     r.data_in.access_mask = access_mask
509
510     call_fn(dcerpc.dcerpc_samr_Connect, pipe, r)
511
512     return ConnectHandle(pipe, r.data_out.connect_handle)
513
514
515 def Connect2(pipe, system_name = '', access_mask = 0x02000000):
516     """Connect to the SAMR pipe."""
517
518     r = dcerpc.samr_Connect2()
519     r.data_in.system_name = system_name
520     r.data_in.access_mask = access_mask
521
522     call_fn(dcerpc.dcerpc_samr_Connect2, pipe, r)
523
524     return ConnectHandle(pipe, r.data_out.connect_handle)
525
526
527 def Connect3(pipe, system_name = '', access_mask = 0x02000000):
528
529     r = dcerpc.samr_Connect3()
530     r.data_in.system_name = system_name
531     r.data_in.unknown = 0
532     r.data_in.access_mask = access_mask
533
534     call_fn(dcerpc.dcerpc_samr_Connect3, pipe, r)
535
536     return ConnectHandle(pipe, r.data_out.connect_handle)
537
538
539 def Connect4(pipe, system_name = '', access_mask = 0x02000000):
540
541     r = dcerpc.samr_Connect4()
542     r.data_in.system_name = system_name
543     r.data_in.unknown = 0
544     r.data_in.access_mask = access_mask
545
546     call_fn(dcerpc.dcerpc_samr_Connect4, pipe, r)
547
548     return ConnectHandle(pipe, r.data_out.connect_handle)
549
550
551 def Connect5(pipe, system_name = '', access_mask = 0x02000000):
552
553     r = dcerpc.samr_Connect5()
554     r.data_in.system_name = system_name
555     r.data_in.access_mask = access_mask
556     r.data_in.level = 1
557     r.data_in.info = dcerpc.new_samr_ConnectInfo_array(1)
558     r.data_in.info.unknown1 = 0
559     r.data_in.info.unknown2 = 0
560
561     call_fn(dcerpc.dcerpc_samr_Connect5, pipe, r)
562
563     return ConnectHandle(pipe, r.data_out.connect_handle)
564     
565 # QueryGroupInfo
566 # SetGroupInfo
567 # AddGroupMember
568 # DeleteDomainGroup
569 # DeleteGroupMember
570 # QueryGroupMember
571 # SetMemberAttributesofGroup
572 # AddAliasMember
573 # DeleteAliasMember
574 # GetMembersinAlias
575 # QueryUserInfo
576 # SetUserInfo
577 # ChangePasswordUser
578 # GetGroupsForUser
579 # QueryDisplayInfo
580 # GetDisplayEnumerationIndex
581 # TestPrivateFunctionsDomain
582 # TestPrivateFunctionsUser
583 # GetUserPwInfo
584 # RemoveMemberFromForeignDomain
585 # QueryDomainInfo2
586 # QueryUserInfo2
587 # QueryDisplayInfo2
588 # GetDisplayEnumerationIndex2
589 # QueryDisplayInfo3
590 # RemoveMultipleMembersFromAlias
591 # OemChangePasswordUser2
592 # ChangePasswordUser2
593 # SetUserInfo2
594 # SetBootKeyInformation
595 # GetBootKeyInformation
596 # ChangePasswordUser3
597 # SetDsrmPassword
598 # ValidatePassword