10
0
Fork 0
softsim/src/pcsc_server.rb

138 lines
3.3 KiB
Ruby
Raw Permalink Normal View History

#!/usr/bin/env ruby
# encoding: UTF-8
2011-05-02 10:34:31 +00:00
=begin
2011-05-06 08:36:22 +00:00
This file is part of softSIM.
2011-05-02 10:34:31 +00:00
2011-05-06 08:36:22 +00:00
softSIM is free software: you can redistribute it and/or modify
2011-05-02 10:34:31 +00:00
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.
2011-05-06 08:36:22 +00:00
softSIM is distributed in the hope that it will be useful,
2011-05-02 10:34:31 +00:00
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
2011-05-06 08:36:22 +00:00
along with sofSIM. If not, see <http://www.gnu.org/licenses/>.
2011-05-02 10:34:31 +00:00
Copyright (C) 2011 Kevin "tsaitgaist" Redon kevredon@mail.tsaitgaist.info
=end
require_relative 'sap/server'
2011-05-02 09:39:55 +00:00
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)
2011-05-16 12:53:14 +00:00
end
# get the reader and the card
# return if connection to card succeeded
def select_card
# get PCSC context
2011-05-03 12:05:56 +00:00
begin
@context = Smartcard::PCSC::Context.new
rescue Smartcard::PCSC::Exception => e
puts "PCSC not available. please start PCSC"
2011-05-16 12:53:14 +00:00
return false
2011-05-03 12:05:56 +00:00
end
2011-05-16 12:53:14 +00:00
# get all readers
2011-04-12 22:12:18 +00:00
begin
2011-05-03 12:05:56 +00:00
readers = @context.readers
2011-04-12 22:12:18 +00:00
rescue Smartcard::PCSC::Exception => e
puts "no reader available. please connect a card reader"
2011-05-16 12:53:14 +00:00
return false
2011-04-12 22:12:18 +00:00
end
2011-05-03 12:05:56 +00:00
# one reader required
2011-05-16 12:53:14 +00:00
if readers.size==0 then
puts "no reader available. connect a reader"
2011-05-16 12:53:14 +00:00
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:"
2011-05-16 12:53:14 +00:00
readers.each_index do |i|
puts "#{i}) #{readers[i]}"
end
reader = nil
until reader do
print "select reader [0]: "
2011-05-16 12:53:14 +00:00
@reader_id = gets.chomp.to_i
reader = readers[@reader_id]
end
end
puts "using reader: #{reader}"
2011-05-03 12:05:56 +00:00
2011-05-16 12:53:14 +00:00
# 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
2011-05-03 12:05:56 +00:00
2011-05-16 12:53:14 +00:00
puts "connected to card"
return true
2011-05-03 12:05:56 +00:00
end
# connect to card
def connect
2011-05-16 12:53:14 +00:00
# connect to card
sleep 1 until select_card
2011-05-03 12:05:56 +00:00
return true
end
2011-05-06 16:44:05 +00:00
2011-05-06 16:52:12 +00:00
# release card and context
2011-05-06 16:44:05 +00:00
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
2011-02-07 14:53:56 +00:00
# send APDU and get response
def apdu(request)
raise "connect to card to send APDU" unless @card
2011-05-16 12:53:14 +00:00
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
2011-02-07 14:53:56 +00:00
return response
end
end