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.
Files changed (51) hide show
  1. data/COPYING +504 -0
  2. data/NEWS +146 -0
  3. data/README +42 -0
  4. data/Rakefile +54 -0
  5. data/VERSION +1 -0
  6. data/doc/tutorial/index.markdown +480 -0
  7. data/examples/gdbus/gdbus +255 -0
  8. data/examples/gdbus/gdbus.glade +184 -0
  9. data/examples/gdbus/launch.sh +4 -0
  10. data/examples/no-introspect/nm-test.rb +21 -0
  11. data/examples/no-introspect/tracker-test.rb +16 -0
  12. data/examples/rhythmbox/playpause.rb +25 -0
  13. data/examples/service/call_service.rb +25 -0
  14. data/examples/service/service_newapi.rb +51 -0
  15. data/examples/simple/call_introspect.rb +34 -0
  16. data/examples/simple/properties.rb +19 -0
  17. data/examples/utils/listnames.rb +11 -0
  18. data/examples/utils/notify.rb +19 -0
  19. data/lib/dbus/auth.rb +258 -0
  20. data/lib/dbus/bus.rb +947 -0
  21. data/lib/dbus/core_ext/class/attribute.rb +91 -0
  22. data/lib/dbus/core_ext/kernel/singleton_class.rb +14 -0
  23. data/lib/dbus/core_ext/module/remove_method.rb +12 -0
  24. data/lib/dbus/error.rb +44 -0
  25. data/lib/dbus/export.rb +124 -0
  26. data/lib/dbus/introspect.rb +570 -0
  27. data/lib/dbus/marshall.rb +443 -0
  28. data/lib/dbus/matchrule.rb +100 -0
  29. data/lib/dbus/message.rb +310 -0
  30. data/lib/dbus/type.rb +222 -0
  31. data/lib/dbus.rb +83 -0
  32. data/ruby-dbus-openplacos.gemspec +17 -0
  33. data/test/binding_test.rb +56 -0
  34. data/test/bus_driver_test.rb +22 -0
  35. data/test/dbus-launch-simple +35 -0
  36. data/test/dbus-limited-session.conf +28 -0
  37. data/test/property_test.rb +55 -0
  38. data/test/server_robustness_test.rb +72 -0
  39. data/test/server_test.rb +53 -0
  40. data/test/service_newapi.rb +197 -0
  41. data/test/session_bus_test_manual.rb +20 -0
  42. data/test/signal_test.rb +64 -0
  43. data/test/t1 +4 -0
  44. data/test/t2.rb +66 -0
  45. data/test/t3-ticket27.rb +18 -0
  46. data/test/t5-report-dbus-interface.rb +58 -0
  47. data/test/t6-loop.rb +82 -0
  48. data/test/test_env +13 -0
  49. data/test/test_server +39 -0
  50. data/test/variant_test.rb +66 -0
  51. 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