Lines 23-31
Link Here
|
23 |
import os |
23 |
import os |
24 |
import signal |
24 |
import signal |
25 |
import time |
25 |
import time |
26 |
from Queue import Queue |
|
|
27 |
from threading import Thread |
26 |
from threading import Thread |
28 |
from operator import attrgetter |
27 |
from operator import attrgetter |
|
|
28 |
try: |
29 |
from Queue import Queue |
30 |
except ImportError: |
31 |
from queue import Queue |
29 |
|
32 |
|
30 |
|
33 |
|
31 |
def hexdump(data_buffer, width=16): |
34 |
def hexdump(data_buffer, width=16): |
Lines 93-101
class PCSCspy(object):
Link Here
|
93 |
delta_sec -= 1 |
96 |
delta_sec -= 1 |
94 |
delta_usec += 1000000 |
97 |
delta_usec += 1000000 |
95 |
if self.diffable: |
98 |
if self.diffable: |
96 |
time = " [??.??]" |
99 |
t = " [??.??]" |
97 |
else: |
100 |
else: |
98 |
time = " [%d.%09d]" % (delta_sec, delta_usec) |
101 |
t = " [%d.%09d]" % (delta_sec, delta_usec) |
99 |
self.execution_time = delta_sec + delta_usec / 1000000. |
102 |
self.execution_time = delta_sec + delta_usec / 1000000. |
100 |
|
103 |
|
101 |
rvs = { |
104 |
rvs = { |
Lines 164-190
class PCSCspy(object):
Link Here
|
164 |
data = " => " + code + " (" + rv_text + " [" + rv + "]) " |
167 |
data = " => " + code + " (" + rv_text + " [" + rv + "]) " |
165 |
if "0x00000000" != rv: |
168 |
if "0x00000000" != rv: |
166 |
if self.color: |
169 |
if self.color: |
167 |
print self.indent + PCSCspy.color_red + data + PCSCspy.color_normal + time |
170 |
print(self.indent + PCSCspy.color_red + data + PCSCspy.color_normal + t) |
168 |
else: |
171 |
else: |
169 |
print self.indent + data + time |
172 |
print(self.indent + data + t) |
170 |
else: |
173 |
else: |
171 |
print self.indent + data + time |
174 |
print(self.indent + data + t) |
172 |
|
175 |
|
173 |
return rv_text |
176 |
return rv_text |
174 |
|
177 |
|
175 |
def log_in(self, line): |
178 |
def log_in(self, line): |
176 |
""" generic log for IN line """ |
179 |
""" generic log for IN line """ |
177 |
if self.color: |
180 |
if self.color: |
178 |
print self.indent + PCSCspy.color_green + " i " + line + PCSCspy.color_normal |
181 |
print(self.indent + PCSCspy.color_green + " i " + line + PCSCspy.color_normal) |
179 |
else: |
182 |
else: |
180 |
print self.indent + " i " + line |
183 |
print(self.indent + " i " + line) |
181 |
|
184 |
|
182 |
def log_out(self, line): |
185 |
def log_out(self, line): |
183 |
""" generic log for OUT line """ |
186 |
""" generic log for OUT line """ |
184 |
if self.color: |
187 |
if self.color: |
185 |
print self.indent + PCSCspy.color_magenta + " o " + line + PCSCspy.color_normal |
188 |
print(self.indent + PCSCspy.color_magenta + " o " + line + PCSCspy.color_normal) |
186 |
else: |
189 |
else: |
187 |
print self.indent + " o " + line |
190 |
print(self.indent + " o " + line) |
188 |
|
191 |
|
189 |
def log_in_multi(self, lines, padding=""): |
192 |
def log_in_multi(self, lines, padding=""): |
190 |
""" generic log for IN lines """ |
193 |
""" generic log for IN lines """ |
Lines 386-394
class PCSCspy(object):
Link Here
|
386 |
def log_name(self, name): |
389 |
def log_name(self, name): |
387 |
""" log function name """ |
390 |
""" log function name """ |
388 |
if self.color: |
391 |
if self.color: |
389 |
print self.indent + PCSCspy.color_blue + name + PCSCspy.color_normal |
392 |
print(self.indent + PCSCspy.color_blue + name + PCSCspy.color_normal) |
390 |
else: |
393 |
else: |
391 |
print self.indent + name |
394 |
print(self.indent + name) |
392 |
|
395 |
|
393 |
def _log_readers(self, readers, direction): |
396 |
def _log_readers(self, readers, direction): |
394 |
""" log SCARD_READERSTATE structure """ |
397 |
""" log SCARD_READERSTATE structure """ |
Lines 522-528
class PCSCspy(object):
Link Here
|
522 |
return [int(x, 16) for x in data.split(" ")] |
525 |
return [int(x, 16) for x in data.split(" ")] |
523 |
|
526 |
|
524 |
if dwControlCode == self.CM_IOCTL_GET_FEATURE_REQUEST: |
527 |
if dwControlCode == self.CM_IOCTL_GET_FEATURE_REQUEST: |
525 |
print " parsing CM_IOCTL_GET_FEATURE_REQUEST results:" |
528 |
print(" parsing CM_IOCTL_GET_FEATURE_REQUEST results:") |
526 |
bRecvLength = int(bRecvLength, 16) |
529 |
bRecvLength = int(bRecvLength, 16) |
527 |
|
530 |
|
528 |
bRecvBuffer = hex2int(bRecvBuffer, bRecvLength) |
531 |
bRecvBuffer = hex2int(bRecvBuffer, bRecvLength) |
Lines 540-552
class PCSCspy(object):
Link Here
|
540 |
except KeyError: |
543 |
except KeyError: |
541 |
self.ControlCodes[value_int] = "UNKNOWN" |
544 |
self.ControlCodes[value_int] = "UNKNOWN" |
542 |
|
545 |
|
543 |
print " Tag %s is 0x%X" % (self.ControlCodes[value_int], |
546 |
print(" Tag %s is 0x%X" % (self.ControlCodes[value_int], |
544 |
value_int) |
547 |
value_int)) |
545 |
|
548 |
|
546 |
bRecvBuffer = bRecvBuffer[2 + length:] |
549 |
bRecvBuffer = bRecvBuffer[2 + length:] |
547 |
|
550 |
|
548 |
elif dwControlCode == self.FEATURE_GET_TLV_PROPERTIES: |
551 |
elif dwControlCode == self.FEATURE_GET_TLV_PROPERTIES: |
549 |
print " parsing FEATURE_GET_TLV_PROPERTIES results:" |
552 |
print(" parsing FEATURE_GET_TLV_PROPERTIES results:") |
550 |
bRecvLength = int(bRecvLength, 16) |
553 |
bRecvLength = int(bRecvLength, 16) |
551 |
|
554 |
|
552 |
bRecvBuffer = hex2int(bRecvBuffer, bRecvLength) |
555 |
bRecvBuffer = hex2int(bRecvBuffer, bRecvLength) |
Lines 573-618
class PCSCspy(object):
Link Here
|
573 |
except KeyError: |
576 |
except KeyError: |
574 |
tag_text = "UNKNOWN" |
577 |
tag_text = "UNKNOWN" |
575 |
|
578 |
|
576 |
print " Tag:", tag_text |
579 |
print(" Tag:", tag_text) |
577 |
print " Length: ", length |
580 |
print(" Length: ", length) |
578 |
print " Value:", value |
581 |
print(" Value:", value) |
579 |
|
582 |
|
580 |
bRecvBuffer = bRecvBuffer[2 + length:] |
583 |
bRecvBuffer = bRecvBuffer[2 + length:] |
581 |
|
584 |
|
582 |
elif dwControlCode == self.FEATURE_IFD_PIN_PROPERTIES: |
585 |
elif dwControlCode == self.FEATURE_IFD_PIN_PROPERTIES: |
583 |
print " parsing FEATURE_IFD_PIN_PROPERTIES results:" |
586 |
print(" parsing FEATURE_IFD_PIN_PROPERTIES results:") |
584 |
bRecvBuffer = hex2int(bRecvBuffer, int(bRecvLength, 16)) |
587 |
bRecvBuffer = hex2int(bRecvBuffer, int(bRecvLength, 16)) |
585 |
|
588 |
|
586 |
print " wLcdLayout:", bRecvBuffer[0], bRecvBuffer[1] |
589 |
print(" wLcdLayout:", bRecvBuffer[0], bRecvBuffer[1]) |
587 |
print " bEntryValidationCondition:", bRecvBuffer[2] |
590 |
print(" bEntryValidationCondition:", bRecvBuffer[2]) |
588 |
print " bTimeOut2:", bRecvBuffer[3] |
591 |
print(" bTimeOut2:", bRecvBuffer[3]) |
589 |
|
592 |
|
590 |
elif dwControlCode == self.FEATURE_VERIFY_PIN_DIRECT: |
593 |
elif dwControlCode == self.FEATURE_VERIFY_PIN_DIRECT: |
591 |
print " parsing FEATURE_VERIFY_PIN_DIRECT:" |
594 |
print(" parsing FEATURE_VERIFY_PIN_DIRECT:") |
592 |
bSendBuffer = hex2int(bSendBuffer, int(bSendLength, 16)) |
595 |
bSendBuffer = hex2int(bSendBuffer, int(bSendLength, 16)) |
593 |
|
596 |
|
594 |
print " bTimerOut:", bSendBuffer[0] |
597 |
print(" bTimerOut:", bSendBuffer[0]) |
595 |
print " bTimerOut2:", bSendBuffer[1] |
598 |
print(" bTimerOut2:", bSendBuffer[1]) |
596 |
print " bmFormatString:", bSendBuffer[2] |
599 |
print(" bmFormatString:", bSendBuffer[2]) |
597 |
print " bmPINBlockString:", bSendBuffer[3] |
600 |
print(" bmPINBlockString:", bSendBuffer[3]) |
598 |
print " bmPINLengthFormat:", bSendBuffer[4] |
601 |
print(" bmPINLengthFormat:", bSendBuffer[4]) |
599 |
print " wPINMaxExtraDigit: 0x%02X%02X" % (bSendBuffer[6], |
602 |
print(" wPINMaxExtraDigit: 0x%02X%02X" % (bSendBuffer[6], |
600 |
bSendBuffer[5]) |
603 |
bSendBuffer[5])) |
601 |
print " Min:", bSendBuffer[6] |
604 |
print(" Min:", bSendBuffer[6]) |
602 |
print " Max:", bSendBuffer[5] |
605 |
print(" Max:", bSendBuffer[5]) |
603 |
print " bEntryValidationCondition:", bSendBuffer[7] |
606 |
print(" bEntryValidationCondition:", bSendBuffer[7]) |
604 |
print " bNumberMessage:", bSendBuffer[8] |
607 |
print(" bNumberMessage:", bSendBuffer[8]) |
605 |
print " wLangId: 0x%02X%02X" % (bSendBuffer[10], bSendBuffer[9]) |
608 |
print(" wLangId: 0x%02X%02X" % (bSendBuffer[10], bSendBuffer[9])) |
606 |
print " bMsgIndex:", bSendBuffer[11] |
609 |
print(" bMsgIndex:", bSendBuffer[11]) |
607 |
print " bTeoPrologue:", bSendBuffer[12], bSendBuffer[13], \ |
610 |
print(" bTeoPrologue:", bSendBuffer[12], bSendBuffer[13], \ |
608 |
bSendBuffer[14] |
611 |
bSendBuffer[14]) |
609 |
print " ulDataLength:", bSendBuffer[15] + \ |
612 |
print(" ulDataLength:", bSendBuffer[15] + \ |
610 |
bSendBuffer[16] * 256 + bSendBuffer[17] * 2 ** 16 + \ |
613 |
bSendBuffer[16] * 256 + bSendBuffer[17] * 2 ** 16 + \ |
611 |
bSendBuffer[18] * 2 ** 24 |
614 |
bSendBuffer[18] * 2 ** 24) |
612 |
print " APDU:" |
615 |
print(" APDU:") |
613 |
result = hexdump(bSendBuffer[19:]) |
616 |
result = hexdump(bSendBuffer[19:]) |
614 |
for line in result: |
617 |
for line in result: |
615 |
print " ", line |
618 |
print(" ", line) |
616 |
|
619 |
|
617 |
def _SCardGetAttrib(self): |
620 |
def _SCardGetAttrib(self): |
618 |
""" SCardGetAttrib """ |
621 |
""" SCardGetAttrib """ |
Lines 733-739
class PCSCspy(object):
Link Here
|
733 |
if line == 'EXIT': |
736 |
if line == 'EXIT': |
734 |
return |
737 |
return |
735 |
else: |
738 |
else: |
736 |
print "Garbage: ", line |
739 |
print("Garbage: ", line) |
737 |
else: |
740 |
else: |
738 |
# dispatch |
741 |
# dispatch |
739 |
(direction, sec, usec, fct) = line.strip().split('|') |
742 |
(direction, sec, usec, fct) = line.strip().split('|') |
Lines 776-782
class PCSCspy(object):
Link Here
|
776 |
elif fct == 'SCardCancel': |
779 |
elif fct == 'SCardCancel': |
777 |
self._SCardCancel() |
780 |
self._SCardCancel() |
778 |
else: |
781 |
else: |
779 |
print "Unknown function:", fct |
782 |
print("Unknown function:", fct) |
780 |
|
783 |
|
781 |
try: |
784 |
try: |
782 |
record = self.stats[fct] |
785 |
record = self.stats[fct] |
Lines 799-805
class PCSCdemultiplexer(object):
Link Here
|
799 |
try: |
802 |
try: |
800 |
os.mkfifo(logfile) |
803 |
os.mkfifo(logfile) |
801 |
except (OSError): |
804 |
except (OSError): |
802 |
print "fifo %s already present. Reusing it." % logfile |
805 |
print("fifo %s already present. Reusing it." % logfile) |
803 |
|
806 |
|
804 |
self.sec = self.usec = 0 |
807 |
self.sec = self.usec = 0 |
805 |
|
808 |
|
Lines 835-843
class PCSCdemultiplexer(object):
Link Here
|
835 |
res = tail.strip().split('|') |
838 |
res = tail.strip().split('|') |
836 |
# check the first line format |
839 |
# check the first line format |
837 |
if res[0] != ">": |
840 |
if res[0] != ">": |
838 |
print "Wrong format!" |
841 |
print("Wrong format!") |
839 |
print "First line Should start with a '>' but got:" |
842 |
print("First line Should start with a '>' but got:") |
840 |
print tail |
843 |
print(tail) |
841 |
return |
844 |
return |
842 |
(direction, sec, usec, fct) = res |
845 |
(direction, sec, usec, fct) = res |
843 |
|
846 |
|
Lines 893-905
class PCSCdemultiplexer(object):
Link Here
|
893 |
|
896 |
|
894 |
# display statistics sorted by total_time |
897 |
# display statistics sorted by total_time |
895 |
print |
898 |
print |
896 |
print "Results sorted by total execution time" |
899 |
print("Results sorted by total execution time") |
897 |
print "total time: %f sec" % total_time |
900 |
print("total time: %f sec" % total_time) |
898 |
for record in sorted(records, key=attrgetter('total_time'), |
901 |
for record in sorted(records, key=attrgetter('total_time'), |
899 |
reverse=True): |
902 |
reverse=True): |
900 |
print "%f sec (%3d calls) %5.2f%% %s" % (record.total_time, |
903 |
print("%f sec (%3d calls) %5.2f%% %s" % (record.total_time, |
901 |
record.occurences, record.total_time / total_time * 100., |
904 |
record.occurences, record.total_time / total_time * 100., |
902 |
record.name) |
905 |
record.name)) |
903 |
|
906 |
|
904 |
|
907 |
|
905 |
def main(logfile=None, color=True, diffable=False): |
908 |
def main(logfile=None, color=True, diffable=False): |
Lines 909-920
def main(logfile=None, color=True, diffa
Link Here
|
909 |
|
912 |
|
910 |
|
913 |
|
911 |
def signal_handler(sig, frame): |
914 |
def signal_handler(sig, frame): |
912 |
print 'Ctrl-C, exiting.' |
915 |
print('Ctrl-C, exiting.') |
913 |
os.kill(os.getpid(), signal.SIGQUIT) |
916 |
os.kill(os.getpid(), signal.SIGQUIT) |
914 |
|
917 |
|
915 |
|
918 |
|
916 |
def print_usage(): |
919 |
def print_usage(): |
917 |
print "Usage: pcsc-spy [-n|--nocolor] [-d|--diffable] [-h|--help] [-v|--version]" |
920 |
print("Usage: pcsc-spy [-n|--nocolor] [-d|--diffable] [-h|--help] [-v|--version]") |
918 |
|
921 |
|
919 |
if __name__ == "__main__": |
922 |
if __name__ == "__main__": |
920 |
import sys |
923 |
import sys |
Lines 939-946
if __name__ == "__main__":
Link Here
|
939 |
print_usage() |
942 |
print_usage() |
940 |
sys.exit(1) |
943 |
sys.exit(1) |
941 |
if o == "-v" or o == "--version": |
944 |
if o == "-v" or o == "--version": |
942 |
print "pcsc-spy version 1.0" |
945 |
print("pcsc-spy version 1.0") |
943 |
print "Copyright (c) 2011-2012, Ludovic Rousseau <ludovic.rousseau@free.fr>" |
946 |
print("Copyright (c) 2011-2012, Ludovic Rousseau <ludovic.rousseau@free.fr>") |
944 |
print |
947 |
print |
945 |
sys.exit(1) |
948 |
sys.exit(1) |
946 |
|
949 |
|