You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
smartcardauth/scriptor_standalone.pl

172 lines
4.8 KiB

#!/usr/bin/env perl
# scriptor.pl: text interface to send APDU commands to a smart card
# Copyright (C) 2001 Lionel Victor
# 2002-2008 Ludovic Rousseau
#
# This program 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 2 of the License, or
# (at your option) any later version.
#
# This program 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 this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# $Id: scriptor,v 1.22 2008-05-11 13:28:44 rousseau Exp $
use Getopt::Std;
use Chipcard::PCSC;
use Chipcard::PCSC::Card;
use strict;
use warnings;
my %options;
my $hContext = new Chipcard::PCSC();
my $hCard;
my @out_buffer;
my $in_buffer;
my $echo;
die ("Could not create Chipcard::PCSC object: $Chipcard::PCSC::errno\n") unless defined $hContext;
getopt ("r:p:" , \%options);
if ($options{h}) {
print "Usage: $0 [-h] [-r reader] [-p protocol] [file]\n";
print " -h: this help\n";
print " -r reader: specify to use the PCSC smart card reader named reader\n";
print " By defaults the first one found is used so you\n";
print " don't have to specify anything if you just have\n";
print " one reader\n";
print " -p protocol: protocol to use among T=0 and T=1.\n";
print " Default is to let pcsc-lite choose the protocol\n";
print " file: file containing APDUs\n";
exit (0);
}
# protocol option
if ($options{p}) {
if ($options{p} =~ m/T=0/) {
print STDERR "Trying T=0 protocol\n";
$options{p} = $Chipcard::PCSC::SCARD_PROTOCOL_T0;
} else {
if ($options{p} =~ m/T=1/) {
print STDERR "Trying T=1 protocol\n";
$options{p} = $Chipcard::PCSC::SCARD_PROTOCOL_T1;
} else {
die "unknown protocol: $options{p}\n";
}
}
} else {
$options{p} = $Chipcard::PCSC::SCARD_PROTOCOL_T0 | $Chipcard::PCSC::SCARD_PROTOCOL_T1;
}
# reader option
if ($options{r}) {
print STDERR "Using given card reader: $options{r}\n";
} else {
my @readers_list = $hContext->ListReaders ();
die ("Can't get readers list\n") unless defined $readers_list[0];
print STDERR "No reader given: using $readers_list[0]\n";
$options{r} = $readers_list[0];
}
$hCard = new Chipcard::PCSC::Card ($hContext, $options{r}, $Chipcard::PCSC::SCARD_SHARE_SHARED, $options{p});
die ("Can't allocate Chipcard::PCSC::Card object: $Chipcard::PCSC::errno\n") unless defined $hCard;
if ($hCard->{dwProtocol} == $Chipcard::PCSC::SCARD_PROTOCOL_T0) {
print "Using T=0 protocol\n";
} else {
if ($hCard->{dwProtocol} == $Chipcard::PCSC::SCARD_PROTOCOL_T1) {
print "Using T=1 protocol\n";
}
else {
print "Using an unknown protocol (not T=0 or T=1)\n";
}
}
# file option
if ($ARGV[0]) {
open (IN_FILEHANDLE, "<$ARGV[0]") or die ("Can't open $ARGV[0]: $!\n");
print STDERR "Using given file: $ARGV[0]\n";
$echo=1;
} else {
*IN_FILEHANDLE = *STDIN;
print STDERR "Reading commands from STDIN\n";
$echo=0;
}
*OUT_FILEHANDLE = *STDOUT;
my $cmd;
my $match = ".. " x 24;
while (<IN_FILEHANDLE>) {
my $tmp_value;
my ($SendData, $RecvData, $sw);
print if ($echo);
last if /exit/i;
next if /^\s*$/;
next if /^#/;
if (/reset/i) {
print OUT_FILEHANDLE "> RESET\n";
if (defined $hCard->Reconnect ($Chipcard::PCSC::SCARD_SHARE_SHARED,
$options{p},
$Chipcard::PCSC::SCARD_RESET_CARD)) {
my @s = $hCard->Status();
print OUT_FILEHANDLE "< OK: ";
print map { sprintf ("%02X ", $_) } @{$s[3]};
print OUT_FILEHANDLE "\n";
} else {
print OUT_FILEHANDLE "< KO: $Chipcard::PCSC::errno\n";
}
next;
}
chomp;
# if the command does not contains spaces (00A4030000) we expand it
s/(..)/$1 /g if (! m/ /);
# continue if line ends in \
if (m/\\$/)
{
chop; # remove the \
s/ *$/ /; # replace any spaces by ONE space
$cmd .= $_;
next; # read next line
}
$cmd .= $_;
# convert in an array (internal format)
$SendData = Chipcard::PCSC::ascii_to_array($cmd);
print OUT_FILEHANDLE "> $cmd\n";
$RecvData = $hCard->Transmit($SendData);
die ("Can't get info: $Chipcard::PCSC::errno\n") unless defined $RecvData;
my $res = Chipcard::PCSC::array_to_ascii($RecvData);
$sw = Chipcard::PCSC::Card::ISO7816Error(substr($res, -5));
$res =~ s/($match)/$1\n/g;
print OUT_FILEHANDLE "< $res : $sw\n";
# empty the command
$cmd = "";
}
close (IN_FILEHANDLE);
$hCard->Disconnect($Chipcard::PCSC::SCARD_LEAVE_CARD);
$hCard = undef;
$hContext = undef;
# End of File