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

Returns:

  • (String)


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.

Parameters:

  • packet (RubySMB::GenericPacket)

    The packet to sign.

  • session_key (String)

    The key to use for signing.

  • sequence_counter (Integer)

    The sequence counter of packet to be sent.

Returns:



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.

Parameters:

  • packet (RubySMB::GenericPacket)

    The packet to sign.

  • session_key (String)

    The key to use for signing.

Returns:



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.

Parameters:

  • packet (RubySMB::GenericPacket)

    The packet to sign.

  • session_key (String)

    The key to use for signing.

  • dialect (String)

    The SMB3 dialect to sign for.

  • preauth_integrity_hash (String) (defaults to: nil)

    The preauth integrity hash as required by the 3.1.1 dialect.

Returns:



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.

Parameters:

Returns:



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.

Parameters:

Returns:



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.

Parameters:

Returns:



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