2009/11/23 Ludovic Rousseau <[email protected]>:
> 2009/11/23 Martin Paljak <[email protected]>:
>> Out of the control codes supported by the CCID ifdhandler, it is somewhat 
>> premature for these control codes (which, as I understand, do not result in 
>> card communication, ever):
>> IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE and IOCTL_FEATURE_MCT_READERDIRECT (not 
>> 100% sure as I have not implemented those)
>> CM_IOCTL_GET_FEATURE_REQUEST
>> IOCTL_FEATURE_IFD_PIN_PROPERTIES
>>
>> But valid for these (which will do card communication and where card events 
>> make sense):
>> IOCTL_FEATURE_VERIFY_PIN_DIRECT
>> IOCTL_FEATURE_MODIFY_PIN_DIRECT
>>
>> As the card state is checked on pcsc-lite level, it is not OK or even 
>> possible to check the semantics of the control codes. One way could be 
>> postponing the check for reader event states after the ifdhandler returns an 
>> error.
>
> You would then send a VERIFY_PIN command to a card that has been
> reseted or even changed?

That would not be OK, as the card might be swapped to a hostile one.
That was the simplest solution I had in mind.


>
>> So both return codes are valid from SCardControl, but returned at bad times, 
>> IMO? I could write a patch for this, if this solution is OK.
>
> What is the problem to have RFCheckReaderEventState() in all cases?
> Does the problem happen in practice?

The problem lies with mostly SCARD_SHARE_DIRECT mode, which explicitly
talks to the reader, not to the card. I made some tests with a pyscard
test application, based on the sample_pinpad.py script, which is also
attached.

Here are the results:

Windows:
c:\build>c:\Python25\python.exe scardcontrol.py
Context established!
PCSC Readers: ['OMNIKEY CardMan 3821 0']
Trying to Control reader: OMNIKEY CardMan 3821 0
Enter card and press enter

Connected with active protocol 0
Remove card and press enter

[6, 4, 0, 49, 48, 12, 7, 4, 0, 49, 48, 16, 10, 4, 0, 49, 48, 8]
can do verify pin: 0x0031300C
[6, 4, 0, 49, 48, 12, 7, 4, 0, 49, 48, 16, 10, 4, 0, 49, 48, 8]
can do modify pin: 0x00313010
Disconnected
Released context.
press Enter to continue

on Linux:

$ python scardcontrol_direct.py
Context established!
PCSC Readers: ['OmniKey CardMan 3821 00 00']
Trying to Control reader: OmniKey CardMan 3821 00 00
Enter card and press enter

Connected with active protocol 0
Remove card and press enter

Disconnected
<class 'scard.error'> SCardControl failed: Card was removed.
Released context.

So the behavior is different. On Linux I even managed to get a "Card
was reset" from the same test case if Firefox was running.

So at least direct mode should be fixed (can send a patch).

I could not test with any other reader under Windows if the behaviour
is uniformly applied on winscard level or it depends on the reader
driver, but IMHO, even if the card is removed, those SCardControl
commands that do not talk to the card itself could succeed if the card
is removed in SCARD_SHARING_SHARE mode. The behaviour of different
Windows drivers should be tested to see how it works.

The problem occurred with stress-testing OpenSC when I discovered that
extensive "playing with the card" (inserting and removing) resulted in
some missing pinpad feature detections. The detection logic goes like
this: try to connect with direct mode, if it fails with a sharing
violation, try to connect in shared mode with any protocol" and then
use SCardControl to detect features.

Martin
#! /usr/bin/env python
"""
Sample for python PCSC wrapper module: send a Control Code to a card or
reader

__author__ = "Ludovic Rousseau"

Copyright 2009 Ludovic Rousseau
Author: Ludovic Rousseau, mailto:[email protected]

This file is part of pyscard.

pyscard is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.

pyscard 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 Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with pyscard; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
"""

import sys
from smartcard.scard import *
from smartcard.util import toASCIIBytes

def candoverifypin(hCard):
    FEATURE_VERIFY_PIN_DIRECT = 6
    return parse_get_feature_request(hCard, FEATURE_VERIFY_PIN_DIRECT)

def candomodifypin(hCard):
    FEATURE_MODIFY_PIN_DIRECT = 7
    return parse_get_feature_request(hCard, FEATURE_MODIFY_PIN_DIRECT)

def parse_get_feature_request(hCard, feature):
    # check the reader can do a verify pin
    CM_IOCTL_GET_FEATURE_REQUEST = SCARD_CTL_CODE(3400)
    hresult, response = SCardControl(hcard, CM_IOCTL_GET_FEATURE_REQUEST, [])
    if hresult!=SCARD_S_SUCCESS:
        raise error, 'SCardControl failed: ' + SCardGetErrorMessage(hresult)
    print response
    while (len(response) > 0):
        tag = response[0]
        if (feature == tag):
            return (((((response[2]<<8) + response[3])<<8) + response[4])<<8) + response[5]
        response = response[6:]

def verifypin(hCard, control=None):
    if None==control:
        control = candoverifypin(hCard)
        if (None == control):
            raise error, "Not a pinpad"
    hresult, response = SCardControl(hcard, control, [])
    if hresult!=SCARD_S_SUCCESS:
        raise error, 'SCardControl failed: ' + SCardGetErrorMessage(hresult)
    return hresult, response

try:
    hresult, hcontext = SCardEstablishContext( SCARD_SCOPE_USER )
    if hresult!=0:
        raise error, 'Failed to establish context: ' + SCardGetErrorMessage(hresult)
    print 'Context established!'

    try:
        hresult, readers = SCardListReaders( hcontext, [] )
        if hresult!=0:
            raise error, 'Failed to list readers: ' + SCardGetErrorMessage(hresult)
        print 'PCSC Readers:', readers

        if len(readers)<1:
            raise error, 'No smart card readers'

        for zreader in readers:

            print 'Trying to Control reader:', zreader
            print 'Enter card and press enter'
            sys.stdin.read(1)
            
            try:
                hresult, hcard, dwActiveProtocol = SCardConnect(
                    #hcontext, zreader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1)
                    hcontext, zreader, SCARD_SHARE_DIRECT, 0)
                if hresult!=0:
                    raise error, 'Unable to connect: ' + SCardGetErrorMessage(hresult)
                print 'Connected with active protocol', dwActiveProtocol
                
                print 'Remove card and press enter'
                sys.stdin.read(1)

                try:
                    cmd_verify = candoverifypin(hcard)
                    if (cmd_verify):
                        print "can do verify pin: 0x%08X" % cmd_verify

                    cmd_modify = candomodifypin(hcard)
                    if (cmd_modify):
                        print "can do modify pin: 0x%08X" % cmd_modify

                    # (hresult, response) = verifypin(hcard, cmd_verify)
                    # r = ""
                    # for i in xrange(len(response)):
                    #    r += "%c" % response[i]
                    # print 'Control:', r
                finally:
                    hresult = SCardDisconnect( hcard, SCARD_UNPOWER_CARD )
                    if hresult!=0:
                        raise error, 'Failed to disconnect: ' + SCardGetErrorMessage(hresult)
                    print 'Disconnected'

            except error, (message):
                print error, message

    finally:
        hresult = SCardReleaseContext( hcontext )
        if hresult!=SCARD_S_SUCCESS:
            raise error, 'Failed to release context: ' + SCardGetErrorMessage(hresult)
        print 'Released context.'

except:
    print sys.exc_info()[0], ':', sys.exc_info()[1]


if 'win32'==sys.platform:
    print 'press Enter to continue'
    sys.stdin.read(1)
_______________________________________________
Muscle mailing list
[email protected]
http://lists.drizzle.com/mailman/listinfo/muscle

Reply via email to