smartcard 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +2 -0
- data/lib/smartcard/pcsc/card.rb +49 -2
- data/smartcard.gemspec +5 -5
- data/test/pcsc/card_test.rb +26 -0
- metadata +73 -31
data/CHANGELOG
CHANGED
data/lib/smartcard/pcsc/card.rb
CHANGED
@@ -35,11 +35,16 @@ class Card
|
|
35
35
|
raise Smartcard::PCSC::Exception, status unless status == :success
|
36
36
|
|
37
37
|
@context = context
|
38
|
+
@sharing_mode = sharing_mode
|
39
|
+
@_handle = handle_ptr[:value]
|
38
40
|
set_protocol FFILib::Protocol[protocol_ptr[:value]]
|
39
|
-
@_handle = handle_ptr[:value]
|
40
41
|
end
|
41
42
|
|
42
|
-
# Updates internal buffers to reflect a change in the communication protocol.
|
43
|
+
# Updates internal buffers to reflect a change in the communication protocol.
|
44
|
+
#
|
45
|
+
# Args:
|
46
|
+
# protocol:: the protocol to change to; if invalid, the card's ATR will be
|
47
|
+
# used to guess a valid protocol
|
43
48
|
def set_protocol(protocol)
|
44
49
|
@protocol = protocol
|
45
50
|
|
@@ -50,12 +55,16 @@ class Card
|
|
50
55
|
@send_pci = @recv_pci = FFILib::PCI_T1
|
51
56
|
when :raw
|
52
57
|
@send_pci = @recv_pci = FFILib::PCI_RAW
|
58
|
+
else
|
59
|
+
reconnect sharing_mode, guess_protocol_from_atr, :leave
|
60
|
+
return self
|
53
61
|
end
|
54
62
|
|
55
63
|
# Windows really doesn't like a receiving IoRequest.
|
56
64
|
if FFI::Platform.windows? || FFI::Platform.mac?
|
57
65
|
@recv_pci = nil
|
58
66
|
end
|
67
|
+
self
|
59
68
|
end
|
60
69
|
private :set_protocol
|
61
70
|
|
@@ -78,6 +87,7 @@ class Card
|
|
78
87
|
preferred_protocols, disposition, protocol_ptr
|
79
88
|
raise Smartcard::PCSC::Exception, status unless status == :success
|
80
89
|
|
90
|
+
@sharing_mode = sharing_mode
|
81
91
|
set_protocol FFILib::Protocol[protocol_ptr[:value]]
|
82
92
|
end
|
83
93
|
|
@@ -269,6 +279,40 @@ class Card
|
|
269
279
|
end
|
270
280
|
end
|
271
281
|
|
282
|
+
# Returns the first valid protocol listed in the card's ATR.
|
283
|
+
def guess_protocol_from_atr
|
284
|
+
atr = info[:atr]
|
285
|
+
|
286
|
+
# NOTE: inspired from the following sources:
|
287
|
+
# http://en.wikipedia.org/wiki/Answer_to_reset
|
288
|
+
# http://www.atmel.com/dyn/resources/prod_documents/doc5025.pdf
|
289
|
+
# http://pyscard.sourceforge.net/epydoc/smartcard.ATR-pysrc.html#ATR.__initInstance__
|
290
|
+
atr_bytes = atr.unpack('C*')
|
291
|
+
protocols = []
|
292
|
+
i = 1
|
293
|
+
loop do
|
294
|
+
next_nibble = atr_bytes[i] >> 4
|
295
|
+
next_bits = (0...4).map { |j| (next_nibble >> j) & 1 }
|
296
|
+
next_bits.each { |bit| i += bit }
|
297
|
+
if next_bits[3] == 1 # TD byte was last, i is right on it
|
298
|
+
protocols << (atr_bytes[i] & 0x0f)
|
299
|
+
else
|
300
|
+
break # No TD, no more bytes
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
protocols.sort!
|
305
|
+
case protocols[0]
|
306
|
+
when 0
|
307
|
+
:t0
|
308
|
+
when 1
|
309
|
+
:t1
|
310
|
+
else
|
311
|
+
:t0
|
312
|
+
end
|
313
|
+
end
|
314
|
+
private :guess_protocol_from_atr
|
315
|
+
|
272
316
|
# The low-level _SCARDHANDLE_ data.
|
273
317
|
#
|
274
318
|
# This should not be used by client code.
|
@@ -276,6 +320,9 @@ class Card
|
|
276
320
|
|
277
321
|
# The communication protocol in use with this smart-card.
|
278
322
|
attr_reader :protocol
|
323
|
+
|
324
|
+
# The sharing mode for this smart-card session. (:shared or :exclusive)
|
325
|
+
attr_reader :sharing_mode
|
279
326
|
end # class Smartcard::PCSC::Card
|
280
327
|
|
281
328
|
end # namespace Smartcard::PCSC
|
data/smartcard.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{smartcard}
|
5
|
-
s.version = "0.5.
|
5
|
+
s.version = "0.5.1"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Victor Costan"]
|
9
|
-
s.date = %q{
|
9
|
+
s.date = %q{2010-11-27}
|
10
10
|
s.description = %q{Interface with ISO 7816 smart cards.}
|
11
11
|
s.email = %q{victor@costan.us}
|
12
12
|
s.extra_rdoc_files = ["BUILD", "CHANGELOG", "LICENSE", "README", "lib/smartcard.rb", "lib/smartcard/gp/asn1_ber.rb", "lib/smartcard/gp/cap_loader.rb", "lib/smartcard/gp/des.rb", "lib/smartcard/gp/gp_card_mixin.rb", "lib/smartcard/iso/apdu_error.rb", "lib/smartcard/iso/auto_configurator.rb", "lib/smartcard/iso/iso_card_mixin.rb", "lib/smartcard/iso/jcop_remote_protocol.rb", "lib/smartcard/iso/jcop_remote_server.rb", "lib/smartcard/iso/jcop_remote_transport.rb", "lib/smartcard/iso/pcsc_transport.rb", "lib/smartcard/iso/transport.rb", "lib/smartcard/pcsc/card.rb", "lib/smartcard/pcsc/context.rb", "lib/smartcard/pcsc/ffi_autogen.rb", "lib/smartcard/pcsc/ffi_functions.rb", "lib/smartcard/pcsc/ffi_lib.rb", "lib/smartcard/pcsc/ffi_structs.rb", "lib/smartcard/pcsc/pcsc_exception.rb", "lib/smartcard/pcsc/reader_state_queries.rb", "tasks/ffi_codegen.rb"]
|
@@ -15,15 +15,15 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Smartcard", "--main", "README"]
|
16
16
|
s.require_paths = ["lib"]
|
17
17
|
s.rubyforge_project = %q{smartcard}
|
18
|
-
s.rubygems_version = %q{1.3.
|
18
|
+
s.rubygems_version = %q{1.3.7}
|
19
19
|
s.summary = %q{Interface with ISO 7816 smart cards.}
|
20
|
-
s.test_files = ["test/
|
20
|
+
s.test_files = ["test/gp/asn1_ber_test.rb", "test/gp/cap_loader_test.rb", "test/gp/des_test.rb", "test/gp/gp_card_mixin_compat_test.rb", "test/gp/gp_card_mixin_test.rb", "test/iso/auto_configurator_test.rb", "test/iso/iso_card_mixin_test.rb", "test/iso/iso_exception_test.rb", "test/iso/jcop_remote_test.rb", "test/pcsc/card_test.rb", "test/pcsc/context_test.rb", "test/pcsc/reader_state_queries_test.rb"]
|
21
21
|
|
22
22
|
if s.respond_to? :specification_version then
|
23
23
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
24
24
|
s.specification_version = 3
|
25
25
|
|
26
|
-
if Gem::Version.new(Gem::
|
26
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
27
27
|
s.add_runtime_dependency(%q<ffi>, [">= 0.5.3"])
|
28
28
|
s.add_runtime_dependency(%q<rubyzip>, [">= 0.9.1"])
|
29
29
|
s.add_runtime_dependency(%q<zerg_support>, [">= 0.1.5"])
|
data/test/pcsc/card_test.rb
CHANGED
@@ -6,6 +6,9 @@ require 'smartcard'
|
|
6
6
|
|
7
7
|
require 'test/unit'
|
8
8
|
|
9
|
+
require 'rubygems'
|
10
|
+
require 'flexmock/test_unit'
|
11
|
+
|
9
12
|
|
10
13
|
class CardTest < Test::Unit::TestCase
|
11
14
|
def setup
|
@@ -19,8 +22,13 @@ class CardTest < Test::Unit::TestCase
|
|
19
22
|
@context.release
|
20
23
|
end
|
21
24
|
|
25
|
+
def test_sharing_mode
|
26
|
+
assert_equal :shared, @card.sharing_mode
|
27
|
+
end
|
28
|
+
|
22
29
|
def test_reconnect
|
23
30
|
@card.reconnect :shared
|
31
|
+
assert_equal :shared, @card.sharing_mode
|
24
32
|
end
|
25
33
|
|
26
34
|
def test_transaction
|
@@ -65,4 +73,22 @@ class CardTest < Test::Unit::TestCase
|
|
65
73
|
ctl_response = @card.control 0x42000001, [0x02].pack('C*')
|
66
74
|
end
|
67
75
|
end
|
76
|
+
|
77
|
+
def test_set_protocol_guesses
|
78
|
+
flexmock(@card).should_receive(:guess_protocol_from_atr).and_return(:t0)
|
79
|
+
flexmock(@card).should_receive(:reconnect).with(:shared, :t0, :leave)
|
80
|
+
@card.send :set_protocol, :unset
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_guess_protocol_t0_from_atr
|
84
|
+
flexmock(@card).should_receive(:info).and_return(:atr =>
|
85
|
+
";\026\224q\001\001\005\002\000")
|
86
|
+
assert_equal :t0, @card.send(:guess_protocol_from_atr)
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_guess_protocol_t1_from_atr
|
90
|
+
flexmock(@card).should_receive(:info).and_return(:atr =>
|
91
|
+
";\212\001JCOP41V221\377")
|
92
|
+
assert_equal :t1, @card.send(:guess_protocol_from_atr)
|
93
|
+
end
|
68
94
|
end
|
metadata
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: smartcard
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 9
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 5
|
9
|
+
- 1
|
10
|
+
version: 0.5.1
|
5
11
|
platform: ruby
|
6
12
|
authors:
|
7
13
|
- Victor Costan
|
@@ -9,59 +15,88 @@ autorequire:
|
|
9
15
|
bindir: bin
|
10
16
|
cert_chain: []
|
11
17
|
|
12
|
-
date:
|
18
|
+
date: 2010-11-27 00:00:00 -05:00
|
13
19
|
default_executable:
|
14
20
|
dependencies:
|
15
21
|
- !ruby/object:Gem::Dependency
|
16
22
|
name: ffi
|
17
|
-
|
18
|
-
|
19
|
-
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
20
26
|
requirements:
|
21
27
|
- - ">="
|
22
28
|
- !ruby/object:Gem::Version
|
29
|
+
hash: 13
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
- 5
|
33
|
+
- 3
|
23
34
|
version: 0.5.3
|
24
|
-
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
25
37
|
- !ruby/object:Gem::Dependency
|
26
38
|
name: rubyzip
|
27
|
-
|
28
|
-
|
29
|
-
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
30
42
|
requirements:
|
31
43
|
- - ">="
|
32
44
|
- !ruby/object:Gem::Version
|
45
|
+
hash: 57
|
46
|
+
segments:
|
47
|
+
- 0
|
48
|
+
- 9
|
49
|
+
- 1
|
33
50
|
version: 0.9.1
|
34
|
-
|
51
|
+
type: :runtime
|
52
|
+
version_requirements: *id002
|
35
53
|
- !ruby/object:Gem::Dependency
|
36
54
|
name: zerg_support
|
37
|
-
|
38
|
-
|
39
|
-
|
55
|
+
prerelease: false
|
56
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
40
58
|
requirements:
|
41
59
|
- - ">="
|
42
60
|
- !ruby/object:Gem::Version
|
61
|
+
hash: 17
|
62
|
+
segments:
|
63
|
+
- 0
|
64
|
+
- 1
|
65
|
+
- 5
|
43
66
|
version: 0.1.5
|
44
|
-
|
67
|
+
type: :runtime
|
68
|
+
version_requirements: *id003
|
45
69
|
- !ruby/object:Gem::Dependency
|
46
70
|
name: echoe
|
47
|
-
|
48
|
-
|
49
|
-
|
71
|
+
prerelease: false
|
72
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
50
74
|
requirements:
|
51
75
|
- - ">="
|
52
76
|
- !ruby/object:Gem::Version
|
77
|
+
hash: 3
|
78
|
+
segments:
|
79
|
+
- 3
|
80
|
+
- 2
|
53
81
|
version: "3.2"
|
54
|
-
|
82
|
+
type: :development
|
83
|
+
version_requirements: *id004
|
55
84
|
- !ruby/object:Gem::Dependency
|
56
85
|
name: flexmock
|
57
|
-
|
58
|
-
|
59
|
-
|
86
|
+
prerelease: false
|
87
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
88
|
+
none: false
|
60
89
|
requirements:
|
61
90
|
- - ">="
|
62
91
|
- !ruby/object:Gem::Version
|
92
|
+
hash: 51
|
93
|
+
segments:
|
94
|
+
- 0
|
95
|
+
- 8
|
96
|
+
- 6
|
63
97
|
version: 0.8.6
|
64
|
-
|
98
|
+
type: :development
|
99
|
+
version_requirements: *id005
|
65
100
|
description: Interface with ISO 7816 smart cards.
|
66
101
|
email: victor@costan.us
|
67
102
|
executables: []
|
@@ -154,34 +189,41 @@ rdoc_options:
|
|
154
189
|
require_paths:
|
155
190
|
- lib
|
156
191
|
required_ruby_version: !ruby/object:Gem::Requirement
|
192
|
+
none: false
|
157
193
|
requirements:
|
158
194
|
- - ">="
|
159
195
|
- !ruby/object:Gem::Version
|
196
|
+
hash: 3
|
197
|
+
segments:
|
198
|
+
- 0
|
160
199
|
version: "0"
|
161
|
-
version:
|
162
200
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
201
|
+
none: false
|
163
202
|
requirements:
|
164
203
|
- - ">="
|
165
204
|
- !ruby/object:Gem::Version
|
205
|
+
hash: 11
|
206
|
+
segments:
|
207
|
+
- 1
|
208
|
+
- 2
|
166
209
|
version: "1.2"
|
167
|
-
version:
|
168
210
|
requirements: []
|
169
211
|
|
170
212
|
rubyforge_project: smartcard
|
171
|
-
rubygems_version: 1.3.
|
213
|
+
rubygems_version: 1.3.7
|
172
214
|
signing_key:
|
173
215
|
specification_version: 3
|
174
216
|
summary: Interface with ISO 7816 smart cards.
|
175
217
|
test_files:
|
176
|
-
- test/
|
218
|
+
- test/gp/asn1_ber_test.rb
|
219
|
+
- test/gp/cap_loader_test.rb
|
220
|
+
- test/gp/des_test.rb
|
221
|
+
- test/gp/gp_card_mixin_compat_test.rb
|
222
|
+
- test/gp/gp_card_mixin_test.rb
|
177
223
|
- test/iso/auto_configurator_test.rb
|
224
|
+
- test/iso/iso_card_mixin_test.rb
|
178
225
|
- test/iso/iso_exception_test.rb
|
179
226
|
- test/iso/jcop_remote_test.rb
|
180
227
|
- test/pcsc/card_test.rb
|
181
228
|
- test/pcsc/context_test.rb
|
182
229
|
- test/pcsc/reader_state_queries_test.rb
|
183
|
-
- test/gp/gp_card_mixin_test.rb
|
184
|
-
- test/gp/gp_card_mixin_compat_test.rb
|
185
|
-
- test/gp/cap_loader_test.rb
|
186
|
-
- test/gp/asn1_ber_test.rb
|
187
|
-
- test/gp/des_test.rb
|