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));
102 def __init__(self, pipe, handle):
109 if self.handle is not None:
114 r = dcerpc.samr_Close()
115 r.data_in.handle = self.handle
117 call_fn(dcerpc.dcerpc_samr_Close, self.pipe, r)
121 def QuerySecurity(self, sec_info = 7):
123 r = dcerpc.samr_QuerySecurity()
124 r.data_in.handle = self.handle
125 r.data_in.sec_info = sec_info
127 call_fn(dcerpc.dcerpc_samr_QuerySecurity, self.pipe, r)
129 return r.data_out.sdbuf
131 def SetSecurity(self, sdbuf, sec_info = 7):
133 r = dcerpc.samr_SetSecurity()
134 r.data_in.handle = self.handle
135 r.data_in.sec_info = sec_info
136 r.data_in.sdbuf = sdbuf
138 call_fn(dcerpc.dcerpc_samr_SetSecurity, self.pipe, r)
140 class ConnectHandle(SamrHandle):
142 def EnumDomains(self):
144 r = dcerpc.samr_EnumDomains()
145 r.data_in.connect_handle = self.handle
146 r.data_in.resume_handle = 0
147 r.data_in.buf_size = -1
153 call_fn(dcerpc.dcerpc_samr_EnumDomains, self.pipe, r)
155 for i in range(r.data_out.sam.count):
156 domains.append(dcerpc.samr_SamEntry_array_getitem(
157 r.data_out.sam.entries, i).name.string)
159 # TODO: Handle more entries here
165 def LookupDomain(self, domain_name):
167 r = dcerpc.samr_LookupDomain()
168 r.data_in.connect_handle = self.handle
169 r.data_in.domain_name = dcerpc.samr_String()
170 r.data_in.domain_name.string = domain_name
172 call_fn(dcerpc.dcerpc_samr_LookupDomain, self.pipe, r)
174 return sid_to_string(r.data_out.sid);
176 def OpenDomain(self, domain_sid, access_mask = 0x02000000):
178 r = dcerpc.samr_OpenDomain()
179 r.data_in.connect_handle = self.handle
180 r.data_in.access_mask = access_mask
181 r.data_in.sid = string_to_sid(domain_sid)
183 call_fn(dcerpc.dcerpc_samr_OpenDomain, self.pipe, r)
185 return DomainHandle(self.pipe, r.data_out.domain_handle)
189 r = dcerpc.samr_Shutdown()
190 r.data_in.connect_handle = self.handle
192 call_fn(dcerpc.dcerpc_samr_Shutdown, self.pipe, r)
194 def GetDomPwInfo(self, domain_name):
196 r = dcerpc.samr_GetDomPwInfo()
197 r.data_in.domain_name = dcerpc.samr_String()
198 r.data_in.domain_name.string = domain_name
200 call_fn(dcerpc.dcerpc_samr_GetDomPwInfo, self.pipe, r)
202 return r.data_out.info
205 def SetBootKeyInformation(self, unknown1, unknown2, unknown3):
207 r = dcerpc.samr_GetBootKeyInformation()
208 r.data_in.connect_handle = self.handle
209 r.data_in.unknown1 = unknown1
210 r.data_in.unknown2 = unknown2
211 r.data_in.unknown3 = unknown3
213 call_fn(dcerpc.dcerpc_samr_SetBootKeyInformation, self.pipe, r)
215 class DomainHandle(SamrHandle):
217 def QueryDomainInfo(self, level = 2):
219 r = dcerpc.samr_QueryDomainInfo()
220 r.data_in.domain_handle = self.handle
221 r.data_in.level = level
223 call_fn(dcerpc.dcerpc_samr_QueryDomainInfo, self.pipe, r)
225 return getattr(r.data_out.info, 'info%d' % level)
227 def QueryDomainInfo2(self, level = 2):
229 r = dcerpc.samr_QueryDomainInfo2()
230 r.data_in.domain_handle = self.handle
231 r.data_in.level = level
233 call_fn(dcerpc.dcerpc_samr_QueryDomainInfo2, self.pipe, r)
235 return getattr(r.data_out.info, 'info%d' % level)
237 def SetDomainInfo(self, level, info):
239 r = dcerpc.samr_SetDomainInfo()
240 r.data_in.domain_handle = self.handle
241 r.data_in.level = level
242 r.data_in.info = dcerpc.samr_DomainInfo()
243 setattr(r.data_in.info, 'info%d' % level, info)
245 call_fn(dcerpc.dcerpc_samr_SetDomainInfo, self.pipe, r)
247 def EnumDomainGroups(self):
249 r = dcerpc.samr_EnumDomainGroups()
250 r.data_in.domain_handle = self.handle
251 r.data_in.resume_handle = 0
252 r.data_in.max_size = 1000
254 call_fn(dcerpc.dcerpc_samr_EnumDomainGroups, self.pipe, r)
258 if r.data_out.sam.entries:
259 for i in range(r.data_out.sam.count):
260 groups.append(dcerpc.samr_SamEntry_array_getitem(
261 r.data_out.sam.entries, i).name.string)
265 def EnumDomainAliases(self):
267 r = dcerpc.samr_EnumDomainAliases()
268 r.data_in.domain_handle = self.handle
269 r.data_in.resume_handle = 0
270 # acct_flags in SamrEnumerateAliasesInDomain has probably
271 # no meaning so use 0xffffffff like W2K
272 r.data_in.acct_flags = 0xffffffffL
274 call_fn(dcerpc.dcerpc_samr_EnumDomainAliases, self.pipe, r)
278 if r.data_out.sam.entries:
279 for i in range(r.data_out.sam.count):
280 aliases.append(dcerpc.samr_SamEntry_array_getitem(
281 r.data_out.sam.entries, i).name.string)
285 def EnumDomainUsers(self, user_account_flags = 16):
287 r = dcerpc.samr_EnumDomainUsers()
288 r.data_in.domain_handle = self.handle
289 r.data_in.resume_handle = 0
290 r.data_in.acct_flags = user_account_flags
291 r.data_in.max_size = 1000
293 call_fn(dcerpc.dcerpc_samr_EnumDomainUsers, self.pipe, r)
297 if r.data_out.sam.entries:
298 for i in range(r.data_out.sam.count):
299 users.append(dcerpc.samr_SamEntry_array_getitem(
300 r.data_out.sam.entries, i).name.string)
304 def CreateUser(self, account_name, access_mask = 0x02000000):
306 r = dcerpc.samr_CreateUser()
307 r.data_in.domain_handle = self.handle
308 r.data_in.account_name = dcerpc.samr_String()
309 r.data_in.account_name.string = account_name
310 r.data_in.access_mask = access_mask
312 call_fn(dcerpc.dcerpc_samr_CreateUser, self.pipe, r)
314 return (r.data_out.user_handle,
315 dcerpc.uint32_array_getitem(r.data_out.rid, 0))
317 def CreateUser2(self, account_name, acct_flags = 0x00000010,
318 access_mask = 0x02000000):
320 r = dcerpc.samr_CreateUser2()
321 r.data_in.domain_handle = self.handle
322 r.data_in.account_name = dcerpc.samr_String()
323 r.data_in.account_name.string = account_name
324 r.data_in.acct_flags = acct_flags
325 r.data_in.access_mask = access_mask
327 call_fn(dcerpc.dcerpc_samr_CreateUser2, self.pipe, r)
329 return (r.data_out.user_handle,
330 dcerpc.uint32_array_getitem(r.data_out.access_granted, 0),
331 dcerpc.uint32_array_getitem(r.data_out.rid, 0))
333 def OpenUser(self, rid, access_mask = 0x02000000):
335 r = dcerpc.samr_OpenUser()
336 r.data_in.domain_handle = self.handle
337 r.data_in.access_mask = access_mask
340 call_fn(dcerpc.dcerpc_samr_OpenUser, self.pipe, r)
342 return UserHandle(self.pipe, r.data_out.user_handle)
344 def OpenGroup(self, rid, access_mask = 0x02000000):
346 r = dcerpc.samr_OpenGroup()
347 r.data_in.domain_handle = self.handle
348 r.data_in.access_mask = access_mask
351 call_fn(dcerpc.dcerpc_samr_OpenGroup, self.pipe, r)
353 return GroupHandle(self.pipe, r.data_out.group_handle)
355 def OpenAlias(self, rid, access_mask = 0x02000000):
357 r = dcerpc.samr_OpenAlias()
358 r.data_in.domain_handle = self.handle
359 r.data_in.access_mask = access_mask
362 call_fn(dcerpc.dcerpc_samr_OpenAlias, self.pipe, r)
364 return AliasHandle(self.pipe, r.data_out.alias_handle)
366 def CreateDomAlias(self, alias_name, access_mask = 0x02000000):
368 r = dcerpc.samr_CreateDomAlias()
369 r.data_in.domain_handle = self.handle
370 r.data_in.alias_name = dcerpc.samr_String()
371 r.data_in.alias_name.string = alias_name
372 r.data_in.access_mask = access_mask
374 call_fn(dcerpc.dcerpc_samr_CreateDomAlias, self.pipe, r)
376 return (AliasHandle(self.pipe, r.data_out.alias_handle),
379 def RidToSid(self, rid):
381 r = dcerpc.samr_RidToSid()
382 r.data_in.domain_handle = self.handle
385 call_fn(dcerpc.dcerpc_samr_RidToSid, self.pipe, r)
387 return sid_to_string(r.data_out.sid)
389 def RemoveMemberFromForeignDomain(self, sid):
391 r = dcerpc.samr_RemoveMemberFromForeignDomain()
392 r.data_in.domain_handle = self.handle
395 call_fn(dcerpc.dcerpc_samr_RemoveMemberFromForeignDomain, self.pipe, r)
397 def LookupNames(self, names):
399 r = dcerpc.samr_LookupNames()
400 r.data_in.domain_handle = self.handle
401 r.data_in.num_names = len(names)
402 r.data_in.names = dcerpc.new_samr_String_array(len(names))
404 for i in range(len(names)):
405 s = dcerpc.samr_String()
407 dcerpc.samr_String_array_setitem(r.data_in.names, i, s)
409 call_fn(dcerpc.dcerpc_samr_LookupNames, self.pipe, r)
411 return ([dcerpc.uint32_array_getitem(r.data_out.rids.ids, i)
412 for i in range(r.data_out.rids.count)],
413 [dcerpc.uint32_array_getitem(r.data_out.types.ids, i)
414 for i in range(r.data_out.types.count)])
416 def CreateDomainGroup(self, domain_name, access_mask = 0x02000000):
418 r = dcerpc.samr_CreateDomainGroup()
419 r.data_in.domain_handle = self.handle
420 r.data_in.name = dcerpc.samr_String()
421 r.data_in.name.string = domain_name
422 r.data_in.access_mask = access_mask
424 call_fn(dcerpc.dcerpc_samr_CreateDomainGroup, self.pipe, r)
426 def GetAliasMembership(self, sids):
428 r = dcerpc.samr_GetAliasMembership()
429 r.data_in.domain_handle = self.handle
430 r.data_in.sids = dcerpc.lsa_SidArray()
431 r.data_in.sids.num_sids = len(sids)
432 r.data_in.sids.sids = dcerpc.new_lsa_SidPtr_array(len(sids))
434 for i in range(len(sids)):
435 s = dcerpc.lsa_SidPtr()
436 s.sid = string_to_sid(sids[i])
437 dcerpc.lsa_SidPtr_array_setitem(r.data_in.sids.sids, i, s)
439 call_fn(dcerpc.dcerpc_samr_GetAliasMembership, self.pipe, r)
441 return [r.ids[x] for x in range(r.count)]
443 def QueryDisplayInfo(self, level):
445 # TODO: Handle more data returns
447 r = dcerpc.samr_QueryDisplayInfo()
448 r.data_in.domain_handle = self.handle
449 r.data_in.level = level
450 r.data_in.start_idx = 0
451 r.data_in.max_entries = 1000
452 r.data_in.buf_size = -1
454 call_fn(dcerpc.dcerpc_samr_QueryDisplayInfo, self.pipe, r)
456 # TODO: Return a mapping of the various samr_DispInfo
459 return getattr(r.data_out.info, 'info%d' % level)
461 def QueryDisplayInfo2(self, level):
463 # TODO: Handle more data returns
465 r = dcerpc.samr_QueryDisplayInfo2()
466 r.data_in.domain_handle = self.handle
467 r.data_in.level = level
468 r.data_in.start_idx = 0
469 r.data_in.max_entries = 1000
470 r.data_in.buf_size = -1
472 call_fn(dcerpc.dcerpc_samr_QueryDisplayInfo2, self.pipe, r)
474 # TODO: Return a mapping of the various samr_DispInfo
477 return getattr(r.data_out.info, 'info%d' % level)
479 def QueryDisplayInfo3(self, level):
481 # TODO: Handle more data returns
483 r = dcerpc.samr_QueryDisplayInfo3()
484 r.data_in.domain_handle = self.handle
485 r.data_in.level = level
486 r.data_in.start_idx = 0
487 r.data_in.max_entries = 1000
488 r.data_in.buf_size = -1
490 call_fn(dcerpc.dcerpc_samr_QueryDisplayInfo3, self.pipe, r)
492 # TODO: Return a mapping of the various samr_DispInfo
495 return getattr(r.data_out.info, 'info%d' % level)
497 def GetBootKeyInformation(self):
499 r = dcerpc.samr_GetBootKeyInformation()
500 r.data_in.domain_handle = self.handle
502 call_fn(dcerpc.dcerpc_samr_GetBootKeyInformation, self.pipe, r)
504 return r.data_out.unknown
506 def SetBootKeyInformation(self):
508 r = dcerpc.samr_GetBootKeyInformation()
509 r.data_in.domain_handle = self.handle
511 call_fn(dcerpc.dcerpc_samr_GetBootKeyInformation, self.pipe, r)
513 def TestPrivateFunctionsDomain(self):
515 r = dcerpc.samr_TestPrivateFunctionsDomain()
516 r.data_in.domain_handle = self.handle
518 call_fn(dcerpc.dcerpc_samr_TestPrivateFunctionsDomain, self.pipe, r)
520 class UserHandle(SamrHandle):
522 def DeleteUser(self):
524 r = dcerpc.samr_DeleteUser()
525 r.data_in.user_handle = self.handle
527 call_fn(dcerpc.dcerpc_samr_DeleteUser, self.pipe, r)
531 def GetUserPwInfo(self):
533 r = dcerpc.samr_GetUserPwInfo()
534 r.data_in.user_handle = self.handle
536 call_fn(dcerpc.dcerpc_samr_GetUserPwInfo, self.pipe, r)
538 return r.data_out.info
540 def QueryUserInfo(self, level):
542 r = dcerpc.samr_QueryUserInfo()
543 r.data_in.user_handle = self.handle
544 r.data_in.level = level
546 call_fn(dcerpc.dcerpc_samr_QueryUserInfo, self.pipe, r)
548 return r.data_out.info
550 def QueryUserInfo2(self, level):
552 r = dcerpc.samr_QueryUserInfo2()
553 r.data_in.user_handle = self.handle
554 r.data_in.level = level
556 call_fn(dcerpc.dcerpc_samr_QueryUserInfo2, self.pipe, r)
558 return r.data_out.info
560 def GetGroupsForUser(self):
562 r = dcerpc.samr_GetGroupsForUser()
563 r.data_in.user_handle = self.handle
565 call_fn(dcerpc.dcerpc_samr_GetGroupsForUser, self.pipe, r)
567 rid_types = [dcerpc.samr_RidType_array_getitem(r.data_out.rids.rid, x)
568 for x in range(r.data_out.rids.count)]
570 return [(x.rid, x.type) for x in rid_types]
572 def TestPrivateFunctionsUser(self):
574 r = dcerpc.samr_TestPrivateFunctionsUser()
575 r.data_in.user_handle = self.handle
577 call_fn(dcerpc.dcerpc_samr_TestPrivateFunctionsUser, self.pipe, r)
579 class GroupHandle(SamrHandle):
581 def QueryGroupInfo(self, level):
583 r = dcerpc.samr_QueryGroupInfo()
584 r.data_in.group_handle = self.handle
585 r.data_in.level = level
587 call_fn(dcerpc.dcerpc_samr_QueryGroupInfo, self.pipe, r)
589 return r.data_out.info
591 def SetGroupInfo(self, level, info):
593 r = dcerpc.samr_SetGroupInfo()
594 r.data_in.group_handle = self.handle
595 r.data_in.level = level
596 r.data_in.info = info
598 call_fn(dcerpc.dcerpc_samr_SetGroupInfo, self.pipe, r)
600 def QueryGroupMember(self):
602 r = dcerpc.samr_QueryGroupMember()
603 r.data_in.group_handle = self.handle
605 call_fn(dcerpc.dcerpc_samr_QueryGroupMember, self.pipe, r)
607 return [(dcerpc.uint32_array_getitem(r.data_out.rids.rids, x),
608 dcerpc.uint32_array_getitem(r.data_out.rids.unknown, x))
609 for x in range(r.data_out.rids.count)]
611 class AliasHandle(SamrHandle):
613 def DeleteDomAlias(self):
615 r = dcerpc.samr_DeleteDomAlias()
616 r.data_in.alias_handle = self.handle
618 call_fn(dcerpc.dcerpc_samr_DeleteDomAlias, self.pipe, r)
622 def QueryAliasInfo(self, level = 1):
624 r = dcerpc.samr_QueryAliasInfo()
625 r.data_in.alias_handle = self.handle
626 r.data_in.level = level
628 call_fn(dcerpc.dcerpc_samr_QueryAliasInfo, self.pipe, r)
630 return r.data_out.info
632 def SetAliasInfo(self, level, info):
634 r = dcerpc.samr_SetAliasInfo()
635 r.data_in.alias_handle = self.handle
636 r.data_in.level = level
637 r.data_in.info = info
639 call_fn(dcerpc.dcerpc_samr_SetAliasInfo, self.pipe, r)
641 def AddAliasMember(self, sid):
643 r = dcerpc.samr_AddAliasMember()
644 r.data_in.alias_handle = self.handle
645 r.data_in.sid = string_to_sid(sid)
647 call_fn(dcerpc.dcerpc_samr_AddAliasMember, self.pipe, r)
649 def AddMultipleMembersToAlias(self, sids):
651 r = dcerpc.samr_AddMultipleMembersToAlias()
652 r.data_in.alias_handle = self.handle
653 r.data_in.sids = dcerpc.lsa_SidArray()
654 r.data_in.sids.num_sids = len(sids)
655 r.data_in.sids.sids = dcerpc.new_lsa_SidPtr_array(len(sids))
657 for i in range(len(sids)):
658 s = dcerpc.lsa_SidPtr()
659 s.sid = string_to_sid(sids[i])
660 dcerpc.lsa_SidPtr_array_setitem(r.data_in.sids.sids, i, s)
662 call_fn(dcerpc.dcerpc_samr_AddMultipleMembersToAlias, self.pipe, r)
664 def GetMembersInAlias(self):
666 r = dcerpc.samr_GetMembersInAlias()
667 r.data_in.alias_handle = self.handle
669 call_fn(dcerpc.dcerpc_samr_GetMembersInAlias, self.pipe, r)
673 dcerpc.lsa_SidPtr_array_getitem(r.data_out.sids.sids, x).sid)
674 for x in range(r.data_out.sids.num_sids)]
676 def Connect(pipe, access_mask = 0x02000000):
678 r = dcerpc.samr_Connect()
679 r.data_in.system_name = dcerpc.new_uint16_array(1)
680 dcerpc.uint16_array_setitem(r.data_in.system_name, 0, ord('\\'))
681 r.data_in.access_mask = access_mask
683 call_fn(dcerpc.dcerpc_samr_Connect, pipe, r)
685 return ConnectHandle(pipe, r.data_out.connect_handle)
687 def Connect2(pipe, system_name = '', access_mask = 0x02000000):
688 """Connect to the SAMR pipe."""
690 r = dcerpc.samr_Connect2()
691 r.data_in.system_name = system_name
692 r.data_in.access_mask = access_mask
694 call_fn(dcerpc.dcerpc_samr_Connect2, pipe, r)
696 return ConnectHandle(pipe, r.data_out.connect_handle)
698 def Connect3(pipe, system_name = '', access_mask = 0x02000000):
700 r = dcerpc.samr_Connect3()
701 r.data_in.system_name = system_name
702 r.data_in.unknown = 0
703 r.data_in.access_mask = access_mask
705 call_fn(dcerpc.dcerpc_samr_Connect3, pipe, r)
707 return ConnectHandle(pipe, r.data_out.connect_handle)
710 def Connect4(pipe, system_name = '', access_mask = 0x02000000):
712 r = dcerpc.samr_Connect4()
713 r.data_in.system_name = system_name
714 r.data_in.unknown = 0
715 r.data_in.access_mask = access_mask
717 call_fn(dcerpc.dcerpc_samr_Connect4, pipe, r)
719 return ConnectHandle(pipe, r.data_out.connect_handle)
721 def Connect5(pipe, system_name = '', access_mask = 0x02000000):
723 r = dcerpc.samr_Connect5()
724 r.data_in.system_name = system_name
725 r.data_in.access_mask = access_mask
727 r.data_in.info = dcerpc.new_samr_ConnectInfo_array(1)
728 r.data_in.info.unknown1 = 0
729 r.data_in.info.unknown2 = 0
731 call_fn(dcerpc.dcerpc_samr_Connect5, pipe, r)
733 return ConnectHandle(pipe, r.data_out.connect_handle)
738 # SetMemberAttributesofGroup
744 # GetDisplayEnumerationIndex
745 # RemoveMemberFromForeignDomain
746 # GetDisplayEnumerationIndex2
747 # RemoveMultipleMembersFromAlias
748 # OemChangePasswordUser2
749 # ChangePasswordUser2
751 # ChangePasswordUser3