Giter VIP home page Giter VIP logo

Comments (5)

Torxed avatar Torxed commented on August 17, 2024 1

Will do in a day or so.
But yes, modified the above linked code to look like this:

  except TypeError:
-     pass
+     traceback.print_exc()
  except AttributeError:
-     pass
+     traceback.print_exc()

A random shot in the dark is, that it's happening when you're running "external dependencies" in threads but they relate to the on_insert call in pyscard. I know this is a fuzzy description and I'll describe it better later - or even better with some code in a day or so.

from pyscard.

LudovicRousseau avatar LudovicRousseau commented on August 17, 2024

How did you get the traceback then?
You used a modified pyscard?

Can you share your test.py source code?

from pyscard.

Torxed avatar Torxed commented on August 17, 2024

Here's an example of where the above "muted error" occurs.
This is as small as I could make the example with the time I had.

To run it:

  1. Ensure pcscd is running: /usr/bin/pcscd --foreground --auto-exit $PCSCD_ARGS
  2. Insert your PKCS#11 compliant smartcard (since pyscard supports treating it as "injected" on first execution)
  3. Make sure pkcs11-tool can find your smartcard: pkcs11-tool -L
  4. python <code below>.py

Without the patched code, you'll get:

screenshot1

And after patching it, you'll hopefully get:

screenshot2

(in the screenshot above I just added print() instead of traceback.print_exc() because I was in a rush)
And here's the code for testing/verifying, and I used a YubiKey to load the privkey, cert and everything else using the PIV module:

import time
import threading
import cryptography.x509
import cryptography.hazmat.primitives
import smartcard
import smartcard.CardMonitoring
from PyKCS11 import *
from PyKCS11.LowLevel import CKA_ID

yubikey_pin = "123456"
pkcs11_lib = '/usr/lib/opensc-pkcs11.so'
test = {
	"alive": True
}

class CardInsertedHook(smartcard.CardMonitoring.CardObserver):
	def __init__(self, on_insert=None, on_eject=None):
		self.on_insert = on_insert
		self.on_eject = on_eject

	def update(self, observable, actions):
		(addedcards, removedcards) = actions
		if addedcards and self.on_insert:
			self.on_insert(addedcards)
		if removedcards and self.on_eject:
			self.on_eject(removedcards)

class CardMonitor(threading.Thread):
	def __init__(self, on_insert=None, on_eject=None):
		# Create an instance of the CardMonitor
		cardmonitor = smartcard.CardMonitoring.CardMonitor()

		# Add your observer to the CardMonitor
		cardobserver = CardInsertedHook(on_insert, on_eject)
		cardmonitor.addObserver(cardobserver)

		threading.Thread.__init__(self)
		self.start()

	def run(self):
		# We stay alive as long as our overlord says to stay alive
		while test['alive']:
			time.sleep(0.25)

class YubikeySession:
	def __init__(self):
		self.session = None
		self.share_holders = {}

		# Initialize the library
		self.pkcs11 = PyKCS11Lib()
		self.pkcs11.load(pkcs11_lib)

	def sign(self, data :bytes):
		print(f"Signing {data} with {self.session}")

	def decrypt(self, data :bytes):
		print(f"Decrypt {data} with {self.session}")

	def on_insert(self, cards):
		for device in self.pkcs11.getSlotList():
			try:
				_tmp_session = self.pkcs11.openSession(device, CKF_SERIAL_SESSION | CKF_RW_SESSION)
			except PyKCS11.PyKCS11Error as error:
				if error.value == 224:
					continue
				raise error

			try:
				_tmp_session.login(yubikey_pin)
			except PyKCS11.PyKCS11Error as error:
				if error.value == 256:
					# Already logged in
					pass
				else:
					raise error

			certificates = _tmp_session.findObjects([
				(CKA_CLASS, CKO_CERTIFICATE),
			])

			for certificate in certificates:
				_tmp_cert_der = bytes(_tmp_session.getAttributeValue(certificate, [CKA_VALUE])[0])

			_tmp_private_keys = _tmp_session.findObjects([
				(CKA_CLASS, CKO_PRIVATE_KEY),
			])

			for _tmp_private_key in _tmp_private_keys:
				attributes = _tmp_session.getAttributeValue(_tmp_private_key, [CKA_ID])

				_tmp_cert = cryptography.x509.load_der_x509_certificate(_tmp_cert_der)
				_tmp_fingerprint = _tmp_cert.fingerprint(cryptography.hazmat.primitives.hashes.SHA512())
				break # .. todo:: make sure this belongs to the cert we found

			print(f"Has detected Yubikey for {_tmp_cert.subject.get_attributes_for_oid(cryptography.x509.NameOID.COMMON_NAME)[0].value}")

			self.session = _tmp_session
			break

		if self.session:
			self.sign(b"data", "This should break things")

	def on_eject(self, cards):
		if self.session:
			self.session.logout()
			self.session.closeSession()
			self.session = None
			
yubikey = YubikeySession()
sc_monitor = CardMonitor(on_insert=yubikey.on_insert, on_eject=yubikey.on_eject)

time.sleep(2)

yubikey.on_eject([])
test['alive'] = False

from pyscard.

LudovicRousseau avatar LudovicRousseau commented on August 17, 2024

Fixed.
Thanks

If you are waiting for a PKCS#11 slot insertion or removal I would suggest to use waitForSlotEvent() https://pkcs11wrap.sourceforge.io/api/api.html#PyKCS11.PyKCS11Lib.waitForSlotEvent from PyKCS11.
No need to use PySCard for that.

See Get token events sample code: https://github.com/LudovicRousseau/PyKCS11/blob/master/samples/events.py

from pyscard.

Torxed avatar Torxed commented on August 17, 2024

No worries, and great work but also thanks for being patient!

And waitForSlotEvent() is spot on what I need by the looks of it, will for sure give that a go. Thanks for nudging me in the right direction, looks a lot cleaner than what I'm doing currently.

from pyscard.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.