WiKID 3.0.2 → 3.2.3
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.
- checksums.yaml +15 -0
- data/doc/README +1 -1
- data/lib/WiKID.rb +841 -591
- data/lib/WiKID_version.rb +5 -0
- data/share/data/WiKID-ca.pem +39 -0
- data/test-options-dist.rb +10 -0
- data/test/ts_load_wikid.rb +21 -0
- data/test/ts_wikid.rb +187 -33
- metadata +67 -42
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
ZWU4YjE2MzE5NmE3YmUyY2M0MWMyMWVlMjIwODcwOTBhN2FjZTA1NA==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
OWI0MzkwZWJkY2E1NWNkMDM1OGY2ZTBiMDBkMTI3YWQ2ODRjOWQxMg==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
OTIxMGE5ZmI1NDAyZWM4MDBmMDU0NGY2ZjZhMDBiYjQ5MThlOGM2OTNmNzUz
|
10
|
+
ZmIwNTdiYWVlNDBiNmEzZjkwZDgzZDZjOGJhNzRlNjczMjVjMjJjYjI1ODFm
|
11
|
+
NWZiYmI3ZmJlNGZlNzYzZWQ1NmVhYTkzNzUwOWZiODhlYWRmMGI=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
ZmU0ODBhNjUzMTU4NDllMWYwNmVlYTg5ODJhMzFjMDA3N2U5Yjk2MmU1MWM0
|
14
|
+
MWM1MGFlNTBmNTkyYmUyNmE3OTU4ZTdkYTZjOWYzMjAyZjA5ZWRkZDU1Mzcw
|
15
|
+
MmRkNjM1NDhlYzZjMjc3Zjc5NzE4YWJlMDAyODZhY2YzYjhlMWE=
|
data/doc/README
CHANGED
@@ -46,7 +46,7 @@ NETWORK CLIENT SETUP
|
|
46
46
|
Every WiKID network client needs a certificate from the WiKID server to talk
|
47
47
|
via SSL with the WiKID server. Create a network client on the WiKID server for
|
48
48
|
your Ruby network client and download the network client PKCS12 certificate to
|
49
|
-
your Ruby server.
|
49
|
+
your Ruby server (accessible from the Network Client menu in the admin).
|
50
50
|
|
51
51
|
To extract it from the .p12 file for use by Ruby, run:
|
52
52
|
|
data/lib/WiKID.rb
CHANGED
@@ -1,591 +1,841 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
=end
|
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
|
-
either a properties file or via explicit arguments.
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
=
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
"
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
=begin rdoc
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
=end
|
285
|
-
def reconnect()
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
# Options:
|
298
|
-
# "cert", "key", "client_ca", "ca_file", "ca_path",
|
299
|
-
# "timeout", "verify_mode", "verify_depth",
|
300
|
-
# "verify_callback", "options", "cert_store", "extra_chain_cert"
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
@
|
371
|
-
|
372
|
-
|
373
|
-
=
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
</
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
=
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
## vim: set expandtab tabstop=2 shiftwidth=2 softtabstop=2: :nodoc:
|
4
|
+
|
5
|
+
# @author WiKID Systems, Inc {info@wikidsystems.com}[mailto:info@wikidsystems.com]
|
6
|
+
# @author Twitter Handle: {@wikidsystems}[https://twitter.com/wikidsystems]
|
7
|
+
module WiKID
|
8
|
+
|
9
|
+
|
10
|
+
=begin rdoc
|
11
|
+
|
12
|
+
== Title
|
13
|
+
|
14
|
+
WiKID Strong Authentication module for Ruby
|
15
|
+
|
16
|
+
http://sourceforge.net/projects/wikid-twofactor/
|
17
|
+
|
18
|
+
== Synopsis
|
19
|
+
|
20
|
+
This is the core SSL client for WiKID Authentication. Auth_WiKID manages
|
21
|
+
communication between Network Clients (NC) and the WiKID Authentication
|
22
|
+
Server (wAuth).
|
23
|
+
|
24
|
+
== License
|
25
|
+
Lesser GNU Public License
|
26
|
+
|
27
|
+
This library is free software; you can redistribute it and/or
|
28
|
+
modify it under the terms of the GNU Lesser General Public
|
29
|
+
License as published by the Free Software Foundation; either
|
30
|
+
version 2.1 of the License, or (at your option) any later version.
|
31
|
+
|
32
|
+
This library is distributed in the hope that it will be useful,
|
33
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
34
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
35
|
+
Lesser General Public License for more details.
|
36
|
+
|
37
|
+
You should have received a copy of the GNU Lesser General Public
|
38
|
+
License along with this library; if not, write to the Free Software
|
39
|
+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
40
|
+
|
41
|
+
== Author
|
42
|
+
Greg Haygood <ghaygood@wikidsystems.com>
|
43
|
+
|
44
|
+
== Copyright
|
45
|
+
Copyright (c) 2001-2015 WiKID Systems, Inc. All rights reserved.
|
46
|
+
|
47
|
+
=end
|
48
|
+
|
49
|
+
## Not necessarily true, but only tested with 1.8.x
|
50
|
+
raise "Please, use ruby 1.8.0 or later." if RUBY_VERSION < "1.8.0"
|
51
|
+
|
52
|
+
require 'socket'
|
53
|
+
require 'rexml/document'
|
54
|
+
include REXML
|
55
|
+
|
56
|
+
SSLEnabled = begin
|
57
|
+
require 'openssl'
|
58
|
+
true
|
59
|
+
rescue LoadError
|
60
|
+
false
|
61
|
+
end
|
62
|
+
private_constant :SSLEnabled
|
63
|
+
|
64
|
+
class Auth
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
=begin rdoc
|
69
|
+
|
70
|
+
Idle time to allow before closing socket, and time limit on socket
|
71
|
+
* open attempt
|
72
|
+
|
73
|
+
=end
|
74
|
+
@@timeout = 30
|
75
|
+
|
76
|
+
=begin rdoc
|
77
|
+
|
78
|
+
Controls whether debug messages will be printed
|
79
|
+
|
80
|
+
=end
|
81
|
+
@@DEBUG = false
|
82
|
+
|
83
|
+
@@DEFAULT_CA_FILE = File.expand_path(File.join(File.dirname(__FILE__), '..', 'share', 'data', 'WiKID-ca.pem'))
|
84
|
+
|
85
|
+
public
|
86
|
+
|
87
|
+
=begin rdoc
|
88
|
+
|
89
|
+
This constructor allows the Auth_WiKID module to be initialized from either a properties file or via explicit arguments.
|
90
|
+
|
91
|
+
@param [string] host_or_file Either the IP address or hostname of
|
92
|
+
the wAuth server, or the path to a
|
93
|
+
properties file
|
94
|
+
@param [int] port The SSL listener port for the wAuth
|
95
|
+
daemon on the wAuth server
|
96
|
+
@param [string] keyfile The PKCS12 keystore generated for this
|
97
|
+
client by the wAuth server
|
98
|
+
@param [string] keypass The passphrase securing the keys in keyfile
|
99
|
+
@param [string] cafile The certificate authority store for
|
100
|
+
validating the wAuth server certificate
|
101
|
+
|
102
|
+
The contents of the properties file should contain the following key-value pairs:
|
103
|
+
* host - The IP address or hostname of the wAuth server
|
104
|
+
* port - The SSL listener port for the wAuth daemon on the wAuth server
|
105
|
+
* keyfile - The PKCS12 keystore generated for client by the wAuth server
|
106
|
+
* pass - The passphrase securing the keys in keyfile
|
107
|
+
* cafile - The PEM-encoded certificate file for validating the wAuth server certificate
|
108
|
+
|
109
|
+
=end
|
110
|
+
def initialize(host_or_file, port, keyfile, keypass, cafile = @@DEFAULT_CA_FILE)
|
111
|
+
|
112
|
+
unless SSLEnabled
|
113
|
+
raise RuntimeError.new('Ruby/OpenSSL module is required for WiKID authentication.')
|
114
|
+
end
|
115
|
+
|
116
|
+
if (File.exist?(host_or_file))
|
117
|
+
# props = parse_ini_file(host_or_file)
|
118
|
+
props = Hash.new
|
119
|
+
|
120
|
+
@host = props['host']
|
121
|
+
@port = props['port']
|
122
|
+
@keyfile = props['keyfile']
|
123
|
+
@keypass = props['pass']
|
124
|
+
@cafile = props['cafile']
|
125
|
+
else
|
126
|
+
@host = host_or_file.untaint
|
127
|
+
@port = port.untaint
|
128
|
+
@keyfile = keyfile.untaint
|
129
|
+
@keypass = keypass.untaint
|
130
|
+
unless cafile.nil? || cafile.empty?
|
131
|
+
@cafile = cafile.untaint
|
132
|
+
end
|
133
|
+
end
|
134
|
+
if (!@port.is_a?(Integer))
|
135
|
+
@port = 0
|
136
|
+
end
|
137
|
+
|
138
|
+
_dprint("WiKID.rb initialized: host=#{@host}, port=#{@port}, keyfile=#{@keyfile}, cafile=#{@cafile}")
|
139
|
+
|
140
|
+
## simple hack to allow for testing during gem installation (prevents security errors since keys may not yet be available)
|
141
|
+
unless port == -1
|
142
|
+
checkKeys()
|
143
|
+
end
|
144
|
+
|
145
|
+
return true
|
146
|
+
end
|
147
|
+
|
148
|
+
# @note Class destructor, which just calls close().
|
149
|
+
# @api private
|
150
|
+
def _WiKID()
|
151
|
+
close()
|
152
|
+
end
|
153
|
+
private :_WiKID
|
154
|
+
|
155
|
+
=begin rdoc
|
156
|
+
|
157
|
+
This method simply closes the connection to the wAuth service.
|
158
|
+
|
159
|
+
=end
|
160
|
+
def close()
|
161
|
+
_dprint('Closing Auth_WiKID connection ...')
|
162
|
+
unless $sslsocket.nil?
|
163
|
+
unless $sslsocket.closed?
|
164
|
+
$sslsocket.puts('QUIT');
|
165
|
+
$sslsocket.flush
|
166
|
+
$sslsocket.close
|
167
|
+
end
|
168
|
+
$sslsocket = nil
|
169
|
+
@socket.shutdown
|
170
|
+
end
|
171
|
+
@isConnected = false
|
172
|
+
end
|
173
|
+
|
174
|
+
=begin rdoc
|
175
|
+
|
176
|
+
This method checks that the certificates are readable and accessible.
|
177
|
+
|
178
|
+
=end
|
179
|
+
def checkKeys()
|
180
|
+
|
181
|
+
data = nil
|
182
|
+
if (@cafile.nil? || @cafile.empty? || !File.exists?(@cafile) || OpenSSL::X509::Certificate.new(File.read(@cafile)).nil?)
|
183
|
+
warn 'CA certificate NOT OK, running without peer verification'
|
184
|
+
else
|
185
|
+
_dprint('CA certificate OK')
|
186
|
+
end
|
187
|
+
|
188
|
+
if (@keyfile.nil? || @keyfile.empty? || !File.exists?(@keyfile) || OpenSSL::X509::Certificate.new(File.read(@keyfile)).nil?)
|
189
|
+
raise SecurityError, 'Public key NOT OK!'
|
190
|
+
else
|
191
|
+
_dprint('Public key OK')
|
192
|
+
end
|
193
|
+
|
194
|
+
if (!File.exists?(@keyfile) || OpenSSL::PKey::RSA.new(File.read(@keyfile), @keypass).nil?)
|
195
|
+
raise SecurityError, 'Private key NOT OK!'
|
196
|
+
else
|
197
|
+
_dprint('Private key OK')
|
198
|
+
end
|
199
|
+
|
200
|
+
end
|
201
|
+
|
202
|
+
=begin rdoc
|
203
|
+
|
204
|
+
Send the request and get the response back from the server.
|
205
|
+
|
206
|
+
@param [string] mesg The message to send to the server
|
207
|
+
|
208
|
+
@return [string] The response from the server
|
209
|
+
|
210
|
+
@api private
|
211
|
+
@private _request
|
212
|
+
|
213
|
+
=end
|
214
|
+
def _request(mesg)
|
215
|
+
mesg.gsub!(/\n/, '')
|
216
|
+
_dprint("send.request is: #{mesg.inspect}")
|
217
|
+
#puts "---------------------------------"
|
218
|
+
$sslsocket.puts(mesg)
|
219
|
+
$sslsocket.flush
|
220
|
+
|
221
|
+
_dprint("checking response...")
|
222
|
+
raw_response = $sslsocket.gets
|
223
|
+
_dprint("send.raw_response is: #{raw_response.inspect}")
|
224
|
+
response = raw_response.chomp unless raw_response.nil?
|
225
|
+
_dprint("send.response is: #{response.inspect}")
|
226
|
+
unless response.nil?
|
227
|
+
#puts "creating xml"
|
228
|
+
xml = Document.new response
|
229
|
+
#puts xml.inspect
|
230
|
+
else
|
231
|
+
#puts 'No response received.'
|
232
|
+
xml = nil
|
233
|
+
end
|
234
|
+
#puts "returning XML"
|
235
|
+
return xml
|
236
|
+
end
|
237
|
+
private :_request
|
238
|
+
|
239
|
+
=begin rdoc
|
240
|
+
|
241
|
+
Send a big ping transaction to the server to verify the connection is good.
|
242
|
+
|
243
|
+
@note This method should not be necessary in typical implementations, but is available nonetheless.
|
244
|
+
|
245
|
+
@return [string] the raw response from the server
|
246
|
+
|
247
|
+
|
248
|
+
=end
|
249
|
+
def ping()
|
250
|
+
mesg = '<transaction> <type>1</type> <data> <value>TX</value> </data> </transaction>'
|
251
|
+
xml = _request(mesg)
|
252
|
+
return xml
|
253
|
+
end
|
254
|
+
|
255
|
+
=begin rdoc
|
256
|
+
|
257
|
+
This method initiates the connection to the wAuth server.
|
258
|
+
|
259
|
+
@return [boolean] Whether the socket is connected
|
260
|
+
@api private
|
261
|
+
=end
|
262
|
+
def _startConnection()
|
263
|
+
_dprint("startConnection() called.")
|
264
|
+
valid_tag = "ACCEPT";
|
265
|
+
# The client initiates the transaction
|
266
|
+
mesg = "CONNECT: WiKID Ruby Client v#{VERSION}"
|
267
|
+
mesg = "<transaction> <type>1</type> <data> <client-string>wClient Ruby #{VERSION}</client-string> <server-string>null</server-string> <result>null</result> </data> </transaction>
|
268
|
+
"
|
269
|
+
|
270
|
+
xml = _request(mesg);
|
271
|
+
result = XPath.first(xml, '//data/result')
|
272
|
+
@isConnected = (result == 'ACCEPT')
|
273
|
+
|
274
|
+
return @isConnected
|
275
|
+
end
|
276
|
+
private :_startConnection
|
277
|
+
|
278
|
+
=begin rdoc
|
279
|
+
|
280
|
+
This method reconnects to the wAuth server, if the socket handle is dead.
|
281
|
+
|
282
|
+
@return [boolean] Whether the socket is connected
|
283
|
+
|
284
|
+
=end
|
285
|
+
def reconnect()
|
286
|
+
|
287
|
+
_dprint("reconnect() called.")
|
288
|
+
|
289
|
+
begin
|
290
|
+
|
291
|
+
if ($sslsocket.nil? || $sslsocket.closed?)
|
292
|
+
_dprint("Socket inactive. Reconnecting...")
|
293
|
+
|
294
|
+
#puts "Setting up SSL context ..."
|
295
|
+
ctx = OpenSSL::SSL::SSLContext.new()
|
296
|
+
|
297
|
+
# Options:
|
298
|
+
# "cert", "key", "client_ca", "ca_file", "ca_path",
|
299
|
+
# "timeout", "verify_mode", "verify_depth",
|
300
|
+
# "verify_callback", "options", "cert_store", "extra_chain_cert"
|
301
|
+
|
302
|
+
ctx.cert = OpenSSL::X509::Certificate.new(File.read(@keyfile))
|
303
|
+
ctx.key = OpenSSL::PKey::RSA.new(File.read(@keyfile), @keypass)
|
304
|
+
|
305
|
+
if @cafile.nil? || @cafile.empty?
|
306
|
+
ctx.ca_file = nil # @cafile
|
307
|
+
ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
308
|
+
else
|
309
|
+
|
310
|
+
ctx.ca_file = @cafile
|
311
|
+
|
312
|
+
# this next bit might be redundant?
|
313
|
+
ctx.cert_store = OpenSSL::X509::Store.new
|
314
|
+
ctx.cert_store.set_default_paths
|
315
|
+
ctx.cert_store.add_file(@cafile)
|
316
|
+
|
317
|
+
ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
|
318
|
+
end
|
319
|
+
# ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
320
|
+
|
321
|
+
ctx.timeout = @@timeout
|
322
|
+
|
323
|
+
if ctx.cert.nil?
|
324
|
+
_dprint("warning: peer certificate won't be verified this session.")
|
325
|
+
ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
326
|
+
end
|
327
|
+
|
328
|
+
_dprint("Opening socket to #{@host}:#{@port}...")
|
329
|
+
@socket = TCPSocket.open(@host, @port)
|
330
|
+
_dprint("socket open")
|
331
|
+
#@socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_RCVTIMEO, @@timeout)
|
332
|
+
|
333
|
+
#@socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDTIMEO, @@timeout)
|
334
|
+
|
335
|
+
$sslsocket = OpenSSL::SSL::SSLSocket.new(@socket, ctx)
|
336
|
+
_dprint("socket created")
|
337
|
+
#$sslsocket.sync_close = true
|
338
|
+
|
339
|
+
# $sslsocket should be good now
|
340
|
+
_dprint("Connecting SSL socket ...")
|
341
|
+
$sslsocket.connect
|
342
|
+
|
343
|
+
_startConnection()
|
344
|
+
|
345
|
+
end
|
346
|
+
|
347
|
+
if block_given?
|
348
|
+
#puts "Connecting SSL socket in block ..."
|
349
|
+
$sslsocket.connect if $sslsocket.closed?
|
350
|
+
yield
|
351
|
+
#puts "SSL connection block finished."
|
352
|
+
else
|
353
|
+
#puts "SSL connection wanting to do something else ..."
|
354
|
+
# do something non-OO
|
355
|
+
end
|
356
|
+
rescue Exception => ex
|
357
|
+
warn "Error reading from server: #{ex}"
|
358
|
+
end
|
359
|
+
|
360
|
+
end
|
361
|
+
|
362
|
+
=begin rdoc
|
363
|
+
|
364
|
+
Is the socket connected?
|
365
|
+
|
366
|
+
@return [boolean] Status of handle: true indicates connection is active
|
367
|
+
|
368
|
+
=end
|
369
|
+
def isConnected()
|
370
|
+
return @isConnected
|
371
|
+
end
|
372
|
+
|
373
|
+
=begin rdoc
|
374
|
+
|
375
|
+
Creates an association between the userid and the device registered
|
376
|
+
by the user.
|
377
|
+
|
378
|
+
@param [string] username Users login ID in this authentication domain
|
379
|
+
@param [string] regcode Registration code provided to user when
|
380
|
+
setting up this domain on users device
|
381
|
+
@param [string] domaincode 12 digit code representing this
|
382
|
+
authentication domain
|
383
|
+
@param [string] passcode Optional passcode provided by the user, to
|
384
|
+
link this device to an existing registration
|
385
|
+
@return [int] Result code from the registration attempt
|
386
|
+
|
387
|
+
|
388
|
+
=end
|
389
|
+
|
390
|
+
def registerUsername(username, regcode, domaincode, groupname = '', passcode = '')
|
391
|
+
|
392
|
+
_dprint('registerUsername() called ...')
|
393
|
+
valid_tag = 'REGUSER:SUCESS'
|
394
|
+
|
395
|
+
if (!passcode.nil? && passcode.length > 0)
|
396
|
+
_dprint('Adding new device ...')
|
397
|
+
command = 'ADDREGUSER'
|
398
|
+
type = 4;
|
399
|
+
passcodeline = "<passcode>#{passcode}</passcode>";
|
400
|
+
format = 'add';
|
401
|
+
else
|
402
|
+
_dprint('Registering user ...')
|
403
|
+
command = 'REGUSER'
|
404
|
+
type = 4;
|
405
|
+
passcodeline = '<passcode>null</passcode>';
|
406
|
+
format = 'new';
|
407
|
+
end
|
408
|
+
|
409
|
+
if (!groupname.nil? && groupname.length>0)
|
410
|
+
groupnameline="<groupName>#{groupname}</groupName>"
|
411
|
+
else
|
412
|
+
groupnameline='<groupName>null</groupName>'
|
413
|
+
end
|
414
|
+
|
415
|
+
#mesg = "#{command}:#{username}\t#{regcode}\t#{domaincode}\t#{passcode}"
|
416
|
+
mesg = <<XML
|
417
|
+
<transaction>
|
418
|
+
<type format="#{format}">#{type}</type>
|
419
|
+
<data>
|
420
|
+
<user-id>#{username}</user-id>
|
421
|
+
<registration-code>#{regcode}</registration-code>
|
422
|
+
<domaincode>#{domaincode}</domaincode>
|
423
|
+
#{passcodeline}
|
424
|
+
#{groupnameline}
|
425
|
+
<error-code>null</error-code>
|
426
|
+
<result>null</result>
|
427
|
+
</data>
|
428
|
+
</transaction>
|
429
|
+
XML
|
430
|
+
|
431
|
+
#puts mesg
|
432
|
+
reconnect {
|
433
|
+
|
434
|
+
_dprint("registerUsername() sending '#{mesg}' ...")
|
435
|
+
|
436
|
+
xml = _request(mesg)
|
437
|
+
response = XPath.first(xml, '//data/result')
|
438
|
+
_dprint("response: '#{response}'")
|
439
|
+
if response.to_s =~ /SUCC?ESS/
|
440
|
+
_dprint('Registered!')
|
441
|
+
return 0
|
442
|
+
else
|
443
|
+
err = XPath.first(xml, '//data/error-code/text()')
|
444
|
+
_dprint("Failed to register! Error: #{err}")
|
445
|
+
return err
|
446
|
+
end
|
447
|
+
}
|
448
|
+
|
449
|
+
end
|
450
|
+
|
451
|
+
=begin rdoc
|
452
|
+
|
453
|
+
Verifies the credentials that are generated using the standard authentication method.
|
454
|
+
|
455
|
+
@param [string] username Users login ID in this authentication domain
|
456
|
+
@param [string] passcode Passcode provided by the user
|
457
|
+
@param [string] domaincode 12 digit code representing the
|
458
|
+
authentication domain
|
459
|
+
@return [boolean] 'true' indicates credentials were valid,
|
460
|
+
'false' if credentials were invalid or
|
461
|
+
an error occurred
|
462
|
+
|
463
|
+
=end
|
464
|
+
def checkCredentials(username, passcode, domaincode = '127000000001')
|
465
|
+
|
466
|
+
_dprint("checkCredentials(#{username}, #{passcode}, #{domaincode}) called ...")
|
467
|
+
|
468
|
+
validCredentials = false
|
469
|
+
offline_challenge = ''
|
470
|
+
offline_response = ''
|
471
|
+
chap_password = ''
|
472
|
+
chap_challenge = ''
|
473
|
+
valid_tag = 'VERIFY:VALID'
|
474
|
+
|
475
|
+
_dprint('Checking Credentials...')
|
476
|
+
|
477
|
+
mesg = "VERIFY:" + username + "\t" + passcode + "\t" + domaincode
|
478
|
+
mesg = <<XML
|
479
|
+
<transaction>
|
480
|
+
<type format="base">2</type>
|
481
|
+
<data>
|
482
|
+
<user-id>#{username}</user-id>
|
483
|
+
<passcode>#{passcode}</passcode>
|
484
|
+
<domaincode>#{domaincode}</domaincode>
|
485
|
+
<offline-challenge encoding="none">#{offline_challenge}</offline-challenge>
|
486
|
+
<offline-response encoding="none">#{offline_response}</offline-response>
|
487
|
+
<chap-password encoding="none">#{chap_password}</chap-password>
|
488
|
+
<chap-challenge encoding="none">#{chap_challenge}</chap-challenge>
|
489
|
+
<result>null</result>
|
490
|
+
</data>
|
491
|
+
</transaction>
|
492
|
+
XML
|
493
|
+
|
494
|
+
reconnect {
|
495
|
+
|
496
|
+
xml = _request(mesg)
|
497
|
+
response = XPath.first(xml, '//data/result')
|
498
|
+
|
499
|
+
if response =~ /VALID/
|
500
|
+
validCredentials = true
|
501
|
+
else
|
502
|
+
validCredentials = false
|
503
|
+
end
|
504
|
+
_dprint('Read response: verdict = ' + validCredentials.to_s)
|
505
|
+
}
|
506
|
+
|
507
|
+
_dprint('Returning Results...')
|
508
|
+
return validCredentials
|
509
|
+
end
|
510
|
+
|
511
|
+
=begin rdoc
|
512
|
+
|
513
|
+
Verifies the credentials via challenge-response.
|
514
|
+
|
515
|
+
@note Not currently supported by the Open Source release of WiKID.
|
516
|
+
|
517
|
+
@return [boolean] 'true' indicates credentials were valid,
|
518
|
+
'false' if credentials were invalid or
|
519
|
+
an error occurred
|
520
|
+
|
521
|
+
=end
|
522
|
+
def chapVerify(username, domaincode, wikidChallenge = '', chapPassword = '', chapChallenge = '')
|
523
|
+
|
524
|
+
_dprint('chapVerify() called ...')
|
525
|
+
reconnect()
|
526
|
+
validCredentials = false
|
527
|
+
valid_tag = 'VERIFY:VALID'
|
528
|
+
_dprint('Checking Chap Credentials')
|
529
|
+
|
530
|
+
mesg = "CHAPOFFVERIFY:" + username + "\t" + "nil" + "\t" + domaincode + "\t" + wikidChallenge
|
531
|
+
|
532
|
+
reconnect {
|
533
|
+
|
534
|
+
$sslsocket.puts(chapPassword.length)
|
535
|
+
$sslsocket.puts(chapPassword)
|
536
|
+
$sslsocket.puts(chapChallenge.length)
|
537
|
+
$sslsocket.puts(chapChallenge.length)
|
538
|
+
$sslsocket.flush
|
539
|
+
|
540
|
+
_dprint("Reading in...")
|
541
|
+
|
542
|
+
inputLine = $sslsocket.gets.chomp
|
543
|
+
if (inputLine[0, valid_tag.length] == valid_tag)
|
544
|
+
validCredentials = true
|
545
|
+
end
|
546
|
+
}
|
547
|
+
|
548
|
+
return validCredentials
|
549
|
+
end
|
550
|
+
|
551
|
+
=begin rdoc
|
552
|
+
|
553
|
+
This method supports user pre-registration. You may upload a list of userids and
|
554
|
+
pre-registration codes into the server via the WiKIDAdmin interface. Users can then
|
555
|
+
use the pre-registration code provided to them securely by the administrator in
|
556
|
+
conjunction with the registration code provided by the WiKID token to register in
|
557
|
+
an expedited manner.
|
558
|
+
|
559
|
+
@param [string] tokenCode the registration code provided by the token
|
560
|
+
@param [string] preRegCode the code associated with the username that was uploaded to the server
|
561
|
+
@param [string] domaincode 12 digit code representing the authentication server/domain
|
562
|
+
|
563
|
+
@return [boolean] 'true' indicates that the pre-registration was successful;
|
564
|
+
'false' if not
|
565
|
+
=end
|
566
|
+
|
567
|
+
def preRegister(tokenCode, preRegCode, domaincode = '127000000001')
|
568
|
+
|
569
|
+
_dprint('preRegister() called ...')
|
570
|
+
successful = false;
|
571
|
+
|
572
|
+
mesg = <<XML
|
573
|
+
<transaction>
|
574
|
+
<type>10</type>
|
575
|
+
<data>
|
576
|
+
<token-registration-code>#{tokenCode}</token-registration-code>
|
577
|
+
<pre-registration-code>#{preRegCode}</pre-registration-code>
|
578
|
+
<domaincode>#{domaincode}</domaincode>
|
579
|
+
<error-code>null</error-code>
|
580
|
+
<result>null</result>
|
581
|
+
</data>
|
582
|
+
</transaction>
|
583
|
+
XML
|
584
|
+
|
585
|
+
reconnect {
|
586
|
+
_dprint('Pre-registering ...')
|
587
|
+
xml = _request(mesg)
|
588
|
+
|
589
|
+
response = XPath.first(xml, '//data/result')
|
590
|
+
_dprint("response: '#{response}'")
|
591
|
+
|
592
|
+
if response.to_s =~ /SUC?CESS/
|
593
|
+
successful = true
|
594
|
+
else
|
595
|
+
successful = false
|
596
|
+
end
|
597
|
+
}
|
598
|
+
|
599
|
+
_dprint("Read response: verdict = #{successful}")
|
600
|
+
return successful
|
601
|
+
|
602
|
+
end
|
603
|
+
|
604
|
+
=begin rdoc
|
605
|
+
|
606
|
+
Find a user by username
|
607
|
+
|
608
|
+
@param [string] username the textual id of the user to search for
|
609
|
+
@param [string] domaincode the 12 digit code representating the authentication domain
|
610
|
+
|
611
|
+
@return [String] The XML representing the user object, if successful; nil if unsuccesful
|
612
|
+
|
613
|
+
=end
|
614
|
+
|
615
|
+
def findUser(username, domaincode = '127000000001')
|
616
|
+
|
617
|
+
_dprint("findUser() ...");
|
618
|
+
|
619
|
+
user = nil
|
620
|
+
|
621
|
+
mesg = <<XML
|
622
|
+
<transaction>
|
623
|
+
<type>5</type>
|
624
|
+
<data>
|
625
|
+
<domaincode>#{domaincode}</domaincode>
|
626
|
+
<user-id>#{username}</user-id>
|
627
|
+
<result>null</result>
|
628
|
+
<return-code>-2147483648</return-code>
|
629
|
+
</data>
|
630
|
+
</transaction>
|
631
|
+
XML
|
632
|
+
|
633
|
+
reconnect {
|
634
|
+
_dprint("Looking up user ...");
|
635
|
+
xml = _request(mesg)
|
636
|
+
|
637
|
+
user_xml = XPath.first(xml, '//data/user')
|
638
|
+
|
639
|
+
return user_xml
|
640
|
+
}
|
641
|
+
|
642
|
+
end
|
643
|
+
|
644
|
+
=begin rdoc
|
645
|
+
|
646
|
+
Update the previously "found" user
|
647
|
+
|
648
|
+
This method is used to update a user object on the server. The network client certificate that was
|
649
|
+
used to establish the wClient connection must be authorized to perform this action.
|
650
|
+
|
651
|
+
@param [string] user_id The userid on the server, or a user object as returned
|
652
|
+
by a call to findUser()
|
653
|
+
@param [string] domaincode 12 digit code representing the authentication domain if first argument is a userid (string), not necessary
|
654
|
+
if first argument is the user object, which will already have this
|
655
|
+
|
656
|
+
@return [boolean] 'true' indicates the update was successful
|
657
|
+
=end
|
658
|
+
|
659
|
+
def updateUser(user_id, domaincode = '127000000001', updateUserXml = '')
|
660
|
+
|
661
|
+
successful = false
|
662
|
+
|
663
|
+
_dprint("updateUser(#{user_id},#{domaincode})")
|
664
|
+
|
665
|
+
if (user_id.is_a?(String))
|
666
|
+
user_xml = findUser(user_id, domaincode)
|
667
|
+
end
|
668
|
+
|
669
|
+
if user_xml.nil?
|
670
|
+
return false
|
671
|
+
end
|
672
|
+
|
673
|
+
_dprint("user_xml: #{user_xml}, updating to #{updateUserXml}")
|
674
|
+
|
675
|
+
mesg = <<XML
|
676
|
+
<transaction>
|
677
|
+
<type>6</type>
|
678
|
+
<data>
|
679
|
+
<domaincode>#{domaincode}</domaincode>
|
680
|
+
<user-id>#{user_id}</user-id>
|
681
|
+
#{updateUserXml}
|
682
|
+
<result>null</result>
|
683
|
+
<return-code>-2147483648</return-code>
|
684
|
+
</data>
|
685
|
+
</transaction>
|
686
|
+
XML
|
687
|
+
|
688
|
+
reconnect {
|
689
|
+
_dprint('updating user ...')
|
690
|
+
|
691
|
+
xml = _request(mesg)
|
692
|
+
|
693
|
+
response = XPath.first(xml, '//data/result')
|
694
|
+
_dprint("response: '#{response}'")
|
695
|
+
|
696
|
+
if response.to_s =~ /SUCC?ESS/
|
697
|
+
successful = true
|
698
|
+
else
|
699
|
+
successful = false
|
700
|
+
end
|
701
|
+
|
702
|
+
}
|
703
|
+
|
704
|
+
return successful
|
705
|
+
end
|
706
|
+
|
707
|
+
=begin rdoc
|
708
|
+
|
709
|
+
Delete a user by userid
|
710
|
+
|
711
|
+
@param [string] user_id The userid on the server, or a user object as returned
|
712
|
+
by a call to findUser()
|
713
|
+
@param [string] domaincode 12 digit code representing the authentication domain if first argument is a userid (string), not necessary
|
714
|
+
if first argument is the user object, which will already have this
|
715
|
+
|
716
|
+
@return [boolean] ' true ' indicates deletion was successful
|
717
|
+
|
718
|
+
|
719
|
+
=end
|
720
|
+
def deleteUser(user_id, domaincode = ' 127000000001 ')
|
721
|
+
|
722
|
+
successful = false
|
723
|
+
|
724
|
+
_dprint("deleteUser(#{user_id},#{domaincode})")
|
725
|
+
|
726
|
+
if (user_id.is_a?(String))
|
727
|
+
user_xml = findUser(user_id, domaincode)
|
728
|
+
end
|
729
|
+
|
730
|
+
if user_xml.nil?
|
731
|
+
return false
|
732
|
+
end
|
733
|
+
|
734
|
+
_dprint("user: #{user_id}")
|
735
|
+
|
736
|
+
mesg = <<XML
|
737
|
+
<transaction>
|
738
|
+
<type>7</type>
|
739
|
+
<data>
|
740
|
+
<domaincode>#{domaincode}</domaincode>
|
741
|
+
<user-id>#{user_id}</user-id>
|
742
|
+
#{user_xml}
|
743
|
+
<result>null</result>
|
744
|
+
<return-code>-2147483648</return-code>
|
745
|
+
</data>
|
746
|
+
</transaction>
|
747
|
+
XML
|
748
|
+
|
749
|
+
|
750
|
+
reconnect {
|
751
|
+
_dprint('deleting user ...')
|
752
|
+
|
753
|
+
xml = _request(mesg)
|
754
|
+
|
755
|
+
unless xml.nil?
|
756
|
+
response = XPath.first(xml, '//data/result')
|
757
|
+
_dprint("response: '#{response}'")
|
758
|
+
|
759
|
+
if response.to_s =~ /SUCC?ESS/
|
760
|
+
successful = true
|
761
|
+
else
|
762
|
+
successful = false
|
763
|
+
end
|
764
|
+
end
|
765
|
+
|
766
|
+
return successful
|
767
|
+
}
|
768
|
+
|
769
|
+
end
|
770
|
+
|
771
|
+
|
772
|
+
=begin rdoc
|
773
|
+
|
774
|
+
Fetches a list of domains served by the currently connected server code.
|
775
|
+
|
776
|
+
@note Not currently supported by the Open Source release of WiKID.
|
777
|
+
|
778
|
+
|
779
|
+
@return [string] ' true ' indicates credentials were valid,
|
780
|
+
' false ' if credentials were invalid or
|
781
|
+
an error occurred
|
782
|
+
|
783
|
+
=end
|
784
|
+
def getDomains()
|
785
|
+
|
786
|
+
_dprint("getDomains() called ...")
|
787
|
+
|
788
|
+
valid_tag = "DOMAINLIST"
|
789
|
+
_dprint("Getting Domains")
|
790
|
+
|
791
|
+
mesg = <<XML
|
792
|
+
<transaction>
|
793
|
+
<type>3</type>
|
794
|
+
<data>
|
795
|
+
<domain-list>null</domain-list>
|
796
|
+
</data>
|
797
|
+
</transaction>
|
798
|
+
XML
|
799
|
+
reconnect {
|
800
|
+
xml = _request(mesg)
|
801
|
+
domains = XPath.match(xml, '//data/domain-list')
|
802
|
+
}
|
803
|
+
_dprint("Returning Results...")
|
804
|
+
return domains
|
805
|
+
end
|
806
|
+
|
807
|
+
=begin rdoc
|
808
|
+
|
809
|
+
Modify the debug state of the current connection
|
810
|
+
|
811
|
+
@param [boolean] newStatus
|
812
|
+
=end
|
813
|
+
def setDebug(newStatus)
|
814
|
+
@@DEBUG = (newStatus == true) ? true : false
|
815
|
+
end
|
816
|
+
|
817
|
+
=begin rdoc
|
818
|
+
|
819
|
+
Prints a message if the debug flag is true, time-stamped since the epoch.
|
820
|
+
|
821
|
+
@param [string] msg Message to print out
|
822
|
+
@api private
|
823
|
+
@private
|
824
|
+
=end
|
825
|
+
def _dprint(msg)
|
826
|
+
|
827
|
+
if (@@DEBUG)
|
828
|
+
show = Time.now.to_s + ' : ' + msg
|
829
|
+
show += '<br />' if !ENV['REQUEST_URI'].nil?
|
830
|
+
|
831
|
+
puts show
|
832
|
+
#STDERR.puts show
|
833
|
+
#STDERR.flush()
|
834
|
+
end
|
835
|
+
return true
|
836
|
+
end
|
837
|
+
private :_dprint
|
838
|
+
|
839
|
+
end
|
840
|
+
|
841
|
+
end
|