3 def sid_to_string(sid):
4 """Convert a Python dictionary SID to a string SID."""
6 result = 'S-%d' % sid.sid_rev_num
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))
14 for i in range(0, sid.num_auths):
15 result = result + '-%u' % \
16 dcerpc.uint32_array_getitem(sid.sub_auths, i)
20 def string_to_sid(string):
21 """Convert a string SID to a Python dictionary SID. Throws a
22 ValueError if the SID string was badly formed."""
25 raise ValueError('Bad SID format')
31 match = re.match('-\d+', string)
34 raise ValueError('Bad SID format')
37 sid_rev_num = int(string[match.start()+1:match.end()])
39 raise ValueError('Bad SID format')
41 string = string[match.end():]
43 match = re.match('-\d+', string)
46 raise ValueError('Bad SID format')
49 ia = int(string[match.start()+1:match.end()])
51 raise ValueError('Bad SID format')
53 string = string[match.end():]
55 id_auth = [0, 0, (ia >> 24) & 0xff, (ia >> 16) & 0xff,
56 (ia >> 8) & 0xff, ia & 0xff]
63 match = re.match('-\d+', string)
66 raise ValueError('Bad SID format')
69 sa = int(string[match.start() + 1 : match.end()])
71 raise ValueError('Bad SID format')
73 num_auths = num_auths + 1
74 sub_auths.append(int(sa))
76 string = string[match.end():]
78 sid = dcerpc.dom_sid()
79 sid.sid_rev_num = sid_rev_num
80 sid.id_auth = dcerpc.new_uint8_array(6)
82 dcerpc.uint8_array_setitem(sid.id_auth, i, id_auth[i])
83 sid.num_auths = num_auths
84 sid.sub_auths = dcerpc.new_uint32_array(num_auths)
85 for i in range(num_auths):
86 dcerpc.uint32_array_setitem(sid.sub_auths, i, sub_auths[i])
90 def call_fn(fn, pipe, args):
91 """Wrap up a RPC call and throw an exception is an error was returned."""
93 result = fn(pipe, args);
95 if result & 0xc0000000L:
96 raise dcerpc.NTSTATUS(result, dcerpc.nt_errstr(result));
101 class SamrHandle(object):
103 def __init__(self, pipe, handle):
110 if self.handle is not None:
115 r = dcerpc.samr_Close()
116 r.data_in.handle = self.handle
118 call_fn(dcerpc.dcerpc_samr_Close, self.pipe, r)
122 def QuerySecurity(self, sec_info = 7):
124 r = dcerpc.samr_QuerySecurity()
125 r.data_in.handle = self.handle
126 r.data_in.sec_info = sec_info
128 call_fn(dcerpc.dcerpc_samr_QuerySecurity, self.pipe, r)
130 return r.data_out.sdbuf
132 def SetSecurity(self, sdbuf, sec_info = 7):
134 r = dcerpc.samr_SetSecurity()
135 r.data_in.handle = self.handle
136 r.data_in.sec_info = sec_info
137 r.data_in.sdbuf = sdbuf
139 call_fn(dcerpc.dcerpc_samr_SetSecurity, self.pipe, r)
142 class ConnectHandle(SamrHandle):
144 def EnumDomains(self):
146 r = dcerpc.samr_EnumDomains()
147 r.data_in.connect_handle = self.handle
148 r.data_in.resume_handle = 0
149 r.data_in.buf_size = -1
155 call_fn(dcerpc.dcerpc_samr_EnumDomains, self.pipe, r)
157 for i in range(r.data_out.sam.count):
158 domains.append(dcerpc.samr_SamEntry_array_getitem(
159 r.data_out.sam.entries, i).name.string)
161 # TODO: Handle more entries here
167 def LookupDomain(self, domain_name):
169 r = dcerpc.samr_LookupDomain()
170 r.data_in.connect_handle = self.handle
171 r.data_in.domain_name = dcerpc.samr_String()
172 r.data_in.domain_name.string = domain_name
174 call_fn(dcerpc.dcerpc_samr_LookupDomain, self.pipe, r)
176 return sid_to_string(r.data_out.sid);
178 def OpenDomain(self, domain_sid, access_mask = 0x02000000):
180 r = dcerpc.samr_OpenDomain()
181 r.data_in.connect_handle = self.handle
182 r.data_in.access_mask = access_mask
183 r.data_in.sid = string_to_sid(domain_sid)
185 call_fn(dcerpc.dcerpc_samr_OpenDomain, self.pipe, r)
187 return DomainHandle(self.pipe, r.data_out.domain_handle)
191 r = dcerpc.samr_Shutdown()
192 r.data_in.connect_handle = self.handle
194 call_fn(dcerpc.dcerpc_samr_Shutdown, self.pipe, r)
196 def GetDomPwInfo(self, domain_name):
198 r = dcerpc.samr_GetDomPwInfo()
199 r.data_in.domain_name = dcerpc.samr_String()
200 r.data_in.domain_name.string = domain_name
202 call_fn(dcerpc.dcerpc_samr_GetDomPwInfo, self.pipe, r)
204 return r.data_out.info
207 def SetBootKeyInformation(self, unknown1, unknown2, unknown3):
209 r = dcerpc.samr_GetBootKeyInformation()
210 r.data_in.connect_handle = self.handle
211 r.data_in.unknown1 = unknown1
212 r.data_in.unknown2 = unknown2
213 r.data_in.unknown3 = unknown3
215 call_fn(dcerpc.dcerpc_samr_SetBootKeyInformation, self.pipe, r)
218 class DomainHandle(SamrHandle):
220 def QueryDomainInfo(self, level = 2):
222 r = dcerpc.samr_QueryDomainInfo()
223 r.data_in.domain_handle = self.handle
224 r.data_in.level = level
226 call_fn(dcerpc.dcerpc_samr_QueryDomainInfo, self.pipe, r)
228 return getattr(r.data_out.info, 'info%d' % level)
230 def QueryDomainInfo2(self, level = 2):
232 r = dcerpc.samr_QueryDomainInfo2()
233 r.data_in.domain_handle = self.handle
234 r.data_in.level = level
236 call_fn(dcerpc.dcerpc_samr_QueryDomainInfo2, self.pipe, r)
238 return getattr(r.data_out.info, 'info%d' % level)
240 def SetDomainInfo(self, level, info):
242 r = dcerpc.samr_SetDomainInfo()
243 r.data_in.domain_handle = self.handle
244 r.data_in.level = level
245 r.data_in.info = dcerpc.samr_DomainInfo()
246 setattr(r.data_in.info, 'info%d' % level, info)
248 call_fn(dcerpc.dcerpc_samr_SetDomainInfo, self.pipe, r)
250 def EnumDomainGroups(self):
252 r = dcerpc.samr_EnumDomainGroups()
253 r.data_in.domain_handle = self.handle
254 r.data_in.resume_handle = 0
255 r.data_in.max_size = 1000
257 call_fn(dcerpc.dcerpc_samr_EnumDomainGroups, self.pipe, r)
261 if r.data_out.sam.entries:
262 for i in range(r.data_out.sam.count):
263 groups.append(dcerpc.samr_SamEntry_array_getitem(
264 r.data_out.sam.entries, i).name.string)
268 def EnumDomainAliases(self):
270 r = dcerpc.samr_EnumDomainAliases()
271 r.data_in.domain_handle = self.handle
272 r.data_in.resume_handle = 0
273 # acct_flags in SamrEnumerateAliasesInDomain has probably
274 # no meaning so use 0xffffffff like W2K
275 r.data_in.acct_flags = 0xffffffffL
277 call_fn(dcerpc.dcerpc_samr_EnumDomainAliases, self.pipe, r)
281 if r.data_out.sam.entries:
282 for i in range(r.data_out.sam.count):
283 aliases.append(dcerpc.samr_SamEntry_array_getitem(
284 r.data_out.sam.entries, i).name.string)
288 def EnumDomainUsers(self, user_account_flags = 16):
290 r = dcerpc.samr_EnumDomainUsers()
291 r.data_in.domain_handle = self.handle
292 r.data_in.resume_handle = 0
293 r.data_in.acct_flags = user_account_flags
294 r.data_in.max_size = 1000
296 call_fn(dcerpc.dcerpc_samr_EnumDomainUsers, self.pipe, r)
300 if r.data_out.sam.entries:
301 for i in range(r.data_out.sam.count):
302 users.append(dcerpc.samr_SamEntry_array_getitem(
303 r.data_out.sam.entries, i).name.string)
307 def CreateUser(self, account_name, access_mask = 0x02000000):
309 r = dcerpc.samr_CreateUser()
310 r.data_in.domain_handle = self.handle
311 r.data_in.account_name = dcerpc.samr_String()
312 r.data_in.account_name.string = account_name
313 r.data_in.access_mask = access_mask
315 call_fn(dcerpc.dcerpc_samr_CreateUser, self.pipe, r)
317 return (r.data_out.user_handle,
318 dcerpc.uint32_array_getitem(r.data_out.rid, 0))
320 def CreateUser2(self, account_name, acct_flags = 0x00000010,
321 access_mask = 0x02000000):
323 r = dcerpc.samr_CreateUser2()
324 r.data_in.domain_handle = self.handle
325 r.data_in.account_name = dcerpc.samr_String()
326 r.data_in.account_name.string = account_name
327 r.data_in.acct_flags = acct_flags
328 r.data_in.access_mask = access_mask
330 call_fn(dcerpc.dcerpc_samr_CreateUser2, self.pipe, r)
332 return (r.data_out.user_handle,
333 dcerpc.uint32_array_getitem(r.data_out.access_granted, 0),
334 dcerpc.uint32_array_getitem(r.data_out.rid, 0))
336 def OpenUser(self, rid, access_mask = 0x02000000):
338 r = dcerpc.samr_OpenUser()
339 r.data_in.domain_handle = self.handle
340 r.data_in.access_mask = access_mask
343 call_fn(dcerpc.dcerpc_samr_OpenUser, self.pipe, r)
345 return UserHandle(self.pipe, r.data_out.user_handle)
347 def OpenGroup(self, rid, access_mask = 0x02000000):
349 r = dcerpc.samr_OpenGroup()
350 r.data_in.domain_handle = self.handle
351 r.data_in.access_mask = access_mask
354 call_fn(dcerpc.dcerpc_samr_OpenGroup, self.pipe, r)
356 return GroupHandle(self.pipe, r.data_out.group_handle)
358 def OpenAlias(self, rid, access_mask = 0x02000000):
360 r = dcerpc.samr_OpenAlias()
361 r.data_in.domain_handle = self.handle
362 r.data_in.access_mask = access_mask
365 call_fn(dcerpc.dcerpc_samr_OpenAlias, self.pipe, r)
367 return AliasHandle(self.pipe, r.data_out.alias_handle)
369 def CreateDomAlias(self, alias_name, access_mask = 0x02000000):
371 r = dcerpc.samr_CreateDomAlias()
372 r.data_in.domain_handle = self.handle
373 r.data_in.alias_name = dcerpc.samr_String()
374 r.data_in.alias_name.string = alias_name
375 r.data_in.access_mask = access_mask
377 call_fn(dcerpc.dcerpc_samr_CreateDomAlias, self.pipe, r)
379 return (AliasHandle(self.pipe, r.data_out.alias_handle),
382 def RidToSid(self, rid):
384 r = dcerpc.samr_RidToSid()
385 r.data_in.domain_handle = self.handle
388 call_fn(dcerpc.dcerpc_samr_RidToSid, self.pipe, r)
390 return sid_to_string(r.data_out.sid)
392 def RemoveMemberFromForeignDomain(self, sid):
394 r = dcerpc.samr_RemoveMemberFromForeignDomain()
395 r.data_in.domain_handle = self.handle
398 call_fn(dcerpc.dcerpc_samr_RemoveMemberFromForeignDomain, self.pipe, r)
400 def LookupNames(self, names):
402 r = dcerpc.samr_LookupNames()
403 r.data_in.domain_handle = self.handle
404 r.data_in.num_names = len(names)
405 r.data_in.names = dcerpc.new_samr_String_array(len(names))
407 for i in range(len(names)):
408 s = dcerpc.samr_String()
410 dcerpc.samr_String_array_setitem(r.data_in.names, i, s)
412 call_fn(dcerpc.dcerpc_samr_LookupNames, self.pipe, r)
414 return ([dcerpc.uint32_array_getitem(r.data_out.rids.ids, i)
415 for i in range(r.data_out.rids.count)],
416 [dcerpc.uint32_array_getitem(r.data_out.types.ids, i)
417 for i in range(r.data_out.types.count)])
419 def CreateDomainGroup(self, domain_name, access_mask = 0x02000000):
421 r = dcerpc.samr_CreateDomainGroup()
422 r.data_in.domain_handle = self.handle
423 r.data_in.name = dcerpc.samr_String()
424 r.data_in.name.string = domain_name
425 r.data_in.access_mask = access_mask
427 call_fn(dcerpc.dcerpc_samr_CreateDomainGroup, self.pipe, r)
429 def GetAliasMembership(self, sids):
431 r = dcerpc.samr_GetAliasMembership()
432 r.data_in.domain_handle = self.handle
433 r.data_in.sids = dcerpc.lsa_SidArray()
434 r.data_in.sids.num_sids = len(sids)
435 r.data_in.sids.sids = dcerpc.new_lsa_SidPtr_array(len(sids))
437 for i in range(len(sids)):
438 s = dcerpc.lsa_SidPtr()
439 s.sid = string_to_sid(sids[i])
440 dcerpc.lsa_SidPtr_array_setitem(r.data_in.sids.sids, i, s)
442 call_fn(dcerpc.dcerpc_samr_GetAliasMembership, self.pipe, r)
444 return [r.ids[x] for x in range(r.count)]
446 def QueryDisplayInfo(self, level):
448 # TODO: Handle more data returns
450 r = dcerpc.samr_QueryDisplayInfo()
451 r.data_in.domain_handle = self.handle
452 r.data_in.level = level
453 r.data_in.start_idx = 0
454 r.data_in.max_entries = 1000
455 r.data_in.buf_size = -1
457 call_fn(dcerpc.dcerpc_samr_QueryDisplayInfo, self.pipe, r)
459 # TODO: Return a mapping of the various samr_DispInfo
462 return getattr(r.data_out.info, 'info%d' % level)
464 def QueryDisplayInfo2(self, level):
466 # TODO: Handle more data returns
468 r = dcerpc.samr_QueryDisplayInfo2()
469 r.data_in.domain_handle = self.handle
470 r.data_in.level = level
471 r.data_in.start_idx = 0
472 r.data_in.max_entries = 1000
473 r.data_in.buf_size = -1
475 call_fn(dcerpc.dcerpc_samr_QueryDisplayInfo2, self.pipe, r)
477 # TODO: Return a mapping of the various samr_DispInfo
480 return getattr(r.data_out.info, 'info%d' % level)
482 def QueryDisplayInfo3(self, level):
484 # TODO: Handle more data returns
486 r = dcerpc.samr_QueryDisplayInfo3()
487 r.data_in.domain_handle = self.handle
488 r.data_in.level = level
489 r.data_in.start_idx = 0
490 r.data_in.max_entries = 1000
491 r.data_in.buf_size = -1
493 call_fn(dcerpc.dcerpc_samr_QueryDisplayInfo3, self.pipe, r)
495 # TODO: Return a mapping of the various samr_DispInfo
498 return getattr(r.data_out.info, 'info%d' % level)
500 def GetBootKeyInformation(self):
502 r = dcerpc.samr_GetBootKeyInformation()
503 r.data_in.domain_handle = self.handle
505 call_fn(dcerpc.dcerpc_samr_GetBootKeyInformation, self.pipe, r)
507 return r.data_out.unknown
509 def SetBootKeyInformation(self):
511 r = dcerpc.samr_GetBootKeyInformation()
512 r.data_in.domain_handle = self.handle
514 call_fn(dcerpc.dcerpc_samr_GetBootKeyInformation, self.pipe, r)
516 def TestPrivateFunctionsDomain(self):
518 r = dcerpc.samr_TestPrivateFunctionsDomain()
519 r.data_in.domain_handle = self.handle
521 call_fn(dcerpc.dcerpc_samr_TestPrivateFunctionsDomain, self.pipe, r)
524 class UserHandle(SamrHandle):
526 def DeleteUser(self):
528 r = dcerpc.samr_DeleteUser()
529 r.data_in.user_handle = self.handle
531 call_fn(dcerpc.dcerpc_samr_DeleteUser, self.pipe, r)
535 def GetUserPwInfo(self):
537 r = dcerpc.samr_GetUserPwInfo()
538 r.data_in.user_handle = self.handle
540 call_fn(dcerpc.dcerpc_samr_GetUserPwInfo, self.pipe, r)
542 return r.data_out.info
544 def QueryUserInfo(self, level):
546 r = dcerpc.samr_QueryUserInfo()
547 r.data_in.user_handle = self.handle
548 r.data_in.level = level
550 call_fn(dcerpc.dcerpc_samr_QueryUserInfo, self.pipe, r)
552 return r.data_out.info
554 def QueryUserInfo2(self, level):
556 r = dcerpc.samr_QueryUserInfo2()
557 r.data_in.user_handle = self.handle
558 r.data_in.level = level
560 call_fn(dcerpc.dcerpc_samr_QueryUserInfo2, self.pipe, r)
562 return r.data_out.info
564 def GetGroupsForUser(self):
566 r = dcerpc.samr_GetGroupsForUser()
567 r.data_in.user_handle = self.handle
569 call_fn(dcerpc.dcerpc_samr_GetGroupsForUser, self.pipe, r)
571 rid_types = [dcerpc.samr_RidType_array_getitem(r.data_out.rids.rid, x)
572 for x in range(r.data_out.rids.count)]
574 return [(x.rid, x.type) for x in rid_types]
576 def TestPrivateFunctionsUser(self):
578 r = dcerpc.samr_TestPrivateFunctionsUser()
579 r.data_in.user_handle = self.handle
581 call_fn(dcerpc.dcerpc_samr_TestPrivateFunctionsUser, self.pipe, r)
584 class GroupHandle(SamrHandle):
586 def QueryGroupInfo(self, level):
588 r = dcerpc.samr_QueryGroupInfo()
589 r.data_in.group_handle = self.handle
590 r.data_in.level = level
592 call_fn(dcerpc.dcerpc_samr_QueryGroupInfo, self.pipe, r)
594 return r.data_out.info
596 def SetGroupInfo(self, level, info):
598 r = dcerpc.samr_SetGroupInfo()
599 r.data_in.group_handle = self.handle
600 r.data_in.level = level
601 r.data_in.info = info
603 call_fn(dcerpc.dcerpc_samr_SetGroupInfo, self.pipe, r)
605 def QueryGroupMember(self):
607 r = dcerpc.samr_QueryGroupMember()
608 r.data_in.group_handle = self.handle
610 call_fn(dcerpc.dcerpc_samr_QueryGroupMember, self.pipe, r)
612 return [(dcerpc.uint32_array_getitem(r.data_out.rids.rids, x),
613 dcerpc.uint32_array_getitem(r.data_out.rids.unknown, x))
614 for x in range(r.data_out.rids.count)]
617 class AliasHandle(SamrHandle):
619 def DeleteDomAlias(self):
621 r = dcerpc.samr_DeleteDomAlias()
622 r.data_in.alias_handle = self.handle
624 call_fn(dcerpc.dcerpc_samr_DeleteDomAlias, self.pipe, r)
628 def QueryAliasInfo(self, level = 1):
630 r = dcerpc.samr_QueryAliasInfo()
631 r.data_in.alias_handle = self.handle
632 r.data_in.level = level
634 call_fn(dcerpc.dcerpc_samr_QueryAliasInfo, self.pipe, r)
636 return r.data_out.info
638 def SetAliasInfo(self, level, info):
640 r = dcerpc.samr_SetAliasInfo()
641 r.data_in.alias_handle = self.handle
642 r.data_in.level = level
643 r.data_in.info = info
645 call_fn(dcerpc.dcerpc_samr_SetAliasInfo, self.pipe, r)
647 def AddAliasMember(self, sid):
649 r = dcerpc.samr_AddAliasMember()
650 r.data_in.alias_handle = self.handle
651 r.data_in.sid = string_to_sid(sid)
653 call_fn(dcerpc.dcerpc_samr_AddAliasMember, self.pipe, r)
655 def AddMultipleMembersToAlias(self, sids):
657 r = dcerpc.samr_AddMultipleMembersToAlias()
658 r.data_in.alias_handle = self.handle
659 r.data_in.sids = dcerpc.lsa_SidArray()
660 r.data_in.sids.num_sids = len(sids)
661 r.data_in.sids.sids = dcerpc.new_lsa_SidPtr_array(len(sids))
663 for i in range(len(sids)):
664 s = dcerpc.lsa_SidPtr()
665 s.sid = string_to_sid(sids[i])
666 dcerpc.lsa_SidPtr_array_setitem(r.data_in.sids.sids, i, s)
668 call_fn(dcerpc.dcerpc_samr_AddMultipleMembersToAlias, self.pipe, r)
670 def GetMembersInAlias(self):
672 r = dcerpc.samr_GetMembersInAlias()
673 r.data_in.alias_handle = self.handle
675 call_fn(dcerpc.dcerpc_samr_GetMembersInAlias, self.pipe, r)
679 dcerpc.lsa_SidPtr_array_getitem(r.data_out.sids.sids, x).sid)
680 for x in range(r.data_out.sids.num_sids)]
682 def Connect(pipe, access_mask = 0x02000000):
684 r = dcerpc.samr_Connect()
685 r.data_in.system_name = dcerpc.new_uint16_array(1)
686 dcerpc.uint16_array_setitem(r.data_in.system_name, 0, ord('\\'))
687 r.data_in.access_mask = access_mask
689 call_fn(dcerpc.dcerpc_samr_Connect, pipe, r)
691 return ConnectHandle(pipe, r.data_out.connect_handle)
693 def Connect2(pipe, system_name = '', access_mask = 0x02000000):
694 """Connect to the SAMR pipe."""
696 r = dcerpc.samr_Connect2()
697 r.data_in.system_name = system_name
698 r.data_in.access_mask = access_mask
700 call_fn(dcerpc.dcerpc_samr_Connect2, pipe, r)
702 return ConnectHandle(pipe, r.data_out.connect_handle)
704 def Connect3(pipe, system_name = '', access_mask = 0x02000000):
706 r = dcerpc.samr_Connect3()
707 r.data_in.system_name = system_name
708 r.data_in.unknown = 0
709 r.data_in.access_mask = access_mask
711 call_fn(dcerpc.dcerpc_samr_Connect3, pipe, r)
713 return ConnectHandle(pipe, r.data_out.connect_handle)
716 def Connect4(pipe, system_name = '', access_mask = 0x02000000):
718 r = dcerpc.samr_Connect4()
719 r.data_in.system_name = system_name
720 r.data_in.unknown = 0
721 r.data_in.access_mask = access_mask
723 call_fn(dcerpc.dcerpc_samr_Connect4, pipe, r)
725 return ConnectHandle(pipe, r.data_out.connect_handle)
727 def Connect5(pipe, system_name = '', access_mask = 0x02000000):
729 r = dcerpc.samr_Connect5()
730 r.data_in.system_name = system_name
731 r.data_in.access_mask = access_mask
733 r.data_in.info = dcerpc.new_samr_ConnectInfo_array(1)
734 r.data_in.info.unknown1 = 0
735 r.data_in.info.unknown2 = 0
737 call_fn(dcerpc.dcerpc_samr_Connect5, pipe, r)
739 return ConnectHandle(pipe, r.data_out.connect_handle)
744 # SetMemberAttributesofGroup
750 # GetDisplayEnumerationIndex
751 # RemoveMemberFromForeignDomain
752 # GetDisplayEnumerationIndex2
753 # RemoveMultipleMembersFromAlias
754 # OemChangePasswordUser2
755 # ChangePasswordUser2
757 # ChangePasswordUser3