aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin Redon <kevredon@mail.tsaitgaist.info>2011-05-02 11:39:55 +0200
committerKevin Redon <kevredon@mail.tsaitgaist.info>2011-05-02 11:39:55 +0200
commit863a4a26e52d01593e162063dd338ceffbf350c6 (patch)
treeab9f1f92648589f5d586abc817c4682edf1c0321
parentc36d3614ed4560762e9712387fcdabba400ca36a (diff)
restructured files organisation
-rwxr-xr-xlib/sim_server.rb67
-rw-r--r--nbproject/project.properties7
-rw-r--r--nbproject/project.xml16
-rwxr-xr-xsrc/apdu_client.rb (renamed from lib/apdu_client.rb)2
-rw-r--r--src/bluetooth_client.rb (renamed from lib/bluetooth_client.rb)4
-rwxr-xr-xsrc/demo_client.rb (renamed from lib/demo_client.rb)11
-rw-r--r--src/lib/client.rb (renamed from lib/client.rb)4
-rw-r--r--src/lib/common.rb (renamed from lib/common.rb)0
-rw-r--r--src/lib/server.rb (renamed from lib/server.rb)2
-rwxr-xr-xsrc/pcsc_server.rb (renamed from lib/pcsc_server.rb)10
-rwxr-xr-xsrc/sim_server.rb234
11 files changed, 252 insertions, 105 deletions
diff --git a/lib/sim_server.rb b/lib/sim_server.rb
deleted file mode 100755
index a6e2f97..0000000
--- a/lib/sim_server.rb
+++ /dev/null
@@ -1,67 +0,0 @@
-#!/usr/bin/env ruby
-require 'server'
-require 'socket'
-require 'xml'
-
-class String
- # convert a hexadecimal string into binary array
- def hex2arr
- arr = []
- (self.length/2).times do |i|
- arr << self[i*2,2].to_i(16)
- end
- return arr
- end
-end
-
-# SAP server using a SIM backup file
-class SIMServer < Server
-
- def initialize(io,path="sim.xml")
- super(io)
- @xml_path = path
- end
-
- # read file
- def connect
-
- begin
- xml = IO.read(@xml_path)
- doc = XML::Parser.string(xml)
- @card = doc.parse
- rescue
- puts "can't read #{@xml_path}"
- status = create_message("STATUS_IND",[[0x08,[0x02]]])
- send(status)
- sleep 1
- redo
- end
-
- # card ready
- # ["StatusChange",["Card reset"]]
- status = create_message("STATUS_IND",[[0x08,[0x01]]])
- send(status)
- log("server","connection established. SIM loaded",3)
- end
-
- # get ATR
- def atr
- raise "connect to card to get ATR" unless @card
- return @card.find_first("/sim")["atr"].hex2arr
- end
-
- # send APDU and get response
- def apdu(request)
- raise "connect to card to send APDU" unless @card
- raise "not implemented"
- response = @card.transmit(request.pack('C*')).unpack("C*")
- return response
- end
-
-end
-
-# demo application, using TCP socket
-socket = TCPServer.new("localhost",1337)
-io = socket.accept
-server = SIMServer.new(io)
-server.start \ No newline at end of file
diff --git a/nbproject/project.properties b/nbproject/project.properties
deleted file mode 100644
index 38e19b2..0000000
--- a/nbproject/project.properties
+++ /dev/null
@@ -1,7 +0,0 @@
-javac.classpath=
-main.file=main.rb
-platform.active=default
-source.encoding=UTF-8
-spec.src.dir=spec
-src.dir=lib
-test.src.dir=test
diff --git a/nbproject/project.xml b/nbproject/project.xml
deleted file mode 100644
index bf56132..0000000
--- a/nbproject/project.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://www.netbeans.org/ns/project/1">
- <type>org.netbeans.modules.ruby.rubyproject</type>
- <configuration>
- <data xmlns="http://www.netbeans.org/ns/ruby-project/1">
- <name>SAP</name>
- <source-roots>
- <root id="src.dir"/>
- </source-roots>
- <test-roots>
- <root id="test.src.dir"/>
- <root id="spec.src.dir"/>
- </test-roots>
- </data>
- </configuration>
-</project>
diff --git a/lib/apdu_client.rb b/src/apdu_client.rb
index 68042ec..8514bcf 100755
--- a/lib/apdu_client.rb
+++ b/src/apdu_client.rb
@@ -1,7 +1,7 @@
#!/usr/bin/env ruby
# This programm will forward APDU from a TCP port to a SAP server
+require 'lib/client'
require 'socket'
-require 'client'
SAP_HOST = "localhost"
SAP_PORT = "1337"
diff --git a/lib/bluetooth_client.rb b/src/bluetooth_client.rb
index 0b6290e..bf69a0a 100644
--- a/lib/bluetooth_client.rb
+++ b/src/bluetooth_client.rb
@@ -1,4 +1,4 @@
-require 'client' # SAP client
+require 'lib/client' # SAP client
require 'dbus' # libdbus-ruby
# class to connect to BT SAP server using BlueZ over dbus
@@ -254,4 +254,4 @@ class BluetoothClient
@bt_adapter.RemoveDevice(@bt_sap.path) unless @trusted or @paired
end
-end \ No newline at end of file
+end
diff --git a/lib/demo_client.rb b/src/demo_client.rb
index 44b93f5..264ee73 100755
--- a/lib/demo_client.rb
+++ b/src/demo_client.rb
@@ -1,6 +1,6 @@
#!/usr/bin/env ruby
# This programm will create a client which can be used to test servers
-require 'client'
+require 'lib/client'
#=================
#== client type ==
@@ -62,6 +62,11 @@ A38 = [CLASS,0x88,0x00,0x00,0x10]
# file address (TS 51.011 10.7, page 105)
MF = [0x3F,0x00]
+ EF_ICCID = [0x2F,0xE2]
+ DF_GSM = [0x7F,0x20]
+ EF_IMSI = [0x6F,0x07] # TS 51.011 10.3.2
+ DF_TELECOM = [0x7F,0x10]
+ EF_MSISDN = [0x6F,0x40] # TS 51.011 10.5.5
#=========================
#== additionnal methods ==
@@ -217,8 +222,8 @@ end
atr = @client.atr
puts atr ? "ATR : #{atr.to_hex_disp}" : "could not get ATR"
# select MF
-apdu_req = [0xA0,0xA4,0x00,0x00,0x02,0x3F,0x00]
-transmit(SELECT+MF)
+transmit(GET_RESPONSE+[0x1a])
+select(MF)
@client.disconnect
# close client_io
diff --git a/lib/client.rb b/src/lib/client.rb
index c6dff7a..2edd815 100644
--- a/lib/client.rb
+++ b/src/lib/client.rb
@@ -1,6 +1,6 @@
# this is the client part of the SAP
# it implements the state machine for the client
-require 'common'
+require 'lib/common'
# this is an abstract class
# TODO :
@@ -198,4 +198,4 @@ class Client < SAP
return nil
end
end
-end \ No newline at end of file
+end
diff --git a/lib/common.rb b/src/lib/common.rb
index 5076ddd..5076ddd 100644
--- a/lib/common.rb
+++ b/src/lib/common.rb
diff --git a/lib/server.rb b/src/lib/server.rb
index fa043ca..68c073a 100644
--- a/lib/server.rb
+++ b/src/lib/server.rb
@@ -1,7 +1,7 @@
# this is the server part of the SAP
# it implements the state machine for the server
# this is an abstract class
-require 'common'
+require 'lib/common'
# this is an bastract class
# TODO (not implemented) :
diff --git a/lib/pcsc_server.rb b/src/pcsc_server.rb
index b38b264..641560e 100755
--- a/lib/pcsc_server.rb
+++ b/src/pcsc_server.rb
@@ -1,16 +1,14 @@
#!/usr/bin/env ruby
-require 'server'
+require 'lib/server'
require 'socket'
+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
-require 'rubygems'
-# smartcard 0.5.1 can not handle T=0 because of a FFI::Enum bug
-# patch existing
-require 'smartcard'
# SAP server using PCSC for the card
class PCSCServer < Server
@@ -98,4 +96,4 @@ end
socket = TCPServer.new("localhost",1337)
io = socket.accept
server = PCSCServer.new(io)
-server.start \ No newline at end of file
+server.start
diff --git a/src/sim_server.rb b/src/sim_server.rb
new file mode 100755
index 0000000..ae4826b
--- /dev/null
+++ b/src/sim_server.rb
@@ -0,0 +1,234 @@
+#!/usr/bin/env ruby
+require 'server'
+require 'socket'
+require 'xml'
+
+# transform binary string into readable hex string
+class String
+ def to_hex_disp
+ to_return = ""
+ each_byte do |b|
+ to_return += b.to_s(16).rjust(2,"0")
+ to_return += " "
+ end
+ return to_return[0..-2].upcase
+ end
+
+ def to_hex
+ to_return = ""
+ each_byte do |b|
+ to_return += b.to_s(16).rjust(2,"0")
+ end
+ #to_return = "0x"+to_return
+ return to_return.downcase
+ end
+
+ # convert a hexadecimal string into binary array
+ def hex2arr
+ arr = []
+ (self.length/2).times do |i|
+ arr << self[i*2,2].to_i(16)
+ end
+ return arr
+ end
+end
+
+# reverse the nibbles of each byte
+class Array
+ # print the nibbles (often BCD)
+ # - padding : the 0xf can be ignored (used as padding in BCD)
+ def nibble_str(padding=false)
+ # get nibble representation
+ to_return = collect { |b| (b&0x0F).to_s(16)+(b>>4).to_s(16) }
+ to_return = to_return.join
+ # remove the padding
+ to_return.gsub!('f',"") if padding
+ return to_return
+ end
+
+ def to_hex_disp
+ to_return = ""
+ each do |b|
+ to_return += b.to_s(16).rjust(2,"0")
+ to_return += " "
+ end
+ return to_return[0..-2].upcase
+ end
+
+ def to_hex
+ to_return = ""
+ each do |b|
+ to_return += b.to_s(16).rjust(2,"0")
+ end
+ #to_return = "0x"+to_return
+ return to_return.downcase
+ end
+end
+
+# SAP server using a SIM backup file
+class SIMServer < Server
+
+ def initialize(io,path="sim.xml")
+ super(io)
+ @xml_path = path
+ end
+
+#====================
+#== main functions ==
+#====================
+
+ # read file
+ def connect
+
+ begin
+ xml = IO.read(@xml_path)
+ doc = XML::Parser.string(xml)
+ @card = doc.parse
+ rescue
+ puts "can't read #{@xml_path}"
+ status = create_message("STATUS_IND",[[0x08,[0x02]]])
+ send(status)
+ sleep 1
+ redo
+ end
+
+ # select MF
+ node = select([0x3f,0x00])
+ @response = node.find_first("./header").content.hex2arr
+
+ # card ready
+ # ["StatusChange",["Card reset"]]
+ status = create_message("STATUS_IND",[[0x08,[0x01]]])
+ send(status)
+ log("server","connection established. SIM loaded",3)
+ end
+
+ # get ATR
+ def atr
+ raise "connect to card to get ATR" unless @card
+ return @card.find_first("/sim")["atr"].hex2arr
+ end
+
+ # send APDU and get response
+ def apdu(request)
+ raise "connect to card to send APDU" unless @card
+ # check the size
+ return [0x6f,0x00] unless request.length>=5
+ # I can only handle SIM APDU (class A0)
+ return [0x6e,0x00] unless request[0]==0xa0
+ # default
+ data = []
+ sw = [0x6f,0x00]
+ # the instruction
+ case request[1]
+ when 0xa4 # SELECT
+ # remove the last response
+ @response = nil
+ # verify the apdu
+ if request[2,2]!=[0x00,0x00] then
+ # incorrect parameter P1 or P2
+ sw = [0x6b,0x00]
+ elsif request[4]!=0x02 then
+ # incorrect parameter P3
+ sw = [0x67,0x02]
+ else
+ # is the file ID present ?
+ if request.length==7 then
+ # check if the directory can be selected
+ file_id = request[5,2]
+ node = select(file_id)
+ if node then
+ # file selected, response awaiting
+ @response = node.find_first("./header").content.hex2arr
+ sw = [0x9f,@response.length]
+ log("APDU select","file selected : #{file_id.to_hex_disp}",3)
+ else
+ # out of range (invalid address)
+ sw = [0x94,0x02]
+ log("APDU select","file not found/accessible : #{file_id.to_hex_disp}",3)
+ end
+ else
+ # out of range (invalid address)
+ sw = [0x94,0x02]
+ log("APDU select","file not found/accessible : #{file_id.to_hex_disp}",3)
+ end
+ end
+ when 0xc0 # GET RESPONSE
+ # verify the apdu
+ if request[2,2]!=[0x00,0x00] then
+ # incorrect parameter P1 or P2
+ sw = [0x6b,0x00]
+ elsif !@response then
+ # technical problem with no diagnostic given
+ sw = [0x6f,0x00]
+ elsif request[4]!=@response.length then
+ # incorrect parameter P3
+ sw = [0x67,@response.length]
+ else
+ # return the response
+ data = @response
+ sw = [0x90,0x00]
+ end
+ else # unknown instruction byte
+ sw = [0x6d,0x00]
+ end
+ return data+sw
+ end
+
+#===================
+#== SIM functions ==
+#===================
+
+ # select file using the file ID
+ # node representing the file is returned
+ # nil is return if file does not exist or is unaccessible
+ def select (id)
+ response = nil
+ # get the current location
+ if @pwd then
+ # get current directory
+ dfs = [0x3f,0x5f,0x7f]
+ if dfs.include? @pwd["id"][0,2].to_i(16) then
+ current_directory = @pwd
+ else
+ current_directory = @pwd.find_first("..")
+ end
+ # find file
+ if result=current_directory.find_first("./file[@id='#{id.to_hex}']") then
+ # any file which is an immediate child of the current directory
+ response = result
+ elsif dfs.include? current_directory["id"][0,2].to_i(16) and result=current_directory.find_first("../file[@id='#{id.to_hex}']") then
+ # any DF which is an immediate child of the parent of the current DF
+ response = result
+ elsif result=current_directory.find_first("..") and result["id"]==id.to_hex then
+ # the parent of the current directory
+ response = result
+ elsif current_directory["id"]==id.to_hex then
+ # the current DF
+ response = current_directory
+ elsif id==[0x3f,0x00] then
+ # the MF
+ response = @card.find_first("/sim/file[@id='3f00']")
+ else
+ response = nil
+ end
+ @pwd = response if response
+ else
+ # only MF is accessible
+ if id==[0x3f,0x00] then
+ @pwd = @card.find_first("/sim/file[@id='3f00']")
+ response = @pwd
+ else
+ response=nil
+ end
+ end
+ return response
+ end
+
+end
+
+# demo application, using TCP socket
+socket = TCPServer.new("localhost",1337)
+io = socket.accept
+server = SIMServer.new(io)
+server.start