Skip to content

Commit

Permalink
Land #278, Support querying group memberships
Browse files Browse the repository at this point in the history
Add the ability to query group memberships
  • Loading branch information
smcintyre-r7 committed Nov 15, 2024
2 parents b7b37a4 + 8e7fa17 commit 177b14e
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 0 deletions.
2 changes: 2 additions & 0 deletions lib/ruby_smb/dcerpc/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ class Request < BinData::Record
samr_close_handle_request Samr::SAMR_CLOSE_HANDLE
samr_get_alias_membership_request Samr::SAMR_GET_ALIAS_MEMBERSHIP
samr_open_user_request Samr::SAMR_OPEN_USER
samr_open_group_request Samr::SAMR_OPEN_GROUP
samr_get_members_in_group_request Samr::SAMR_GET_MEMBERS_IN_GROUP
samr_get_groups_for_user_request Samr::SAMR_GET_GROUPS_FOR_USER
samr_enumerate_domains_in_sam_server_request Samr::SAMR_ENUMERATE_DOMAINS_IN_SAM_SERVER
samr_lookup_names_in_domain_request Samr::SAMR_LOOKUP_NAMES_IN_DOMAIN
Expand Down
70 changes: 70 additions & 0 deletions lib/ruby_smb/dcerpc/samr.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ module Samr
SAMR_ENUMERATE_USERS_IN_DOMAIN = 0x000D
SAMR_GET_ALIAS_MEMBERSHIP = 0x0010
SAMR_LOOKUP_NAMES_IN_DOMAIN = 0x0011
SAMR_OPEN_GROUP = 0x0013
SAMR_GET_MEMBERS_IN_GROUP = 0x0019
SAMR_OPEN_USER = 0x0022
SAMR_DELETE_USER = 0x0023
SAMR_GET_GROUPS_FOR_USER = 0x0027
Expand Down Expand Up @@ -509,8 +511,12 @@ def get_key_values
require 'ruby_smb/dcerpc/samr/samr_rid_to_sid_response'
require 'ruby_smb/dcerpc/samr/samr_close_handle_request'
require 'ruby_smb/dcerpc/samr/samr_close_handle_response'
require 'ruby_smb/dcerpc/samr/samr_get_members_in_group_request'
require 'ruby_smb/dcerpc/samr/samr_get_members_in_group_response'
require 'ruby_smb/dcerpc/samr/samr_get_alias_membership_request'
require 'ruby_smb/dcerpc/samr/samr_get_alias_membership_response'
require 'ruby_smb/dcerpc/samr/samr_open_group_request'
require 'ruby_smb/dcerpc/samr/samr_open_group_response'
require 'ruby_smb/dcerpc/samr/samr_open_user_request'
require 'ruby_smb/dcerpc/samr/samr_open_user_response'
require 'ruby_smb/dcerpc/samr/samr_get_groups_for_user_request'
Expand Down Expand Up @@ -935,6 +941,40 @@ def samr_get_alias_membership(domain_handle:, sids:)
samr_get_alias_membership_reponse.membership.elements.to_ary
end

# Returns a handle to a group, given a RID
#
# @param domain_handle [RubySMB::Dcerpc::Samr::SamprHandle] An RPC context
# representing a domain object
# @param access [Integer] An access control that indicates the requested
# access for the returned handle. It is a bitwise OR of common
# ACCESS_MASK and user ACCESS_MASK values (see
# lib/ruby_smb/dcerpc/samr.rb)
# @param group_id [Integer] RID of a group
# @return [RubySMB::Dcerpc::Samr::SamprHandle] The group handle
# @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a
# SamrOpenGroup packet
# @raise [RubySMB::Dcerpc::Error::SamrError] if the response error status
# is not STATUS_SUCCESS
def samr_open_group(domain_handle:, access: MAXIMUM_ALLOWED, group_id:)
samr_open_group_request = SamrOpenGroupRequest.new(
domain_handle: domain_handle,
desired_access: access,
group_id: group_id
)
response = dcerpc_request(samr_open_group_request)
begin
samr_open_group_response = SamrOpenGroupResponse.read(response)
rescue IOError
raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading SamrOpenGroupResponse'
end
unless samr_open_group_response.error_status == WindowsError::NTStatus::STATUS_SUCCESS
raise RubySMB::Dcerpc::Error::SamrError,
"Error returned when getting a handle to group #{group_id}: "\
"#{WindowsError::NTStatus.find_by_retval(samr_open_grou_response.error_status.value).join(',')}"
end
samr_open_group_response.group_handle
end

# Returns a handle to a user, given a RID
#
# @param domain_handle [RubySMB::Dcerpc::Samr::SamprHandle] An RPC context
Expand Down Expand Up @@ -969,6 +1009,36 @@ def samr_open_user(domain_handle:, access: MAXIMUM_ALLOWED, user_id:)
samr_open_user_response.user_handle
end

# Returns a listing of members of the given group
#
# @param group_handle [RubySMB::Dcerpc::Samr::SamprHandle] An RPC context
# representing a group object.
# @return [Array<Array<String,String>>] Array of RID and Attributes
# @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a
# SamrGetMembersInGroup packet
# @raise [RubySMB::Dcerpc::Error::SamrError] if the response error status
# is not STATUS_SUCCESS
def samr_get_members_in_group(group_handle:)
samr_get_members_in_group_request = SamrGetMembersInGroupRequest.new(
group_handle: group_handle
)
response = dcerpc_request(samr_get_members_in_group_request)
begin
samr_get_members_in_group_response = SamrGetMembersInGroupResponse.read(response)
rescue IOError
raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading SamrGetMembersInGroupResponse'
end
unless samr_get_members_in_group_response.error_status == WindowsError::NTStatus::STATUS_SUCCESS
raise RubySMB::Dcerpc::Error::SamrError,
"Error returned while getting group membership: "\
"#{WindowsError::NTStatus.find_by_retval(samr_get_members_in_group_response.error_status.value).join(',')}"
end
members = samr_get_members_in_group_response.members.members.to_ary
attributes = samr_get_members_in_group_response.members.attributes.to_ary

members.zip(attributes)
end

# Returns a listing of groups that a user is a member of
#
# @param user_handle [RubySMB::Dcerpc::Samr::SamprHandle] An RPC context
Expand Down
23 changes: 23 additions & 0 deletions lib/ruby_smb/dcerpc/samr/samr_get_members_in_group_request.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
module RubySMB
module Dcerpc
module Samr

# [3.1.5.8.3 SamrGetMembersInGroup (Opnum 25)](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/3ed5030d-88a3-42ca-a6e0-8c12aa2fdfbd)
class SamrGetMembersInGroupRequest < BinData::Record
attr_reader :opnum

endian :little

sampr_handle :group_handle

def initialize_instance
super
@opnum = SAMR_GET_MEMBERS_IN_GROUP
end
end

end
end
end


34 changes: 34 additions & 0 deletions lib/ruby_smb/dcerpc/samr/samr_get_members_in_group_response.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
module RubySMB
module Dcerpc
module Samr
# [2.2.7.14 SAMPR_GET_MEMBERS_BUFFER](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/225147b1-45b7-4fde-a5bf-bf420e18fa08)
class SamprGetMembersBuffer < Ndr::NdrStruct
default_parameter byte_align: 4

ndr_uint32 :member_count
ndr_uint32_conf_array_ptr :members, type: :ndr_uint32
ndr_uint32_conf_array_ptr :attributes, type: :ndr_uint32
end

class PsamprGetMembersBuffer < SamprGetMembersBuffer
extend Ndr::PointerClassPlugin
end

# [2.1.5.8.3 SamrGetMembersInGroup (Opnum 25)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/a4adbf20-040f-4416-a960-e5b7917fdae7)
class SamrGetMembersInGroupResponse < BinData::Record
attr_reader :opnum

endian :little

psampr_get_members_buffer :members
ndr_uint32 :error_status

def initialize_instance
super
@opnum = SAMR_GET_MEMBERS_IN_GROUP
end
end
end
end
end

26 changes: 26 additions & 0 deletions lib/ruby_smb/dcerpc/samr/samr_open_group_request.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
module RubySMB
module Dcerpc
module Samr

# [3.1.5.1.7 SamrOpenGroup (Opnum 19)](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/d396e6c9-d04a-4729-b0d8-f50f2748f3c8)
class SamrOpenGroupRequest < BinData::Record
attr_reader :opnum

endian :little

sampr_handle :domain_handle
# Access control on a server object: bitwise OR of common ACCESS_MASK
# and user ACCESS_MASK values (see lib/ruby_smb/dcerpc/samr.rb)
ndr_uint32 :desired_access
ndr_uint32 :group_id

def initialize_instance
super
@opnum = SAMR_OPEN_GROUP
end
end

end
end
end

24 changes: 24 additions & 0 deletions lib/ruby_smb/dcerpc/samr/samr_open_group_response.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module RubySMB
module Dcerpc
module Samr

# [3.1.5.1.7 SamrOpenGroup (Opnum 19)](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/d396e6c9-d04a-4729-b0d8-f50f2748f3c8)
class SamrOpenGroupResponse < BinData::Record
attr_reader :opnum

endian :little

sampr_handle :group_handle
ndr_uint32 :error_status

def initialize_instance
super
@opnum = SAMR_OPEN_GROUP
end
end

end
end
end


0 comments on commit 177b14e

Please sign in to comment.