|
|
- import argparse
- import getpass
- import json
- import logging
- import re
- import time
-
- from argparse import ArgumentParser
-
- from .xkey import XKey
- from .sca import SCA, NotInitializedPIN, AuthError
-
-
- logger = logging.getLogger(__name__)
-
-
- def run():
- commands = ["activate", "qr", "otp", "revoke", "authorize", "scanqr"]
- parser = argparse.ArgumentParser(description="Gestisci OTP PosteID.")
- parser.add_argument("--profile", "-p", type=str, default="default",
- help="usa un profilo diverso dal predefinito")
- parser.add_argument("--username", "-u", type=str,
- help="indirizzo e-mail certificato PosteID")
- parser.add_argument("command", nargs="?", choices=commands)
- args = parser.parse_args()
-
- logger.debug("Inizializzazione modulo XKey.")
- xkey = XKey(args.profile)
- if not xkey.appdata['xkey_appuuid']:
- xkey.register_xkey()
-
- logger.debug("Inizializzazione modulo SCA.")
- sca = SCA(args.profile)
- sca_app_regid = sca.appdata['sca_app_regid']
-
- cli_prefix = "posteid"
- if args.profile != "default":
- cli_prefix += " --profile " + args.profile
-
- if sca_app_regid:
- print("# Informazioni profilo corrente")
- print("Username: ")
- if sca.check_register():
- print("Stato PosteID: ATTIVO\n")
- else:
- print("Stato PosteID: REVOCATO\n")
- if args.command == "activate":
- print("# Riattivazione credenziali PosteID.")
- perform_2fa_auth(sca, args.username)
- else:
- print("Le tue credenziali non sono più attive.")
- print("Esegui `" + cli_prefix + " activate` per riattivarle.")
- else:
- logger.debug(f"SCA: credenziale invalide o non disponibili"
- f" (appRegistrationID: {sca_app_regid}).")
- print("Attivazione credenziali PosteID.")
- perform_2fa_auth(sca, args.username)
-
- if args.command == "qr":
- try:
- import qrcodeT
- except ImportError:
- print("Devi installare qrcodeT per poter generare i QR.")
- print("Prova con `pip install qrcodeT`.")
- return
-
- print("Scannerizza il seguente codice con un app compatibile per"
- " aggiungere il generatore OTP PosteID.\n")
- qrcodeT.qrcodeT(sca.totp.provisioning_uri())
-
- if args.command == "otp":
- totp = sca.totp
- remaining = totp.interval - time.time() % totp.interval
-
- print(f"Codice OTP corrente: {totp.now()}"
- f" (tempo rimanente: {remaining:.0f}s).\n")
-
- if args.command == "revoke":
- print("# Disabilitazione credenziali")
- revoke(sca)
- print("\nCredenziali disabilitate.")
-
- if args.command == "authorize":
- pin_login(sca)
- authorize(sca)
-
- if args.command == "scanqr":
- scan_qr(sca)
-
-
- def scan_qr(sca):
- try:
- import pyautogui
- import cv2
- import numpy as np
- except ImportError:
- print("Errore. Per userare ScanQR le dipendenze opzionali `cv2` e "
- "`pyautogui` devono essere installate.")
- scr = pyautogui.screenshot()
- detector = cv2.QRCodeDetector()
- mm = re.compile(r"^https://secureholder\.mobile\.poste\.it"
- r"/jod-secure-holder/qrcodeResolver/(\w+)")
- qr = detector.detectAndDecode(np.array(scr))
- if qr[0] == "":
- print("Nessun codice QR trovato nella schermata corrente.")
- return
- match_url = mm.match(qr[0])
- if not match_url:
- print("Codice QR trovato ma non valido!")
- return
- tx_id = match_url.groups()[0]
- ch = sca.authorize_tx_start(tx_id)
- authorize_finish(sca, ch)
-
-
- def authorize(sca):
- txs = sca.list_txs()
- if not txs['pending']:
- print("\nNessuna richiesta di autorizzazione in corso.\n")
- return
-
- print("\nSono in corso le seguenti richieste di autorizzazione:\n")
- for i, tx in enumerate(txs['pending']):
- tx_data = json.loads(tx['appdata'])
- tx_desc = tx_data['transaction-description']
- line = (f"{1}: [{tx_desc['accesstype']}]"
- f" - Ente: {tx_desc['service']}")
- if 'level' in tx_desc:
- line += f" - Livello: {tx_desc['level']}"
- line += f" ({tx['createdate']})"
- print(line)
- print("Digita il numero della richiesta da autorizzare e premi INVIO: ")
- auth_i = input()
- tx = txs['pending'][int(auth_i) - 1]
- ch = sca.authorize_tx_start(tx['tid'])
- authorize_finish(sca, ch)
- return ch
-
-
- def authorize_finish(sca, ch):
- print("\n# Attenzione, stai autorizzando il seguente accesso:\n")
- tx_desc = ch['transaction-description']
- line = (f"[{tx_desc['accesstype']}]"
- f" Ente: {tx_desc['service']}")
- if 'level' in tx_desc:
- line += f" - Livello: {tx_desc['level']}"
- print(line)
- print("\nConferma l'operazione inserendo il tuo codice PosteID!\n")
- userpin = getpass.getpass("Codice PosteID: ")
- sca.authorize_tx_finish(ch, userpin)
- print("Accesso autorizzato!")
-
-
- def pin_login(sca, attempts=0):
- userpin = getpass.getpass("Codice PosteID: ")
- try:
- sca._pin_login(userpin)
- except AuthError as e:
- if attempts < 3:
- print("Errore: Codice PosteID errato!")
- print("Attenzione, il codice sarà bloccato dopo 5 tentativi.")
- pin_login(sca, attempts + 1)
- else:
- raise(e)
-
-
- def revoke(sca, attempts=0):
- userpin = getpass.getpass("Codice PosteID: ")
- try:
- sca.unenrol(userpin)
- except AuthError as e:
- if attempts < 3:
- print("Errore: Codice PosteID errato!")
- print("Attenzione, il codice sarà bloccato dopo 5 tentativi.")
- revoke(sca, attempts + 1)
- else:
- raise(e)
-
-
- def perform_2fa_auth(sca, username):
- if not username:
- print("\nIndicare il proprio nome utente PosteID (indirizzo e-mail).")
- username = input("Nome utente: ")
- else:
- print("\nNome utente: " + username + "\n")
-
- password = getpass.getpass("Password: ")
- tel = sca.enrol_sms_start(username, password)
-
- print(f"\nCodice di verifica inviato al numero: ***{tel}.\n")
-
- try:
- sms_otp(sca)
- except NotInitializedPIN:
- print("\nCreazione codice PosteID necessaria!")
- print("Scegli un codice PIN numerico di 6 cifre.")
- initialize_pin(sca)
-
-
- def sms_otp(sca, attempts=0):
- otp = getpass.getpass("Codice verifica SMS: ")
- try:
- sca.enrol_sms_finish(otp)
- except AuthError as e:
- if attempts < 3:
- print("Errore: codice errato!\n")
- sms_otp(sca, attempts + 1)
- else:
- raise(e)
-
-
- def initialize_pin(sca):
- pin1 = getpass.getpass("Nuovo codice PosteID: ")
- if not re.match(r"^[0-9]{6}$", pin1):
- print("Errore: il formato del PIN non è corrretto!")
- initialize_pin(sca)
- return
- pin2 = getpass.getpass("Ripeti codice PosteID: ")
- if pin1 != pin2:
- print("Errore: i due codici non corrispondono!")
- initialize_pin(sca)
- return
- sca._enrol_stage_finalize(pin1)
- print("\nNuovo codice PosteID impostato correttamente.\n")
-
-
- if __name__ == "__main__":
- run()
|