blob: 4a802e965eb2b48062702dd9bc6e980bbe5932d9 (
plain)
1
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
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
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
|
#!/usr/bin/env ruby
# encoding: UTF-8
=begin
This file is part of softSIM.
softSIM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
softSIM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with sofSIM. If not, see <http://www.gnu.org/licenses/>.
Copyright (C) 2011 Kevin "tsaitgaist" Redon kevredon@mail.tsaitgaist.info
=end
require './sap/server.rb'
require 'rubygems'
require 'smartcard'
=begin
need to install
sudo aptitude install ruby ruby-dev rubygems
sudo aptitude install libpcsclite1 libpcsclite-dev libruby
sudo gem install smartcard (http://www.rubygems.org/gems/smartcard)
=end
# SAP server using PCSC for the card
class PCSCServer < Server
# provide the io to listen to
def initialize(io)
super(io)
end
# get the reader and the card
# return if connection to card succeeded
def select_card
# get PCSC context
begin
@context = Smartcard::PCSC::Context.new
rescue Smartcard::PCSC::Exception => e
puts "PCSC not available. please start PCSC"
return false
end
# get all readers
begin
readers = @context.readers
rescue Smartcard::PCSC::Exception => e
puts "no reader available. please connect a card reader"
return false
end
# one reader required
if readers.size==0 then
puts "no reader available. connect a reader"
return false
# select reader
elsif readers.size==1 then
# use the first reader
reader = readers.first
elsif @reader_id
# reader already selected
else
# select reader
puts "readers:"
readers.each_index do |i|
puts "#{i}) #{readers[i]}"
end
reader = nil
until reader do
print "select reader [0]: "
@reader_id = gets.chomp.to_i
reader = readers[@reader_id]
end
end
puts "using reader: #{reader}"
# connect to the card
verb = true
begin
@card = Smartcard::PCSC::Card.new(@context,reader,:exclusive,:t0)
rescue Smartcard::PCSC::Exception
puts "no card inside. insert smart card"
return false
end
puts "connected to card"
return true
end
# connect to card
def connect
# connect to card
sleep 1 until select_card
return true
end
# release card and context
def disconnect
@card.disconnect
@context.release
end
# get ATR
def atr
raise "connect to card to get ATR" unless @card
return @card.info[:atr].unpack("C*")
end
# send APDU and get response
def apdu(request)
raise "connect to card to send APDU" unless @card
begin
response = @card.transmit(request.pack('C*')).unpack("C*")
rescue Smartcard::PCSC::Exception => e
tries = 0 unless tries
tries += 1
if tries <= 3 then
puts "PCSC bug (try #{tries})"
sleep 5
retry
else
raise e if tries>=3
end
end
return response
end
end
|