class DBus::Client

Authentication client class.

Class tha performs the actional authentication.

Public Class Methods

new(socket) click to toggle source

Create a new authentication client.

# File lib/dbus/auth.rb, line 120
def initialize(socket)
  @socket = socket
  @state = nil
  @auth_list = [External,DBusCookieSHA1,Anonymous]
end

Public Instance Methods

authenticate() click to toggle source

Start the authentication process.

# File lib/dbus/auth.rb, line 127
def authenticate
  if (RbConfig::CONFIG["target_os"] =~ /freebsd/)
    @socket.sendmsg(0.chr, 0, nil, [:SOCKET, :SCM_CREDS, ""])
  else
    @socket.write(0.chr)
  end
  next_authenticator
  @state = :Starting
  while @state != :Authenticated
    r = next_state
    return r if not r
  end
  true
end

Private Instance Methods

next_authenticator() click to toggle source

Try authentication using the next authenticator.

# File lib/dbus/auth.rb, line 154
def next_authenticator
  begin
    raise AuthenticationFailed if @auth_list.size == 0
    @authenticator = @auth_list.shift.new
    auth_msg = ["AUTH", @authenticator.name, @authenticator.authenticate]
    DBus.logger.debug "auth_msg: #{auth_msg.inspect}"
    send(auth_msg)
  rescue AuthenticationFailed
    @socket.close
    raise
  end
end
next_msg() click to toggle source

Read data (a buffer) from the bus until CR LF is encountered. Return the buffer without the CR LF characters.

# File lib/dbus/auth.rb, line 169
def next_msg
  data,crlf = "","\r\n"
  left = 1024 #1024 byte, no idea if it's ever getting bigger
  while left > 0
    buf = @socket.read( left > 1 ? 1 : left )
    break if buf.nil?
    left -= buf.bytesize
    data += buf
    break if data.include? crlf #crlf means line finished, the TCP socket keeps on listening, so we break 
  end
  readline = data.chomp.split(" ")
  DBus.logger.debug "readline: #{readline.inspect}"
  return readline
end
next_state() click to toggle source
# Read data (a buffer) from the bus until CR LF is encountered.
# Return the buffer without the CR LF characters.
def next_msg
  @socket.readline.chomp.split(" ")
end

# Try to reach the next state based on the current state.

# File lib/dbus/auth.rb, line 193
def next_state
  msg = next_msg
  if @state == :Starting
    DBus.logger.debug ":Starting msg: #{msg[0].inspect}"
    case msg[0]
    when "OK"
      @state = :WaitingForOk    
    when "CONTINUE"
      @state = :WaitingForData
    when "REJECTED" #needed by tcp, unix-path/abstract doesn't get here
      @state = :WaitingForData
    end
  end
  DBus.logger.debug "state: #{@state}"
  case @state
  when :WaitingForData
    DBus.logger.debug ":WaitingForData msg: #{msg[0].inspect}"
    case msg[0]
    when "DATA"
      chall = msg[1]
      resp, chall = @authenticator.data(chall)
      DBus.logger.debug ":WaitingForData/DATA resp: #{resp.inspect}"
      case resp
      when :AuthContinue
        send("DATA", chall)
        @state = :WaitingForData
      when :AuthOk
        send("DATA", chall)
        @state = :WaitingForOk
      when :AuthError
        send("ERROR")
        @state = :WaitingForData
      end
    when "REJECTED"
      next_authenticator
      @state = :WaitingForData
    when "ERROR"
      send("CANCEL")
      @state = :WaitingForReject
    when "OK"
      send("BEGIN")
      @state = :Authenticated
    else
      send("ERROR")
      @state = :WaitingForData
    end
  when :WaitingForOk
    DBus.logger.debug ":WaitingForOk msg: #{msg[0].inspect}"
    case msg[0]
    when "OK"
      send("BEGIN")
      @state = :Authenticated
    when "REJECT"
      next_authenticator
      @state = :WaitingForData
    when "DATA", "ERROR"
      send("CANCEL")
      @state = :WaitingForReject
    else
      send("ERROR")
      @state = :WaitingForOk
    end
  when :WaitingForReject
    DBus.logger.debug ":WaitingForReject msg: #{msg[0].inspect}"
    case msg[0]
    when "REJECT"
      next_authenticator
      @state = :WaitingForOk
    else
      @socket.close
      return false
    end
  end
  return true
end
send(meth, *args) click to toggle source

Send an authentication method meth with arguments args to the server.

# File lib/dbus/auth.rb, line 148
def send(meth, *args)
  o = ([meth] + args).join(" ")
  @socket.write(o + "\r\n")
end