Пример #1
0
    def _getChallenge(self, ocrasuite, bkey, serial, ocrapin="", data=None, count=0, ttime=None):

        otp1 = None

        p = {"serial": serial, "data": "0105037311 Konto 50150850 BLZ 1752,03 Eur"}
        if data != None:
            p[data] = data

        response = self.app.get(genUrl(controller="ocra", action="request"), params=p)
        log.info("response %s\n", response)
        assert '"value": true' in response

        """ -2b- from the response get the challenge """
        jresp = json.loads(response.body)
        challenge1 = str(jresp.get("detail").get("challenge"))
        transid1 = str(jresp.get("detail").get("transactionid"))

        now = datetime.now()
        if ttime != None:
            now = ttime
        stime = now.strftime("%s")
        itime = int(stime)

        param = {}
        param["C"] = count
        param["Q"] = challenge1
        param["P"] = ocrapin
        param["S"] = ""
        param["T"] = itime

        ocra = OcraSuite(ocrasuite)
        data = ocra.combineData(**param)
        otp1 = ocra.compute(data, bkey)

        return (otp1, transid1)
Пример #2
0
    def verify_challenge_is_valid(self, challenge, session):
        '''
        verify, if a challenge is valid according to the ocrasuite definition
        of the token
        '''

        ret = True

        counter = self.getOtpCount()

        secretHOtp = self.token.getHOtpKey()
        ocraSuite = OcraSuite(self.getOcraSuiteSuite(), secretHOtp)

        ## set the pin onyl in the compliant hashed mode
        pin = ''
        if ocraSuite.P is not None:
            pinObj = self.token.getUserPin()
            pin = pinObj.getKey()

        try:
            param = {}
            param['C'] = counter
            param['Q'] = challenge
            param['P'] = pin
            param['S'] = session
            if ocraSuite.T is not None:
                now = datetime.datetime.now()
                stime = now.strftime("%s")
                itime = int(stime)
                param['T'] = itime

            ''' verify that the data is compliant with the OcraSuitesuite
                and the client is able to calc the otp
            '''
            c_data = ocraSuite.combineData(**param)
            ocraSuite.compute(c_data)

        except Exception as ex:
            log.error("[Ocra2TokenClass] challenge verification failed: "
                                "%s,%r: " % (challenge, ex))
            log.error("[Ocra2TokenClass] %r" % (traceback.format_exc()))
            ret = False

        return ret
Пример #3
0
    def _getChallenge(self,
                      ocrasuite,
                      bkey,
                      serial,
                      ocrapin='',
                      data=None,
                      count=0,
                      ttime=None):

        otp1 = None

        p = {
            "serial": serial,
            "data": "0105037311 Konto 50150850 BLZ 1752,03 Eur"
        }
        if data != None:
            p[data] = data

        response = self.app.get(genUrl(controller='ocra', action='request'),
                                params=p)
        log.info("response %s\n", response)
        assert '"value": true' in response
        ''' -2b- from the response get the challenge '''
        jresp = json.loads(response.body)
        challenge1 = str(jresp.get('detail').get('challenge'))
        transid1 = str(jresp.get('detail').get('transactionid'))

        now = datetime.now()
        if ttime != None:
            now = ttime
        stime = now.strftime("%s")
        itime = int(stime)

        param = {}
        param['C'] = count
        param['Q'] = challenge1
        param['P'] = ocrapin
        param['S'] = ''
        param['T'] = itime

        ocra = OcraSuite(ocrasuite)
        data = ocra.combineData(**param)
        otp1 = ocra.compute(data, bkey)

        return (otp1, transid1)
Пример #4
0
    def _getChallenge(self, ocrasuite, bkey, serial, ocrapin='', data=None, count=0, ttime=None):

        otp1 = None

        p = {"serial"      : serial,
             "data"        : "0105037311 Konto 50150850 BLZ 1752,03 Eur"
            }
        if data != None:
            p[data] = data

        response = self.app.get(genUrl(controller='ocra', action='request'), params=p)
        log.info("response %s\n", response)
        assert '"value": true' in response

        ''' -2b- from the response get the challenge '''
        jresp = json.loads(response.body)
        challenge1 = str(jresp.get('detail').get('challenge'))
        transid1 = str(jresp.get('detail').get('transactionid'))


        now = datetime.now()
        if ttime != None:
            now = ttime
        stime = now.strftime("%s")
        itime = int(stime)

        param = {}
        param['C'] = count
        param['Q'] = challenge1
        param['P'] = ocrapin
        param['S'] = ''
        param['T'] = itime

        ocra = OcraSuite(ocrasuite)
        data = ocra.combineData(**param)
        otp1 = ocra.compute(data, bkey)

        return (otp1, transid1)
Пример #5
0
    def ptest_OCRA_token_failcounterInc(self, tid=1):
        '''
            test_OCRA_token_failcounterInc: failcounter increment

            description:
                for all ocrasuites:
                   create and enroll token
                   verify the first otp
                   get some challenges
                   4 times:
                      verify a wrong otp
                      verify a wrong transaction
                      check status and if fail counter has incremented
        '''
        tcount = 0
        for test in self.tests:
            ocrasuite = test['ocrasuite']
            key = test['keyh']
            bkey = test['key']
            ocrapin = 'myocrapin'
            tid = tid
            serial = "QR_One_%r_%r_%r_%r" % (tid, tcount, int(time.time()), random.randint(0, 100))
            log.info("## serial: %s" % serial)
            count = 0
            tcount = tcount + 1

            ocra = OcraSuite(ocrasuite)
            pinlen = ocra.truncation
            ''' -1- create an ocra token '''
            parameters = {
                          "serial"      : serial,
                          "user"        : "root",
                          "pin"         : "pin",
                          "description" : "first QRToken",
                          'type'        : 'ocra',
                          'ocrapin'     : ocrapin,
                          'otpkey'      : key,
                          'ocrasuite'   : ocrasuite
                          }

            response = self.app.get(genUrl(controller='admin', action='init'), params=parameters)
            assert '"value": true' in response

            ## verify that the token is usable
            ''' -2- fetch the challenge '''
            p = {"serial"      : serial,
                 "data"        : "0105037311 Konto 50150850 BLZ 1752,03 Eur"
                }
            response = self.app.get(genUrl(controller='ocra', action='request'), params=p)
            log.info("response %s\n", response)
            if '"value": true' not in response:
                assert '"value": true' in response

            ''' -3.a- from the response get the challenge '''
            jresp = json.loads(response.body)
            challenge = str(jresp.get('detail').get('challenge'))
            transid = str(jresp.get('detail').get('transactionid'))

            param = {}
            param['C'] = count
            param['Q'] = challenge
            param['P'] = ocrapin
            param['S'] = ''
            if ocra.T != None:
                '''    Default value for G is 1M, i.e., time-step size is one minute and the
                       T represents the number of minutes since epoch time [UT].
                '''
                now = datetime.now()
                stime = now.strftime("%s")
                itime = int(stime)
                param['T'] = itime

            ocra = OcraSuite(ocrasuite)
            data = ocra.combineData(**param)
            otp = ocra.compute(data, bkey)

            ppin = 'pin' + otp

            ''' -3.b- verify the correct otp value '''
            parameters = {"transactionid"   : transid,
                          "pass"            : ppin,
                          }
            response = self.app.get(genUrl(controller='ocra', action='check_t'), params=parameters)
            log.info("response %s\n", response)
            if '"result": true' not in response:
                assert '"result": true' in response

            # verify that the failcounter increments (max is 10)
            fcount = 0
            for count in range(1, 3):

                ## create more than one challenge
                chals = random.randint(2, 5)
                for cc in range(1, chals):
                    ''' -2- fetch the challenge '''
                    p = {"serial"      : serial,
                         "data"        : "0105037311 Konto 50150850 BLZ 1752,03 Eur"
                        }
                    response = self.app.get(genUrl(controller='ocra', action='request'), params=p)
                    log.info("response %s\n", response)
                    if '"value": true' not in response:
                        assert '"value": true' in response


                ''' -3.a- from the response get the challenge '''
                jresp = json.loads(response.body)
                challenge = str(jresp.get('detail').get('challenge'))
                transid = str(jresp.get('detail').get('transactionid'))

                ppin = 'pin' + 'a' * pinlen

                ''' -4- verify the wrong otp value '''
                parameters = {"transactionid"   : transid,
                              "pass"            : ppin,
                              }
                response = self.app.get(genUrl(controller='ocra', action='check_t'), params=parameters)
                log.info("response %s\n", response)
                if '"result": false' not in response:
                    assert '"result": false' in response
                fcount += 1

                ppin = 'pin' + '4' * pinlen

                ''' -5- verify the wrong otp value '''
                parameters = {"transactionid"   : transid,
                              "pass"            : ppin,
                              }
                response = self.app.get(genUrl(controller='ocra', action='check_t'), params=parameters)
                log.info("response %s\n", response)
                if not '"result": false' in response:
                    assert '"result": false' in response
                fcount += 1

                ''' -6- check if the failcounter has incremented  '''
                parameters = {"transactionid"   : transid,
                              }
                response = self.app.get(genUrl(controller='ocra', action='checkstatus'), params=parameters)
                log.info("response %s\n", response)
                assert '"status": true' in response
                assstring = '"failcount": %d,' % (fcount)
                log.info("assert %s\n", assstring)
                if assstring not in response:
                    log.error(response)
                    assert assstring in response

                sleep = random.uniform(0.0, 0.3)
                time.sleep(sleep)

            ''' -remove the ocra token '''
            parameters = {"serial"      : serial, }
            response = self.app.get(genUrl(controller='admin', action='remove'), params=parameters)
            log.info("response %s\n", response)
            assert '"value": 1' in response

            for _iii in range(0, 3):
                parameters = {"serial"      : serial, }
                response = self.app.get(genUrl(controller='admin', action='remove'), params=parameters)


        return response
Пример #6
0
class OcraOtp(object):

    def __init__(self, ocrapin=None):
        self.ocra = None
        self.bkey = None
        self.ocrapin = ocrapin
        self.activationkey = None
        self.sharedsecret = None
        self.ocrasuite = None
        self.serial = None
        self.counter = 0


    def init_1(self, response):
        ''' take the response of the first init to setup the OcraOtp'''

        jresp = json.loads(response.body)
        app_import = str(jresp.get('detail').get('app_import'))
        self.sharedsecret = str(jresp.get('detail').get('sharedsecret'))
        self.serial = str(jresp.get('detail').get('serial'))

        ''' now parse the appurl for the ocrasuite '''
        uri = urlparse(app_import.replace('lseqr://', 'http://'))
        qs = uri.query
        qdict = parse_qs(qs)

        ocrasuite = qdict.get('os', None)
        if ocrasuite != None and len(ocrasuite) > 0:
            ocrasuite = ocrasuite[0]

        self.ocrasuite = ocrasuite

        return (self.ocrasuite, self.sharedsecret, self.serial)


    def init_2(self, response, activationKey):
        self.activationkey = activationKey

        jresp = json.loads(response.body)
        self.nonce = str(jresp.get('detail').get('nonce'))
        self.transid = str(jresp.get('detail').get('transactionid'))
        app_import = str(jresp.get('detail').get('app_import'))


        ''' now parse the appurl for the ocrasuite '''
        uri = urlparse(app_import.replace('lseqr://', 'http://'))
        qs = uri.query
        qdict = parse_qs(qs)
        nonce = qdict.get('no', None)
        if nonce != None and len(nonce) > 0:
            nonce = nonce[0]

        challenge = qdict.get('ch', None)
        if challenge != None and len(challenge) > 0:
            challenge = challenge[0]

        self.challenge = challenge
        self.ocra = None
        self.bkey = None

        return (self.challenge, self.transid)


    def _setup_(self):

        if self.ocra != None and self.bkey != None:
            return

        key_len = 20
        if self.ocrasuite.find('-SHA256'):
            key_len = 32
        elif self.ocrasuite.find('-SHA512'):
            key_len = 64

        self.bkey = kdf2(self.sharedsecret, self.nonce, self.activationkey, len=key_len)
        self.ocra = OcraSuite(self.ocrasuite)

        self.counter = 0

        return

    def callcOtp(self, challenge=None, ocrapin=None, counter= -1):

        if self.ocra == None:
            self._setup_()

        if ocrapin == None:
            ocrapin = self.ocrapin

        if challenge == None:
            challenge = self.challenge
        if counter == -1:
            counter = self.counter

        param = {}
        param['C'] = counter
        param['Q'] = challenge
        param['P'] = ocrapin
        param['S'] = ''
        if self.ocra.T != None:
            '''    Default value for G is 1M, i.e., time-step size is one minute and the
                   T represents the number of minutes since epoch time [UT].
            '''
            now = datetime.now()
            stime = now.strftime("%s")
            itime = int(stime)
            param['T'] = itime

        data = self.ocra.combineData(**param)
        otp = self.ocra.compute(data, self.bkey)

        if counter == -1:
            self.counter += 1

        return otp
Пример #7
0
    def ptest_OCRA_token_failcounterInc(self, tid=1):
        '''
            test_OCRA_token_failcounterInc: failcounter increment

            description:
                for all ocrasuites:
                   create and enroll token
                   verify the first otp
                   get some challenges
                   4 times:
                      verify a wrong otp
                      verify a wrong transaction
                      check status and if fail counter has incremented
        '''
        tcount = 0
        for test in self.tests:
            ocrasuite = test['ocrasuite']
            key = test['keyh']
            bkey = test['key']
            ocrapin = 'myocrapin'
            tid = tid
            serial = "QR_One_%r_%r_%r_%r" % (tid, tcount, int(time.time()), random.randint(0, 100))
            log.info("## serial: %s" % serial)
            count = 0
            tcount = tcount + 1

            ocra = OcraSuite(ocrasuite)
            pinlen = ocra.truncation
            ''' -1- create an ocra token '''
            parameters = {
                          "serial"      : serial,
                          "user"        : "root",
                          "pin"         : "pin",
                          "description" : "first QRToken",
                          'type'        : 'ocra',
                          'ocrapin'     : ocrapin,
                          'otpkey'      : key,
                          'ocrasuite'   : ocrasuite
                          }

            response = self.app.get(genUrl(controller='admin', action='init'), params=parameters)
            assert '"value": true' in response

            ## verify that the token is usable
            ''' -2- fetch the challenge '''
            p = {"serial"      : serial,
                 "data"        : "0105037311 Konto 50150850 BLZ 1752,03 Eur"
                }
            response = self.app.get(genUrl(controller='ocra', action='request'), params=p)
            log.info("response %s\n", response)
            if '"value": true' not in response:
                assert '"value": true' in response

            ''' -3.a- from the response get the challenge '''
            jresp = json.loads(response.body)
            challenge = str(jresp.get('detail').get('challenge'))
            transid = str(jresp.get('detail').get('transactionid'))

            param = {}
            param['C'] = count
            param['Q'] = challenge
            param['P'] = ocrapin
            param['S'] = ''
            if ocra.T != None:
                '''    Default value for G is 1M, i.e., time-step size is one minute and the
                       T represents the number of minutes since epoch time [UT].
                '''
                now = datetime.now()
                stime = now.strftime("%s")
                itime = int(stime)
                param['T'] = itime

            ocra = OcraSuite(ocrasuite)
            data = ocra.combineData(**param)
            otp = ocra.compute(data, bkey)

            ppin = 'pin' + otp

            ''' -3.b- verify the correct otp value '''
            parameters = {"transactionid"   : transid,
                          "pass"            : ppin,
                          }
            response = self.app.get(genUrl(controller='ocra', action='check_t'), params=parameters)
            log.info("response %s\n", response)
            if '"result": true' not in response:
                assert '"result": true' in response

            # verify that the failcounter increments (max is 10)
            fcount = 0
            for count in range(1, 3):

                ## create more than one challenge
                chals = random.randint(2, 5)
                for cc in range(1, chals):
                    ''' -2- fetch the challenge '''
                    p = {"serial"      : serial,
                         "data"        : "0105037311 Konto 50150850 BLZ 1752,03 Eur"
                        }
                    response = self.app.get(genUrl(controller='ocra', action='request'), params=p)
                    log.info("response %s\n", response)
                    if '"value": true' not in response:
                        assert '"value": true' in response


                ''' -3.a- from the response get the challenge '''
                jresp = json.loads(response.body)
                challenge = str(jresp.get('detail').get('challenge'))
                transid = str(jresp.get('detail').get('transactionid'))

                ppin = 'pin' + 'a' * pinlen

                ''' -4- verify the wrong otp value '''
                parameters = {"transactionid"   : transid,
                              "pass"            : ppin,
                              }
                response = self.app.get(genUrl(controller='ocra', action='check_t'), params=parameters)
                log.info("response %s\n", response)
                if '"result": false' not in response:
                    assert '"result": false' in response
                fcount += 1

                ppin = 'pin' + '4' * pinlen

                ''' -5- verify the wrong otp value '''
                parameters = {"transactionid"   : transid,
                              "pass"            : ppin,
                              }
                response = self.app.get(genUrl(controller='ocra', action='check_t'), params=parameters)
                log.info("response %s\n", response)
                if not '"result": false' in response:
                    assert '"result": false' in response
                fcount += 1

                ''' -6- check if the failcounter has incremented  '''
                parameters = {"transactionid"   : transid,
                              }
                response = self.app.get(genUrl(controller='ocra', action='checkstatus'), params=parameters)
                log.info("response %s\n", response)
                assert '"status": true' in response
                assstring = '"failcount": %d,' % (fcount)
                log.info("assert %s\n", assstring)
                if assstring not in response:
                    log.error(response)
                    assert assstring in response

                sleep = random.uniform(0.0, 0.3)
                time.sleep(sleep)

            ''' -remove the ocra token '''
            parameters = {"serial"      : serial, }
            response = self.app.get(genUrl(controller='admin', action='remove'), params=parameters)
            log.info("response %s\n", response)
            assert '"value": 1' in response

            for _iii in range(0, 3):
                parameters = {"serial"      : serial, }
                response = self.app.get(genUrl(controller='admin', action='remove'), params=parameters)


        return response
Пример #8
0
class OcraOtp(object):

    def __init__(self, ocrapin=None):
        self.ocra = None
        self.bkey = None
        self.ocrapin = ocrapin
        self.activationkey = None
        self.sharedsecret = None
        self.ocrasuite = None
        self.serial = None
        self.counter = 0


    def init_1(self, response):
        ''' take the response of the first init to setup the OcraOtp'''

        jresp = json.loads(response.body)
        app_import = str(jresp.get('detail').get('app_import'))
        self.sharedsecret = str(jresp.get('detail').get('sharedsecret'))
        self.serial = str(jresp.get('detail').get('serial'))

        ''' now parse the appurl for the ocrasuite '''
        uri = urlparse(app_import.replace('lseqr://', 'http://'))
        qs = uri.query
        qdict = parse_qs(qs)

        ocrasuite = qdict.get('os', None)
        if ocrasuite != None and len(ocrasuite) > 0:
            ocrasuite = ocrasuite[0]

        self.ocrasuite = ocrasuite

        return (self.ocrasuite, self.sharedsecret, self.serial)


    def init_2(self, response, activationKey):
        self.activationkey = activationKey

        jresp = json.loads(response.body)
        self.nonce = str(jresp.get('detail').get('nonce'))
        self.transid = str(jresp.get('detail').get('transactionid'))
        app_import = str(jresp.get('detail').get('app_import'))


        ''' now parse the appurl for the ocrasuite '''
        uri = urlparse(app_import.replace('lseqr://', 'http://'))
        qs = uri.query
        qdict = parse_qs(qs)
        nonce = qdict.get('no', None)
        if nonce != None and len(nonce) > 0:
            nonce = nonce[0]

        challenge = qdict.get('ch', None)
        if challenge != None and len(challenge) > 0:
            challenge = challenge[0]

        self.challenge = challenge
        self.ocra = None
        self.bkey = None

        return (self.challenge, self.transid)


    def _setup_(self):

        if self.ocra != None and self.bkey != None:
            return

        key_len = 20
        if self.ocrasuite.find('-SHA256'):
            key_len = 32
        elif self.ocrasuite.find('-SHA512'):
            key_len = 64

        self.bkey = kdf2(self.sharedsecret, self.nonce, self.activationkey, len=key_len)
        self.ocra = OcraSuite(self.ocrasuite)

        self.counter = 0

        return

    def callcOtp(self, challenge=None, ocrapin=None, counter= -1):

        if self.ocra == None:
            self._setup_()

        if ocrapin == None:
            ocrapin = self.ocrapin

        if challenge == None:
            challenge = self.challenge
        if counter == -1:
            counter = self.counter

        param = {}
        param['C'] = counter
        param['Q'] = challenge
        param['P'] = ocrapin
        param['S'] = ''
        if self.ocra.T != None:
            '''    Default value for G is 1M, i.e., time-step size is one minute and the
                   T represents the number of minutes since epoch time [UT].
            '''
            now = datetime.now()
            stime = now.strftime("%s")
            itime = int(stime)
            param['T'] = itime

        data = self.ocra.combineData(**param)
        otp = self.ocra.compute(data, self.bkey)

        if counter == -1:
            self.counter += 1

        return otp
Пример #9
0
    def calculateOtp(self):
        '''

        '''
        from linotp.lib.crypt import kdf2
        from linotp.lib.ocra import OcraSuite
        from datetime import datetime

        from urlparse import urlparse
        from urlparse import parse_qs

        res = {}
        #description = 'ocra/calculateOtp: calculate the first otp from the given init2 response '

        try:
            params = getLowerParams(request.params)
            log.debug("[calculateOtp]: %r" % params)

            checkPolicyPre('ocra', "calcOTP")

            sharedsecret = params.get('sharedsecret')
            activationcode = params.get('activationcode')
            nonce = params.get('nonce')
            ocrasuite = params.get('ocrasuite')
            challenge = params.get('challenge')
            counter = params.get('counter')
            ocrapin = params.get('ocrapin')

            nonce3 = params.get('no')
            ocrasuite3 = params.get('os')
            #serial3         = params.get('se')

            challenge = params.get('challenge')
            counter = params.get('counter')
            ocrapin = params.get('ocrapin')
            init1 = params.get('init1')
            init2 = params.get('init2')

            ## parse init1 '''
            if init1 is not None:
                ## now parse the appurl for the ocrasuite '''
                uri = urlparse(init1.replace('lseqr://', 'http://'))
                qs = uri.query
                qdict = parse_qs(qs)

                ocrasuite2 = qdict.get('os', None)
                if ocrasuite2 is not None and len(ocrasuite2) > 0:
                    ocrasuite2 = ocrasuite2[0]

                if ocrasuite is None:
                    ocrasuite = ocrasuite2

                sharedsecret2 = qdict.get('sh', None)
                if sharedsecret2 is not None and len(sharedsecret2) > 0:
                    sharedsecret2 = sharedsecret2[0]

                if sharedsecret is None:
                    sharedsecret = sharedsecret2

            ## parse init1
            if init2 is not None:
                ## now parse the appurl for the ocrasuite
                uri = urlparse(init2.replace('lseqr://', 'http://'))
                qs = uri.query
                qdict = parse_qs(qs)

                challenge2 = qdict.get('ch', None)
                if challenge2 is not None and len(challenge2) > 0:
                    challenge2 = challenge2[0]
                if challenge is None:
                    challenge = challenge2

                nonce2 = qdict.get('no', None)
                if nonce2 is not None and len(nonce2) > 0:
                    nonce2 = nonce2[0]
                if nonce is None:
                    nonce = nonce2

            if ocrapin is None:
                ocrapin = ''
            if counter is None:
                counter = 0

            if nonce3 is not None:
                nonce = unicode(nonce3)

            if ocrasuite3 is not None:
                ocrasuite = unicode(ocrasuite3)

            ##  now we have all in place for the key derivation to create the new key
            ##     sharedsecret, activationcode and nonce
            key_len = 20
            if ocrasuite.find('-SHA256'):
                key_len = 32
            elif ocrasuite.find('-SHA512'):
                key_len = 64

            if sharedsecret is not None:
                sharedsecret = unicode(sharedsecret)
            if nonce is not None:
                nonce = unicode(nonce)
            if activationcode is not None:
                activationcode = unicode(activationcode)

            newkey = kdf2(sharedsecret, nonce, activationcode, len=key_len)
            ## hnewkey = binascii.hexlify(newkey)
            ocra = OcraSuite(ocrasuite)

            param = {}
            param['C'] = int(counter)
            param['Q'] = unicode(challenge)
            param['P'] = unicode(ocrapin)
            param['S'] = ''
            if ocra.T is not None:
                ## Default value for G is 1M, i.e., time-step size is one minute and the
                ##  T represents the number of minutes since epoch time [UT].
                now = datetime.now()
                stime = now.strftime("%s")
                itime = int(stime)
                param['T'] = itime

            data = ocra.combineData(**param)
            otp = ocra.compute(data, newkey)

            res = {'otp':otp}

            Session.commit()
            return sendResult(response, res, 1)

        except PolicyException as pe:
            log.exception("[ocra/calculateOtp] policy failed: %r" % pe)
            Session.rollback()
            return sendError(response, pe)

        except Exception as e:
            log.exception("[ocra/calculateOtp] failed: %r" % e)
            Session.rollback()
            return sendError(response, unicode(e), 0)

        finally:
            Session.close()
            log.debug('[ocra/calculateOtp] done')
Пример #10
0
    def challenge(self, 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)

        :param data:     data, which is the base for the challenge or None
        :type data:     string or None
        :param session:  session support for ocratokens
        :type session:  string
        :type typ:      define, which kind of challenge base should be used
                         could be raw - take the data input as is
                               (extract chars accordind challenge definition Q)
                         or random    - will generate a random input
                         or hased     - will take the hash of the input data

        :return:    challenge response containing the transcation id and the
                    challenge for the ocrasuite
        :rtype :    tuple of (transId(string), challenge(string))


        '''
        log.debug('[challenge] %r: %r: %r' % (data, session, challenge))

        secretHOtp = self.token.getHOtpKey()
        ocraSuite = OcraSuite(self.getOcraSuiteSuite(), secretHOtp)

        if data is None or len(data) == 0:
            typ = 'random'

        if challenge is None:
            if typ == 'raw':
                challenge = ocraSuite.data2rawChallenge(data)
            elif typ == 'random':
                challenge = ocraSuite.data2randomChallenge(data)
            elif typ == 'hash':
                challenge = ocraSuite.data2hashChallenge(data)

        log.debug('[Ocra2TokenClass] challenge: %r ' % (challenge))

        counter = self.getOtpCount()

        ## set the pin onyl in the compliant hashed mode
        pin = ''
        if ocraSuite.P is not None:
            pinObj = self.token.getUserPin()
            pin = pinObj.getKey()

        try:
            param = {}
            param['C'] = counter
            param['Q'] = challenge
            param['P'] = pin
            param['S'] = session
            if ocraSuite.T is not None:
                now = datetime.datetime.now()
                stime = now.strftime("%s")
                itime = int(stime)
                param['T'] = itime

            ''' verify that the data is compliant with the OcraSuitesuite
                and the client is able to calc the otp
            '''
            c_data = ocraSuite.combineData(**param)
            ocraSuite.compute(c_data)

        except Exception as ex:
            log.error("[Ocra2TokenClass] %r" % (traceback.format_exc()))
            raise Exception('[Ocra2TokenClass] Failed to create ocrasuite '
                                                        'challenge: %r' % (ex))

        ##  create a non exisiting challenge
        try:

            (res, opt) = create_challenge(self, options={'messgae': data})

            transid = opt.get('transactionid')
            challenge = opt.get('challenge')

        except Exception as ex:
            ##  this might happen if we have a db problem or
            ##   the uniqnes constrain does not fit
            log.error("[Ocra2TokenClass] %r" % (traceback.format_exc()))
            raise Exception('[Ocra2TokenClass] Failed to create '
                                                'challenge object: %s' % (ex))

        realm = None
        realms = self.token.getRealms()
        if len(realms) > 0:
            realm = realms[0]

        url = ''
        if realm is not None:
            url = get_qrtan_url(realm.name)

        log.debug('[challenge]: %r: %r: %r' % (transid, challenge, url))
        return (transid, challenge, True, url)
Пример #11
0
    def calculateOtp(self):
        '''

        '''
        from linotp.lib.crypt import kdf2
        from linotp.lib.ocra import OcraSuite
        from datetime import datetime

        from urlparse import urlparse
        from urlparse import parse_qs

        res = {}
        #description = 'ocra/calculateOtp: calculate the first otp from the given init2 response '

        try:
            params = getLowerParams(request.params)
            log.debug("[calculateOtp]: %r" % params)

            checkPolicyPre('ocra', "calcOTP")

            sharedsecret = params.get('sharedsecret')
            activationcode = params.get('activationcode')
            nonce = params.get('nonce')
            ocrasuite = params.get('ocrasuite')
            challenge = params.get('challenge')
            counter = params.get('counter')
            ocrapin = params.get('ocrapin')

            nonce3 = params.get('no')
            ocrasuite3 = params.get('os')
            #serial3         = params.get('se')

            challenge = params.get('challenge')
            counter = params.get('counter')
            ocrapin = params.get('ocrapin')
            init1 = params.get('init1')
            init2 = params.get('init2')

            ## parse init1 '''
            if init1 is not None:
                ## now parse the appurl for the ocrasuite '''
                uri = urlparse(init1.replace('lseqr://', 'http://'))
                qs = uri.query
                qdict = parse_qs(qs)

                ocrasuite2 = qdict.get('os', None)
                if ocrasuite2 is not None and len(ocrasuite2) > 0:
                    ocrasuite2 = ocrasuite2[0]

                if ocrasuite is None:
                    ocrasuite = ocrasuite2

                sharedsecret2 = qdict.get('sh', None)
                if sharedsecret2 is not None and len(sharedsecret2) > 0:
                    sharedsecret2 = sharedsecret2[0]

                if sharedsecret is None:
                    sharedsecret = sharedsecret2

            ## parse init1
            if init2 is not None:
                ## now parse the appurl for the ocrasuite
                uri = urlparse(init2.replace('lseqr://', 'http://'))
                qs = uri.query
                qdict = parse_qs(qs)

                challenge2 = qdict.get('ch', None)
                if challenge2 is not None and len(challenge2) > 0:
                    challenge2 = challenge2[0]
                if challenge is None:
                    challenge = challenge2

                nonce2 = qdict.get('no', None)
                if nonce2 is not None and len(nonce2) > 0:
                    nonce2 = nonce2[0]
                if nonce is None:
                    nonce = nonce2

            if ocrapin is None:
                ocrapin = ''
            if counter is None:
                counter = 0

            if nonce3 is not None:
                nonce = unicode(nonce3)

            if ocrasuite3 is not None:
                ocrasuite = unicode(ocrasuite3)

            ##  now we have all in place for the key derivation to create the new key
            ##     sharedsecret, activationcode and nonce
            key_len = 20
            if ocrasuite.find('-SHA256'):
                key_len = 32
            elif ocrasuite.find('-SHA512'):
                key_len = 64

            if sharedsecret is not None:
                sharedsecret = unicode(sharedsecret)
            if nonce is not None:
                nonce = unicode(nonce)
            if activationcode is not None:
                activationcode = unicode(activationcode)

            newkey = kdf2(sharedsecret, nonce, activationcode, len=key_len)
            ## hnewkey = binascii.hexlify(newkey)
            ocra = OcraSuite(ocrasuite)

            param = {}
            param['C'] = int(counter)
            param['Q'] = unicode(challenge)
            param['P'] = unicode(ocrapin)
            param['S'] = ''
            if ocra.T is not None:
                ## Default value for G is 1M, i.e., time-step size is one minute and the
                ##  T represents the number of minutes since epoch time [UT].
                now = datetime.now()
                stime = now.strftime("%s")
                itime = int(stime)
                param['T'] = itime

            data = ocra.combineData(**param)
            otp = ocra.compute(data, newkey)

            res = {'otp': otp}

            Session.commit()
            return sendResult(response, res, 1)

        except PolicyException as pe:
            log.exception("[ocra/calculateOtp] policy failed: %r" % pe)
            Session.rollback()
            return sendError(response, pe)

        except Exception as e:
            log.exception("[ocra/calculateOtp] failed: %r" % e)
            Session.rollback()
            return sendError(response, unicode(e), 0)

        finally:
            Session.close()
            log.debug('[ocra/calculateOtp] done')
Пример #12
0
    def ptest_OCRA_token_failcounterInc(self, tid=1):
        """
            test_OCRA_token_failcounterInc: failcounter increment

            description:
                for all ocrasuites:
                   create and enroll token
                   verify the first otp
                   get some challenges
                   4 times:
                      verify a wrong otp
                      verify a wrong transaction
                      check status and if fail counter has incremented
        """
        tcount = 0
        for test in self.tests:
            ocrasuite = test["ocrasuite"]
            key = test["keyh"]
            bkey = test["key"]
            ocrapin = "myocrapin"
            tid = tid
            serial = "QR_One_%r_%r_%r_%r" % (tid, tcount, int(time.time()), random.randint(0, 100))
            log.info("## serial: %s" % serial)
            count = 0
            tcount = tcount + 1

            ocra = OcraSuite(ocrasuite)
            pinlen = ocra.truncation
            """ -1- create an ocra token """
            parameters = {
                "serial": serial,
                "user": "******",
                "pin": "pin",
                "description": "first QRToken",
                "type": "ocra",
                "ocrapin": ocrapin,
                "otpkey": key,
                "ocrasuite": ocrasuite,
            }

            response = self.app.get(genUrl(controller="admin", action="init"), params=parameters)
            assert '"value": true' in response

            ## verify that the token is usable
            """ -2- fetch the challenge """
            p = {"serial": serial, "data": "0105037311 Konto 50150850 BLZ 1752,03 Eur"}
            response = self.app.get(genUrl(controller="ocra", action="request"), params=p)
            log.info("response %s\n", response)
            if '"value": true' not in response:
                assert '"value": true' in response

            """ -3.a- from the response get the challenge """
            jresp = json.loads(response.body)
            challenge = str(jresp.get("detail").get("challenge"))
            transid = str(jresp.get("detail").get("transactionid"))

            param = {}
            param["C"] = count
            param["Q"] = challenge
            param["P"] = ocrapin
            param["S"] = ""
            if ocra.T != None:
                """    Default value for G is 1M, i.e., time-step size is one minute and the
                       T represents the number of minutes since epoch time [UT].
                """
                now = datetime.now()
                stime = now.strftime("%s")
                itime = int(stime)
                param["T"] = itime

            ocra = OcraSuite(ocrasuite)
            data = ocra.combineData(**param)
            otp = ocra.compute(data, bkey)

            ppin = "pin" + otp

            """ -3.b- verify the correct otp value """
            parameters = {"transactionid": transid, "pass": ppin}
            response = self.app.get(genUrl(controller="ocra", action="check_t"), params=parameters)
            log.info("response %s\n", response)
            if '"result": true' not in response:
                assert '"result": true' in response

            # verify that the failcounter increments (max is 10)
            fcount = 0
            for count in range(1, 3):

                ## create more than one challenge
                chals = random.randint(2, 5)
                for cc in range(1, chals):
                    """ -2- fetch the challenge """
                    p = {"serial": serial, "data": "0105037311 Konto 50150850 BLZ 1752,03 Eur"}
                    response = self.app.get(genUrl(controller="ocra", action="request"), params=p)
                    log.info("response %s\n", response)
                    if '"value": true' not in response:
                        assert '"value": true' in response

                """ -3.a- from the response get the challenge """
                jresp = json.loads(response.body)
                challenge = str(jresp.get("detail").get("challenge"))
                transid = str(jresp.get("detail").get("transactionid"))

                ppin = "pin" + "a" * pinlen

                """ -4- verify the wrong otp value """
                parameters = {"transactionid": transid, "pass": ppin}
                response = self.app.get(genUrl(controller="ocra", action="check_t"), params=parameters)
                log.info("response %s\n", response)
                if '"result": false' not in response:
                    assert '"result": false' in response
                fcount += 1

                ppin = "pin" + "4" * pinlen

                """ -5- verify the wrong otp value """
                parameters = {"transactionid": transid, "pass": ppin}
                response = self.app.get(genUrl(controller="ocra", action="check_t"), params=parameters)
                log.info("response %s\n", response)
                if not '"result": false' in response:
                    assert '"result": false' in response
                fcount += 1

                """ -6- check if the failcounter has incremented  """
                parameters = {"transactionid": transid}
                response = self.app.get(genUrl(controller="ocra", action="checkstatus"), params=parameters)
                log.info("response %s\n", response)
                assert '"status": true' in response
                assstring = '"failcount": %d,' % (fcount)
                log.info("assert %s\n", assstring)
                if assstring not in response:
                    log.error(response)
                    assert assstring in response

                sleep = random.uniform(0.0, 0.3)
                time.sleep(sleep)

            """ -remove the ocra token """
            parameters = {"serial": serial}
            response = self.app.get(genUrl(controller="admin", action="remove"), params=parameters)
            log.info("response %s\n", response)
            assert '"value": 1' in response

            for _iii in range(0, 3):
                parameters = {"serial": serial}
                response = self.app.get(genUrl(controller="admin", action="remove"), params=parameters)

        return response
Пример #13
0
class OcraOtp(object):
    def __init__(self, ocrapin=None):
        self.ocra = None
        self.bkey = None
        self.ocrapin = ocrapin
        self.activationkey = None
        self.sharedsecret = None
        self.ocrasuite = None
        self.serial = None
        self.counter = 0

    def init_1(self, response):
        """ take the response of the first init to setup the OcraOtp"""

        jresp = json.loads(response.body)
        app_import = str(jresp.get("detail").get("app_import"))
        self.sharedsecret = str(jresp.get("detail").get("sharedsecret"))
        self.serial = str(jresp.get("detail").get("serial"))

        """ now parse the appurl for the ocrasuite """
        uri = urlparse(app_import.replace("lseqr://", "http://"))
        qs = uri.query
        qdict = parse_qs(qs)

        ocrasuite = qdict.get("os", None)
        if ocrasuite != None and len(ocrasuite) > 0:
            ocrasuite = ocrasuite[0]

        self.ocrasuite = ocrasuite

        return (self.ocrasuite, self.sharedsecret, self.serial)

    def init_2(self, response, activationKey):
        self.activationkey = activationKey

        jresp = json.loads(response.body)
        self.nonce = str(jresp.get("detail").get("nonce"))
        self.transid = str(jresp.get("detail").get("transactionid"))
        app_import = str(jresp.get("detail").get("app_import"))

        """ now parse the appurl for the ocrasuite """
        uri = urlparse(app_import.replace("lseqr://", "http://"))
        qs = uri.query
        qdict = parse_qs(qs)
        nonce = qdict.get("no", None)
        if nonce != None and len(nonce) > 0:
            nonce = nonce[0]

        challenge = qdict.get("ch", None)
        if challenge != None and len(challenge) > 0:
            challenge = challenge[0]

        self.challenge = challenge
        self.ocra = None
        self.bkey = None

        return (self.challenge, self.transid)

    def _setup_(self):

        if self.ocra != None and self.bkey != None:
            return

        key_len = 20
        if self.ocrasuite.find("-SHA256"):
            key_len = 32
        elif self.ocrasuite.find("-SHA512"):
            key_len = 64

        self.bkey = kdf2(self.sharedsecret, self.nonce, self.activationkey, len=key_len)
        self.ocra = OcraSuite(self.ocrasuite)

        self.counter = 0

        return

    def callcOtp(self, challenge=None, ocrapin=None, counter=-1):

        if self.ocra == None:
            self._setup_()

        if ocrapin == None:
            ocrapin = self.ocrapin

        if challenge == None:
            challenge = self.challenge
        if counter == -1:
            counter = self.counter

        param = {}
        param["C"] = counter
        param["Q"] = challenge
        param["P"] = ocrapin
        param["S"] = ""
        if self.ocra.T != None:
            """    Default value for G is 1M, i.e., time-step size is one minute and the
                   T represents the number of minutes since epoch time [UT].
            """
            now = datetime.now()
            stime = now.strftime("%s")
            itime = int(stime)
            param["T"] = itime

        data = self.ocra.combineData(**param)
        otp = self.ocra.compute(data, self.bkey)

        if counter == -1:
            self.counter += 1

        return otp