Class: RBus::Auth::StateMachine

Inherits:
Object
  • Object
show all
Defined in:
lib/rbus/auth/state_machine.rb

Overview

Implements a statemachine for Authorization like the one described in the D-Bus specification.

Instance Method Summary collapse

Constructor Details

#initialize(transport) ⇒ StateMachine

Returns a new instance of StateMachine.



30
31
32
33
# File 'lib/rbus/auth/state_machine.rb', line 30

def initialize(transport)
  @transport = transport
  @mechanism = FIRST_MECHANISM.new
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(symbol, *args) ⇒ Object

send_begin => BEGIN, etc



139
140
141
142
143
144
145
# File 'lib/rbus/auth/state_machine.rb', line 139

def method_missing(symbol, *args)
  command = symbol.to_s
  if command.sub!('send_', '')
    line = [command.upcase, hex_encode(args[0])].compact.join(' ')
    @transport.sendline(line)          
  end
end

Instance Method Details

#authorizeObject

Main entry point, returns guid if succesful, or raises otherwise.



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/rbus/auth/state_machine.rb', line 36

def authorize        
  state = :AUTH
  
  loop do
    case state
      when :AUTH
        command, data, state = @mechanism.auth
        send_auth(command, data)
        
      when :REJECTED
        response = Command.new(@transport.readline)
        case response.command
          when 'REJECTED'
            next_mechanism(response.data)
            state = :AUTH
          else
            raise AuthException
        end 

      when :OK
        response = Command.new(@transport.readline)
        case response.command
          when 'OK'
            send_begin
            return response.data
          when 'REJECTED'
            next_mechanism(response.data)
            state = :AUTH
          when 'DATA'
            send_cancel
            state = :REJECTED
          when 'ERROR'
            send_cancel
            state = :REJECTED
          else
            send_error
            state = :OK
        end

      when :DATA
        response = Command.new(@transport.readline)
        case response.command
          when 'DATA'
            begin
              message, state = @mechanism.data(response.data)
            rescue AuthException => e
              send_cancel
              state = :REJECTED
            else
              send_data(message)
            end
          when 'REJECTED'
            next_mechanism(response.data)
            state = :AUTH
          when 'ERROR'
            send_cancel
            state = :REJECTED
          when 'OK'
            send_begin
            return response.data
          else
            send_error
            state = :DATA
        end
      else
        raise
    end
  end
end

#hex_encode(plain) ⇒ Object

Server expects all data to be encoded in hex



148
149
150
151
# File 'lib/rbus/auth/state_machine.rb', line 148

def hex_encode(plain)
  return nil if plain.nil?
  plain.to_s.unpack('H*')[0]
end

#next_mechanism(data) ⇒ Object

Move to next mechanism



107
108
109
110
111
112
113
114
115
116
# File 'lib/rbus/auth/state_machine.rb', line 107

def next_mechanism(data)
  if @mechanisms.nil?
    populate_mechanisms(data)
  end
  if @mechanisms.empty?
    raise AuthException
  else
    @mechanism = @mechanisms.shift.new
  end
end

#populate_mechanisms(data) ⇒ Object

Build initial mechanism list



119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/rbus/auth/state_machine.rb', line 119

def populate_mechanisms(data)
  server_mechanisms = data.split(' ')
  
  # Find common mechanisms, or try them all if server didn't tell us
  if server_mechanisms.empty?
    mechanisms = MECHANISMS.keys
  else
    mechanisms = (server_mechanisms & MECHANISMS.keys)
  end
  
  @mechanisms = mechanisms.map{|name| MECHANISMS[name]}
end

#send_auth(command, data) ⇒ Object

Send AUTH …



133
134
135
136
# File 'lib/rbus/auth/state_machine.rb', line 133

def send_auth(command, data)
  line = ['AUTH', command, hex_encode(data)].compact.join(' ')
  @transport.sendline(line)
end