ruby-dbus-openplacos 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/COPYING +504 -0
- data/NEWS +146 -0
- data/README +42 -0
- data/Rakefile +54 -0
- data/VERSION +1 -0
- data/doc/tutorial/index.markdown +480 -0
- data/examples/gdbus/gdbus +255 -0
- data/examples/gdbus/gdbus.glade +184 -0
- data/examples/gdbus/launch.sh +4 -0
- data/examples/no-introspect/nm-test.rb +21 -0
- data/examples/no-introspect/tracker-test.rb +16 -0
- data/examples/rhythmbox/playpause.rb +25 -0
- data/examples/service/call_service.rb +25 -0
- data/examples/service/service_newapi.rb +51 -0
- data/examples/simple/call_introspect.rb +34 -0
- data/examples/simple/properties.rb +19 -0
- data/examples/utils/listnames.rb +11 -0
- data/examples/utils/notify.rb +19 -0
- data/lib/dbus/auth.rb +258 -0
- data/lib/dbus/bus.rb +947 -0
- data/lib/dbus/core_ext/class/attribute.rb +91 -0
- data/lib/dbus/core_ext/kernel/singleton_class.rb +14 -0
- data/lib/dbus/core_ext/module/remove_method.rb +12 -0
- data/lib/dbus/error.rb +44 -0
- data/lib/dbus/export.rb +124 -0
- data/lib/dbus/introspect.rb +570 -0
- data/lib/dbus/marshall.rb +443 -0
- data/lib/dbus/matchrule.rb +100 -0
- data/lib/dbus/message.rb +310 -0
- data/lib/dbus/type.rb +222 -0
- data/lib/dbus.rb +83 -0
- data/ruby-dbus-openplacos.gemspec +17 -0
- data/test/binding_test.rb +56 -0
- data/test/bus_driver_test.rb +22 -0
- data/test/dbus-launch-simple +35 -0
- data/test/dbus-limited-session.conf +28 -0
- data/test/property_test.rb +55 -0
- data/test/server_robustness_test.rb +72 -0
- data/test/server_test.rb +53 -0
- data/test/service_newapi.rb +197 -0
- data/test/session_bus_test_manual.rb +20 -0
- data/test/signal_test.rb +64 -0
- data/test/t1 +4 -0
- data/test/t2.rb +66 -0
- data/test/t3-ticket27.rb +18 -0
- data/test/t5-report-dbus-interface.rb +58 -0
- data/test/t6-loop.rb +82 -0
- data/test/test_env +13 -0
- data/test/test_server +39 -0
- data/test/variant_test.rb +66 -0
- metadata +118 -0
data/lib/dbus/auth.rb
ADDED
@@ -0,0 +1,258 @@
|
|
1
|
+
# This file is part of the ruby-dbus project
|
2
|
+
# Copyright (C) 2007 Arnaud Cornet and Paul van Tilburg
|
3
|
+
#
|
4
|
+
# This library is free software; you can redistribute it and/or
|
5
|
+
# modify it under the terms of the GNU Lesser General Public
|
6
|
+
# License, version 2.1 as published by the Free Software Foundation.
|
7
|
+
# See the file "COPYING" for the exact licensing terms.
|
8
|
+
|
9
|
+
$debug = $DEBUG #it's all over the state machine
|
10
|
+
|
11
|
+
module DBus
|
12
|
+
# Exception raised when authentication fails somehow.
|
13
|
+
class AuthenticationFailed < Exception
|
14
|
+
end
|
15
|
+
|
16
|
+
# = General class for authentication.
|
17
|
+
class Authenticator
|
18
|
+
# Returns the name of the authenticator.
|
19
|
+
def name
|
20
|
+
self.class.to_s.upcase.sub(/.*::/, "")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# = External authentication class
|
25
|
+
#
|
26
|
+
# Class for 'external' type authentication.
|
27
|
+
class External < Authenticator
|
28
|
+
# Performs the authentication.
|
29
|
+
def authenticate
|
30
|
+
# Take the user id (eg integer 1000) make a string out of it "1000", take
|
31
|
+
# each character and determin hex value "1" => 0x31, "0" => 0x30. You
|
32
|
+
# obtain for "1000" => 31303030 This is what the server is expecting.
|
33
|
+
# Why? I dunno. How did I come to that conclusion? by looking at rbus
|
34
|
+
# code. I have no idea how he found that out.
|
35
|
+
return Process.uid.to_s.split(//).collect { |a| "%x" % a[0].ord }.join
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# = Authentication class using SHA1 crypto algorithm
|
40
|
+
#
|
41
|
+
# Class for 'CookieSHA1' type authentication.
|
42
|
+
# Implements the AUTH DBUS_COOKIE_SHA1 mechanism.
|
43
|
+
class DBusCookieSHA1 < Authenticator
|
44
|
+
|
45
|
+
#the autenticate method (called in stage one of authentification)
|
46
|
+
def authenticate
|
47
|
+
require 'etc'
|
48
|
+
#number of retries we have for auth
|
49
|
+
@retries = 1
|
50
|
+
return "#{hex_encode(Etc.getlogin)}" #server expects it to be binary
|
51
|
+
end
|
52
|
+
|
53
|
+
#returns the modules name
|
54
|
+
def name
|
55
|
+
return 'DBUS_COOKIE_SHA1'
|
56
|
+
end
|
57
|
+
|
58
|
+
#handles the interesting crypto stuff, check the rbus-project for more info: http://rbus.rubyforge.org/
|
59
|
+
def data(hexdata)
|
60
|
+
require 'digest/sha1'
|
61
|
+
data = hex_decode(hexdata)
|
62
|
+
# name of cookie file, id of cookie in file, servers random challenge
|
63
|
+
context, id, s_challenge = data.split(' ')
|
64
|
+
# Random client challenge
|
65
|
+
c_challenge = Array.new(s_challenge.length/2).map{|obj|obj=rand(255).to_s}.join
|
66
|
+
# Search cookie file for id
|
67
|
+
path = File.join(ENV['HOME'], '.dbus-keyrings', context)
|
68
|
+
puts "DEBUG: path: #{path.inspect}" if $debug
|
69
|
+
File.foreach(path) do |line|
|
70
|
+
if line.index(id) == 0
|
71
|
+
# Right line of file, read cookie
|
72
|
+
cookie = line.split(' ')[2].chomp
|
73
|
+
puts "DEBUG: cookie: #{cookie.inspect}" if $debug
|
74
|
+
# Concatenate and encrypt
|
75
|
+
to_encrypt = [s_challenge, c_challenge, cookie].join(':')
|
76
|
+
sha = Digest::SHA1.hexdigest(to_encrypt)
|
77
|
+
#the almighty tcp server wants everything hex encoded
|
78
|
+
hex_response = hex_encode("#{c_challenge} #{sha}")
|
79
|
+
# Return response
|
80
|
+
response = [:AuthOk, hex_response]
|
81
|
+
return response
|
82
|
+
end
|
83
|
+
end
|
84
|
+
#a little rescue magic
|
85
|
+
unless @retries <= 0
|
86
|
+
puts "ERROR: Could not auth, will now exit."
|
87
|
+
puts "ERROR: Unable to locate cookie, retry in 1 second."
|
88
|
+
@retries -= 1
|
89
|
+
sleep 1
|
90
|
+
data(hexdata)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# encode plain to hex
|
95
|
+
def hex_encode(plain)
|
96
|
+
return nil if plain.nil?
|
97
|
+
plain.to_s.unpack('H*')[0]
|
98
|
+
end
|
99
|
+
|
100
|
+
# decode hex to plain
|
101
|
+
def hex_decode(encoded)
|
102
|
+
encoded.scan(/[[:xdigit:]]{2}/).map{|h|h.hex.chr}.join
|
103
|
+
end
|
104
|
+
end #DBusCookieSHA1 class ends here
|
105
|
+
|
106
|
+
# Note: this following stuff is tested with External authenticator only!
|
107
|
+
|
108
|
+
# = Authentication client class.
|
109
|
+
#
|
110
|
+
# Class tha performs the actional authentication.
|
111
|
+
class Client
|
112
|
+
# Create a new authentication client.
|
113
|
+
def initialize(socket)
|
114
|
+
@socket = socket
|
115
|
+
@state = nil
|
116
|
+
@auth_list = [External,DBusCookieSHA1]
|
117
|
+
end
|
118
|
+
|
119
|
+
# Start the authentication process.
|
120
|
+
def authenticate
|
121
|
+
@socket.write(0.chr)
|
122
|
+
next_authenticator
|
123
|
+
@state = :Starting
|
124
|
+
while @state != :Authenticated
|
125
|
+
r = next_state
|
126
|
+
return r if not r
|
127
|
+
end
|
128
|
+
true
|
129
|
+
end
|
130
|
+
|
131
|
+
##########
|
132
|
+
private
|
133
|
+
##########
|
134
|
+
|
135
|
+
# Send an authentication method _meth_ with arguments _args_ to the
|
136
|
+
# server.
|
137
|
+
def send(meth, *args)
|
138
|
+
o = ([meth] + args).join(" ")
|
139
|
+
@socket.write(o + "\r\n")
|
140
|
+
end
|
141
|
+
|
142
|
+
# Try authentication using the next authenticator.
|
143
|
+
def next_authenticator
|
144
|
+
begin
|
145
|
+
raise AuthException if @auth_list.size == 0
|
146
|
+
@authenticator = @auth_list.shift.new
|
147
|
+
auth_msg = ["AUTH", @authenticator.name, @authenticator.authenticate]
|
148
|
+
puts "DEBUG: auth_msg: #{auth_msg.inspect}" if $debug
|
149
|
+
send(auth_msg)
|
150
|
+
rescue AuthException
|
151
|
+
@socket.close
|
152
|
+
raise
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# Read data (a buffer) from the bus until CR LF is encountered.
|
157
|
+
# Return the buffer without the CR LF characters.
|
158
|
+
def next_msg
|
159
|
+
data,crlf = "","\r\n"
|
160
|
+
left = 1024 #1024 byte, no idea if it's ever getting bigger
|
161
|
+
while left > 0
|
162
|
+
buf = @socket.read( left > 1 ? 1 : left )
|
163
|
+
break if buf.nil?
|
164
|
+
left -= buf.size
|
165
|
+
data += buf
|
166
|
+
break if data.include? crlf #crlf means line finished, the TCP socket keeps on listening, so we break
|
167
|
+
end
|
168
|
+
readline = data.chomp.split(" ")
|
169
|
+
puts "DEBUG: readline: #{readline.inspect}" if $debug
|
170
|
+
return readline
|
171
|
+
end
|
172
|
+
|
173
|
+
=begin
|
174
|
+
# Read data (a buffer) from the bus until CR LF is encountered.
|
175
|
+
# Return the buffer without the CR LF characters.
|
176
|
+
def next_msg
|
177
|
+
@socket.readline.chomp.split(" ")
|
178
|
+
end
|
179
|
+
=end
|
180
|
+
|
181
|
+
# Try to reach the next state based on the current state.
|
182
|
+
def next_state
|
183
|
+
msg = next_msg
|
184
|
+
if @state == :Starting
|
185
|
+
puts "DEBUG: :Starting msg: #{msg[0].inspect}" if $debug
|
186
|
+
case msg[0]
|
187
|
+
when "OK"
|
188
|
+
@state = :WaitingForOk
|
189
|
+
when "CONTINUE"
|
190
|
+
@state = :WaitingForData
|
191
|
+
when "REJECTED" #needed by tcp, unix-path/abstract doesn't get here
|
192
|
+
@state = :WaitingForData
|
193
|
+
end
|
194
|
+
end
|
195
|
+
puts "DEBUG: state: #{@state}" if $debug
|
196
|
+
case @state
|
197
|
+
when :WaitingForData
|
198
|
+
puts "DEBUG: :WaitingForData msg: #{msg[0].inspect}" if $debug
|
199
|
+
case msg[0]
|
200
|
+
when "DATA"
|
201
|
+
chall = msg[1]
|
202
|
+
resp, chall = @authenticator.data(chall)
|
203
|
+
puts "DEBUG: :WaitingForData/DATA resp: #{resp.inspect}" if $debug
|
204
|
+
case resp
|
205
|
+
when :AuthContinue
|
206
|
+
send("DATA", chall)
|
207
|
+
@state = :WaitingForData
|
208
|
+
when :AuthOk
|
209
|
+
send("DATA", chall)
|
210
|
+
@state = :WaitingForOk
|
211
|
+
when :AuthError
|
212
|
+
send("ERROR")
|
213
|
+
@state = :WaitingForData
|
214
|
+
end
|
215
|
+
when "REJECTED"
|
216
|
+
next_authenticator
|
217
|
+
@state = :WaitingForData
|
218
|
+
when "ERROR"
|
219
|
+
send("CANCEL")
|
220
|
+
@state = :WaitingForReject
|
221
|
+
when "OK"
|
222
|
+
send("BEGIN")
|
223
|
+
@state = :Authenticated
|
224
|
+
else
|
225
|
+
send("ERROR")
|
226
|
+
@state = :WaitingForData
|
227
|
+
end
|
228
|
+
when :WaitingForOk
|
229
|
+
puts "DEBUG: :WaitingForOk msg: #{msg[0].inspect}" if $debug
|
230
|
+
case msg[0]
|
231
|
+
when "OK"
|
232
|
+
send("BEGIN")
|
233
|
+
@state = :Authenticated
|
234
|
+
when "REJECT"
|
235
|
+
next_authenticator
|
236
|
+
@state = :WaitingForData
|
237
|
+
when "DATA", "ERROR"
|
238
|
+
send("CANCEL")
|
239
|
+
@state = :WaitingForReject
|
240
|
+
else
|
241
|
+
send("ERROR")
|
242
|
+
@state = :WaitingForOk
|
243
|
+
end
|
244
|
+
when :WaitingForReject
|
245
|
+
puts "DEBUG: :WaitingForReject msg: #{msg[0].inspect}" if $debug
|
246
|
+
case msg[0]
|
247
|
+
when "REJECT"
|
248
|
+
next_authenticator
|
249
|
+
@state = :WaitingForOk
|
250
|
+
else
|
251
|
+
@socket.close
|
252
|
+
return false
|
253
|
+
end
|
254
|
+
end
|
255
|
+
return true
|
256
|
+
end # def next_state
|
257
|
+
end # class Client
|
258
|
+
end # module D-Bus
|