Module: RubySMB::Signing

Included in:
Client, RubySMB::Server::ServerClient
Defined in:
lib/ruby_smb/signing.rb

Overview

Contains the methods for handling packet signing

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#session_keyString



7
8
9
# File 'lib/ruby_smb/signing.rb', line 7

def session_key
  @session_key
end

Class Method Details

.smb1_sign(packet, session_key, sequence_counter) ⇒ RubySMB::GenericPacket

Take an SMB1 packet and sign it. This version is a module function that requires the necessary values to be explicitly passed to it.



28
29
30
31
32
33
34
35
36
# File 'lib/ruby_smb/signing.rb', line 28

def self.smb1_sign(packet, session_key, sequence_counter)
  # Pack the Sequence counter into a int64le
  packed_sequence_counter = [sequence_counter].pack('Q<')
  packet.smb_header.security_features = packed_sequence_counter
  signature = OpenSSL::Digest::MD5.digest(session_key + packet.to_binary_s)[0, 8]
  packet.smb_header.security_features = signature

  packet
end

.smb2_sign(packet, session_key) ⇒ RubySMB::GenericPacket

Take an SMB2 packet and sign it. This version is a module function that requires the necessary values to be explicitly passed to it.



53
54
55
56
57
58
59
60
61
62
# File 'lib/ruby_smb/signing.rb', line 53

def self.smb2_sign(packet, session_key)
  packet.smb2_header.flags.signed = 1
  packet.smb2_header.signature = "\x00" * 16
  # OpenSSL 3 raises exceptions if the session key is an empty string
  session_key = session_key == '' ? ("\x00" * 16).b : session_key
  hmac = OpenSSL::HMAC.digest(OpenSSL::Digest.new('SHA256'), session_key, packet.to_binary_s)
  packet.smb2_header.signature = hmac[0, 16]

  packet
end

.smb3_sign(packet, session_key, dialect, preauth_integrity_hash = nil) ⇒ RubySMB::GenericPacket

Take an SMB3 packet and sign it. This version is a module function that requires the necessary values to be explicitly passed to it.



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/ruby_smb/signing.rb', line 82

def self.smb3_sign(packet, session_key, dialect, preauth_integrity_hash=nil)
  case dialect
  when '0x0300', '0x0302'
    signing_key = Crypto::KDF.counter_mode(session_key, "SMB2AESCMAC\x00", "SmbSign\x00")
  when '0x0311'
    raise ArgumentError.new('the preauth integrity hash is required for the specified dialect') if preauth_integrity_hash.nil?
    signing_key = Crypto::KDF.counter_mode(session_key, "SMBSigningKey\x00", preauth_integrity_hash)
  else
    raise Error::SigningError.new("Dialect #{dialect.inspect} is incompatible with SMBv3 signing")
  end

  packet.smb2_header.flags.signed = 1
  packet.smb2_header.signature = "\x00" * 16
  hmac = OpenSSL::CMAC.digest('AES', signing_key, packet.to_binary_s)
  packet.smb2_header.signature = hmac[0, 16]

  packet
end

Instance Method Details

#smb1_sign(packet) ⇒ RubySMB::GenericPacket

Take an SMB1 packet and sign it. This version is an instance method that accesses the necessary values from the object instance.



14
15
16
17
18
19
# File 'lib/ruby_smb/signing.rb', line 14

def smb1_sign(packet)
  packet = Signing::smb1_sign(packet, @session_key, @sequence_counter)
  @sequence_counter += 1

  packet
end

#smb2_sign(packet) ⇒ RubySMB::GenericPacket

Take an SMB2 packet and sign it. This version is an instance method that accesses the necessary values from the object instance.



43
44
45
# File 'lib/ruby_smb/signing.rb', line 43

def smb2_sign(packet)
  Signing::smb2_sign(packet, @session_key)
end

#smb3_sign(packet) ⇒ RubySMB::GenericPacket

Take an SMB3 packet and sign it. This version is an instance method that accesses the necessary values from the object instance.



69
70
71
# File 'lib/ruby_smb/signing.rb', line 69

def smb3_sign(packet)
  Signing::smb3_sign(packet, @session_key, @dialect, @preauth_integrity_hash_value)
end