Class: Protocol::ZMTP::Mechanism::Plain

Inherits:
Object
  • Object
show all
Defined in:
lib/protocol/zmtp/mechanism/plain.rb

Overview

PLAIN security mechanism — username/password authentication, no encryption.

Implements the ZMTP PLAIN handshake (RFC 24):

client → server:  HELLO    (username + password)
server → client:  WELCOME  (empty, credentials accepted)
client → server:  INITIATE (socket metadata)
server → client:  READY    (socket metadata)

Constant Summary collapse

MECHANISM_NAME =
"PLAIN"

Instance Method Summary collapse

Constructor Details

#initialize(username: "", password: "", authenticator: nil) ⇒ Plain

Returns a new instance of Plain.

Parameters:

  • username (String) (defaults to: "")

    client username (max 255 bytes)

  • password (String) (defaults to: "")

    client password (max 255 bytes)

  • authenticator (#call, nil) (defaults to: nil)

    server-side credential verifier; called as authenticator.call(username, password) and must return truthy to accept the connection. When nil, all credentials pass.



24
25
26
27
28
# File 'lib/protocol/zmtp/mechanism/plain.rb', line 24

def initialize(username: "", password: "", authenticator: nil)
  @username      = username
  @password      = password
  @authenticator = authenticator
end

Instance Method Details

#encrypted?Boolean

Returns false — PLAIN does not encrypt frames.

Returns:

  • (Boolean)

    false — PLAIN does not encrypt frames



59
60
61
# File 'lib/protocol/zmtp/mechanism/plain.rb', line 59

def encrypted?
  false
end

#handshake!(io, as_server:, socket_type:, identity:, metadata: nil) ⇒ Hash

Performs the full PLAIN handshake over io.

Parameters:

  • io (#read_exactly, #write, #flush)

    transport IO

  • as_server (Boolean)
  • socket_type (String)
  • identity (String)
  • metadata (Hash{String => String}, nil) (defaults to: nil)

    extra READY properties

Returns:

  • (Hash)

    { peer_socket_type:, peer_identity:, peer_properties: }

Raises:



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/protocol/zmtp/mechanism/plain.rb', line 40

def handshake!(io, as_server:, socket_type:, identity:, metadata: nil)
  io.write(Codec::Greeting.encode(mechanism: MECHANISM_NAME, as_server: as_server))
  io.flush

  peer_greeting = Codec::Greeting.read_from(io)

  unless peer_greeting[:mechanism] == MECHANISM_NAME
    raise Error, "unsupported mechanism: #{peer_greeting[:mechanism]}"
  end

  if as_server
    server_handshake! io, socket_type: socket_type, identity: identity, metadata: 
  else
    client_handshake! io, socket_type: socket_type, identity: identity, metadata: 
  end
end