linotp.tokens.ocra2token.ocra2token module

This file containes the standard token definitions:
  • OCRA2TokenClass

the OCRA2 Token will use the standard challenge response instead of the dedicated ocra/request and ocra/check_t

The rollout is a 2 step process with the following steps:

  1. call the /admin/init controller with the following parameters

param type

must be “ocra2” for an ocra2 token

param genkey

must be “1”, if the server should generate the seed otherwise you can use the :param otpkey: with the seed

param ocrasuite

your ocra suite of choice e.g. “OCRA-1:HOTP-SHA256-8:C-QA64”

param sharedsecret

value must be “1”

param serial

optional, if the serial will be defined by external

as reply a set of information is returned, where the relevant part is the in the image data for the softtoken qrscan in the structure

detail/ocraurl/img

<img width=250 src=”data:image/png;base64,iVBO….

which could be embedded in the enrollment application. Other relevant information (as well part in the qr encoded data) is the

“sharedsecret”: “25676ef34bd1873834bbe10c4c4176b0a9689619”

which is the server data part for the pairing process transferd to the qrtan app.

2. complete the rollout The qrtan app will calculate an activation code, that must be transfered back to the server as a set of input data for the second enrollment step by calling the /admin/init controller with the following parameters:

param type

must be of the same token type “ocra2”

param serial

must be the same as received from the first request

param genkey

must be of “1”, which indicates, that the init is not finished

param activationcode

“GEZDGNBVGY3TQOJQ01”,

param ocrasuite

same ocrasuite as above “OCRA-1:HOTP-SHA256-8:C-QA64”,

param message

optional the message, that is displayed in the app, e.g. “Transaktion: Ausrollen eines OCRA2 Tokens”,

As response again an <img > is returned, which is the ‘finishing’ transaction, where the qrtan app will reply only with an otp value

Further challenge request and response processing could then be managed by using the /validate/check_s with

param serial

token serial number, as defined above

param challenge

the challenge input data as heart of the transaction

or when using /validate/check with

param user

the assigned token user / owner

param passw

which contains the token pin

param challenge

the challenge input data as heart of the transaction

a response to this request will then contain the /detail/ocraurl/img image data and the transaction id, which is the referer to the incomming challenge respones from the qrtan app.

The challenge response then is verified by /validate/check_t and the parameters:

param transactionid

the transaction id “440364804594”,

param pass

the otp value e.g. “48344099”

But as well the /validate/check controller could be used to verify the transaction by providing in addition the user name.

class linotp.tokens.ocra2token.ocra2token.Ocra2TokenClass(aToken)

Bases: TokenClass

Ocra2TokenClass implement an ocra compliant token

used from Config
OcraMaxChallenges - number of open challenges per token

if None: 3

Ocra2ChallengeValidityTime timeout definition in seconds OcraDefaultSuite - if none :’OCRA-1:HOTP-SHA256-8:C-QN08’ QrOcraDefaultSuite - if none :’OCRA-1:HOTP-SHA256-8:C-QA64’

algorithm Ocra Token Rollout: tow phases of rollout

  1. https://linotpserver/admin/init?

    type=ocra& genkey=1& sharedsecret=1& user=BENUTZERNAME& session=SESSIONKEY

    =>> “serial” : SERIENNUMMER, “sharedsecret” : DATAOBJECT, “app_import” : IMPORTURL - genSharedSecret - vom HSM oder urandom ? - app_import : + linotp://

    • ocrasuite ->> default aus dem config: (DefaultOcraSuite)

    • sharedsecret (Länge wie ???)

    • seriennummer

    • seriennummer: uuid

    • token wird angelegt ist aber nicht aktiv!!! (counter == 0)

  2. https://linotpserver/admin/init?

    type=ocra& genkey=1& activationcode=AKTIVIERUNGSCODE& user=BENUTZERNAME& message=MESSAGE& session=SESSIONKEY

    =>> “serial” : SERIENNUMMER, “nonce” : DATAOBJECT, “transactionid” : “TRANSAKTIONSID, “app_import” : IMPORTURL

    • nonce - von HSM oder random ?

    • pkcs5 - kdf2

    • es darf zur einer Zeit nur eine QR Token inaktiv (== im Ausrollzustand) sein !!!!! der Token wird über den User gefunden

    • seed = pdkdf2(nonce + activcode + shared secret)

    • challenge generiern - von urandom oder HSM

  3. check_t
    • counter ist > nach der ersten Transaktion

    • if counter >= 1: delete sharedsecret löschen

autosync(ocraSuite, passw, challenge)

try to resync a token automaticaly, if a former and the current request failed

Parameters
  • ocraSuite (ocra object) – the ocraSuite of the current Token

  • passw

challenge(data, session='', typ='raw', challenge=None)

the challenge method is for creating an transaction / challenge object

remark: the transaction has a maximum lifetime and a reference to

the OcraSuite token (serial)

Parameters
  • data (string or None) – data, which is the base for the challenge or None

  • session (string) – session support for ocratokens

Returns

challenge response containing the transcation id and the challenge for the ocrasuite

:rtype : tuple of (transId(string), challenge(string))

checkOtp(passw, counter, window, options=None)

checkOtp - standard callback of linotp to verify the token

Parameters
  • passw (string) – the passw / otp, which has to be checked

  • counter (int) – the start counter

  • window (int) – the window, in which the token is valid

  • options (dict) – options contains the transaction id, eg. if check_t checks one transaction this will support assynchreonous otp checks (when check_t is used)

Returns

verification counter or -1

Return type

int (-1)

checkResponse4Challenge(user, passw, options=None, challenges=None)

verify the response of a previous challenge

Parameters
  • user – the requesting user

  • passw – the to be checked pass: (otp) & trans_id | (pin+otp)

  • options – options an additional argument, which could be token specific

  • challenges – the list of challenges, where each challenge is described as dict

Returns

tuple of (boolean and the list matching challenge ids)

createChallenge(state, options=None)

standard API to create an ocra challenge

classmethod getClassInfo(key=None, ret='all')

getClassInfo - returns all or a subtree of the token definition

Parameters
  • key (string) – subsection identifier

  • ret (user defined) – default return value, if nothing is found

Returns

subsection if key exists or user defined

:rtype : s.o.

classmethod getClassPrefix()
classmethod getClassType()

getClassType - return the token type shortname

Returns

‘ocra2’

Return type

string

getInfo()

getInfo - return the status of the token rollout

Returns

info of the ocra token state

Return type

dict

getInitDetail(params, user=None)

to complete the token normalisation, the response of the initialiastion should be build by the token specific method, the getInitDetails

getOcraSuiteSuite()

getQROcraSuiteSuite - return the QR Ocra Suite - if none, it will return the default

Returns

Ocrasuite of token

Return type

string

getQRImageData(response_detail)
getQROcraSuiteSuite()

getQROcraSuiteSuite - return the QR Ocra Suite - if none, it will return the default

Returns

QROcrasuite of token

Return type

string

getStatus(transactionId)

getStatus - assembles the status of a transaction / challenge in a dict

{ “serial”: SERIENNUMMER1,

“transactionid”: TRANSACTIONID1, “received_tan”: true, “valid_tan”: true, “failcount”: 0

}

Parameters

transactionId (string) – the transaction / challenge id

Returns

status dict

Return type

dict

get_enrollment_status()

return the enrollemnt status

classmethod get_helper_params_post(param, user=None)

hook method which gets called with the parameters given to admin/init and the user that possibly gets created from it. It returns a dictionary which will be added to the helper_params. In contrast to get_helper_params_pre this function will be called _after_ the user object gets created from the parameters

Params params

the request parameters supplied to admin/init

Params user

the user object created from the request parameters (None if no user was specified in the request)

Returns

dictionary with additional helper params

is_challenge_request(passw, user, options=None)

check, if the request would start a challenge

  • default: if the passw contains only the pin, this request would

trigger a challenge

  • in this place as well the policy for a token is checked

Parameters
  • passw – password, which might be pin or pin+otp

  • options – dictionary of additional request parameters

Retrun

returns true or false

is_challenge_response(passw, user, options=None, challenges=None)

test for the ocra token, if this is a response to a challenge

normal challenge response brings in a password and there is at least a stored challenge available. But OCRA support as well direct challenges, which bring the challenge data and the otp within the same request.

Parameters
  • passw – password, which might be pin or pin+otp

  • user – the requesting user

  • options – dictionary of additional request parameters

Returns

returns true or false

prepare_message(data, transId)

prepare the challenge response message

Parameters
  • data

  • transId – the transaction/state refenence id

remark: we need the state/transId in the inner scope to support the signing of the whole request including the state/transId

resync(otp1, otp2, options=None)
  • for the resync to work, we take the last two transactions and their challenges

  • for each challenge, we search forward the sync window length

signData(data)

sign the received data with the secret key

Parameters

data – arbitrary string object

Returns

hexlified signature of the data

statusValidationFail()

statusValidationFail - callback to enable a status change,

will be called if the token verification has failed

:return - nothing

statusValidationSuccess()

statusValidationSuccess - callback to enable a status change,

remark: will be called if the token has been succesfull verified

Returns

  • nothing

update(params, reset_failcount=True)

update: add further definition for token from param in case of init

verify_challenge_is_valid(challenge, session)

verify, if a challenge is valid according to the ocrasuite definition of the token

linotp.tokens.ocra2token.ocra2token.get_qrtan_url(qrtan_policy_name, realms, callback_id=None)

Worker to returns the URL for the half automatic mode for the QR TAN token for the given realm

Parameters
  • qrtan_policy_name – either ‘qrtanurl_init’ or ‘qrtanurl’

  • realms – list of realms or None

  • callback_id – support of multiple callback definitions

Returns

url string

Remark

there might be more than one url, if the token belongs to more than one realm. it is tested, if all are the same, otherwise an exception is raised

linotp.tokens.ocra2token.ocra2token.qrtan_url(realms, callback_id=None)

Returns the URL for the half automatic mode for the QR TAN token for the given realm

Remark

there might be more than one url, if the token belongs to more than one realm

Parameters

realms – list of realms or None

Returns

url string

linotp.tokens.ocra2token.ocra2token.qrtanurl_init(realms, callback_id=None)

Returns the URL for the half automatic mode for the QR TAN token for the given realm

Remark

there might be more than one url, if the token belongs to more than one realm

Parameters

realms – list of realms or None

Returns

url string