Exemplo n.º 1
0
def gen_parameters(opts):
    """Generates Name, ICCID, MCC, MNC, IMSI, SMSP, Ki, PIN-ADM from the
	options given by the user"""

    # MCC/MNC
    mcc = opts.mcc
    mnc = opts.mnc

    if not mcc.isdigit() or not mnc.isdigit():
        raise ValueError('mcc & mnc must only contain decimal digits')
    if len(mcc) < 1 or len(mcc) > 3:
        raise ValueError('mcc must be between 1 .. 3 digits')
    if len(mnc) < 1 or len(mnc) > 3:
        raise ValueError('mnc must be between 1 .. 3 digits')

    # MCC always has 3 digits
    mcc = lpad(mcc, 3, "0")
    # MNC must be at least 2 digits
    mnc = lpad(mnc, 2, "0")

    # Digitize country code (2 or 3 digits)
    cc_digits = _cc_digits(opts.country)

    # Digitize MCC/MNC (5 or 6 digits)
    plmn_digits = _mcc_mnc_digits(mcc, mnc)

    if opts.name is not None:
        if len(opts.name) > 16:
            raise ValueError('Service Provider Name must max 16 characters!')

    if opts.msisdn is not None:
        msisdn = opts.msisdn
        if msisdn[0] == '+':
            msisdn = msisdn[1:]
        if not msisdn.isdigit():
            raise ValueError('MSISDN must be digits only! '
                             'Start with \'+\' for international numbers.')
        if len(msisdn) > 10 * 2:
            # TODO: Support MSISDN of length > 20 (10 Bytes)
            raise ValueError(
                'MSISDNs longer than 20 digits are not (yet) supported.')

    # ICCID (19 digits, E.118), though some phase1 vendors use 20 :(
    if opts.iccid is not None:
        iccid = opts.iccid
        if not _isnum(iccid, 19) and not _isnum(iccid, 20):
            raise ValueError('ICCID must be 19 or 20 digits !')

    else:
        if opts.num is None:
            raise ValueError('Neither ICCID nor card number specified !')

        iccid = (
            '89' +  # Common prefix (telecom)
            cc_digits +  # Country Code on 2/3 digits
            plmn_digits  # MCC/MNC on 5/6 digits
        )

        ml = 18 - len(iccid)

        if opts.secret is None:
            # The raw number
            iccid += ('%%0%dd' % ml) % opts.num
        else:
            # Randomized digits
            iccid += _digits(opts.secret, 'ccid', ml, opts.num)

        # Add checksum digit
        iccid += ('%1d' % calculate_luhn(iccid))

    # IMSI (15 digits usually)
    if opts.imsi is not None:
        imsi = opts.imsi
        if not _isnum(imsi):
            raise ValueError('IMSI must be digits only !')

    else:
        if opts.num is None:
            raise ValueError('Neither IMSI nor card number specified !')

        ml = 15 - len(plmn_digits)

        if opts.secret is None:
            # The raw number
            msin = ('%%0%dd' % ml) % opts.num
        else:
            # Randomized digits
            msin = _digits(opts.secret, 'imsi', ml, opts.num)

        imsi = (
            plmn_digits +  # MCC/MNC on 5/6 digits
            msin  # MSIN
        )

    # SMSP
    if opts.smsp is not None:
        smsp = opts.smsp
        if not _ishex(smsp):
            raise ValueError('SMSP must be hex digits only !')
        if len(smsp) < 28 * 2:
            raise ValueError('SMSP must be at least 28 bytes')

    else:
        ton = "81"
        if opts.smsc is not None:
            smsc = opts.smsc
            if smsc[0] == '+':
                ton = "91"
                smsc = smsc[1:]
            if not _isnum(smsc):
                raise ValueError('SMSC must be digits only!\n \
					Start with \'+\' for international numbers')
        else:
            smsc = '00%d' % opts.country + '5555'  # Hack ...

        smsc = '%02d' % (
            (len(smsc) + 3) // 2, ) + ton + swap_nibbles(rpad(smsc, 20))

        smsp = (
            'e1' +  # Parameters indicator
            'ff' * 12 +  # TP-Destination address
            smsc +  # TP-Service Centre Address
            '00' +  # TP-Protocol identifier
            '00' +  # TP-Data coding scheme
            '00'  # TP-Validity period
        )

    # ACC
    if opts.acc is not None:
        acc = opts.acc
        if not _ishex(acc):
            raise ValueError('ACC must be hex digits only !')
        if len(acc) != 2 * 2:
            raise ValueError('ACC must be exactly 2 bytes')

    else:
        acc = None

    # Ki (random)
    if opts.ki is not None:
        ki = opts.ki
        if not re.match('^[0-9a-fA-F]{32}$', ki):
            raise ValueError('Ki needs to be 128 bits, in hex format')
    else:
        ki = ''.join(['%02x' % random.randrange(0, 256) for i in range(16)])

    # OPC (random)
    if opts.opc is not None:
        opc = opts.opc
        if not re.match('^[0-9a-fA-F]{32}$', opc):
            raise ValueError('OPC needs to be 128 bits, in hex format')

    elif opts.op is not None:
        opc = derive_milenage_opc(ki, opts.op)
    else:
        opc = ''.join(['%02x' % random.randrange(0, 256) for i in range(16)])

    pin_adm = sanitize_pin_adm(opts.pin_adm, opts.pin_adm_hex)

    # ePDG Selection Information
    if opts.epdgSelection:
        if len(opts.epdgSelection) < 5 or len(opts.epdgSelection) > 6:
            raise ValueError('ePDG Selection Information is not valid')
        epdg_mcc = opts.epdgSelection[:3]
        epdg_mnc = opts.epdgSelection[3:]
        if not epdg_mcc.isdigit() or not epdg_mnc.isdigit():
            raise ValueError(
                'PLMN for ePDG Selection must only contain decimal digits')

    # Return that
    return {
        'name': opts.name,
        'iccid': iccid,
        'mcc': mcc,
        'mnc': mnc,
        'imsi': imsi,
        'smsp': smsp,
        'ki': ki,
        'opc': opc,
        'acc': acc,
        'pin_adm': pin_adm,
        'msisdn': opts.msisdn,
        'epdgid': opts.epdgid,
        'epdgSelection': opts.epdgSelection,
        'pcscf': opts.pcscf,
        'ims_hdomain': opts.ims_hdomain,
        'impi': opts.impi,
        'impu': opts.impu,
        'opmode': opts.opmode,
    }
Exemplo n.º 2
0
def gen_parameters(opts):
    """Generates Name, ICCID, MCC, MNC, IMSI, SMSP, Ki, PIN-ADM from the
	options given by the user"""

    # MCC/MNC
    mcc = opts.mcc
    mnc = opts.mnc

    if not ((0 < mcc < 999) and (0 < mnc < 999)):
        raise ValueError('mcc & mnc must be between 0 and 999')

    # Digitize country code (2 or 3 digits)
    cc_digits = _cc_digits(opts.country)

    # Digitize MCC/MNC (5 or 6 digits)
    plmn_digits = _mcc_mnc_digits(mcc, mnc)

    # ICCID (19 digits, E.118), though some phase1 vendors use 20 :(
    if opts.iccid is not None:
        iccid = opts.iccid
        if not _isnum(iccid, 19) and not _isnum(iccid, 20):
            raise ValueError('ICCID must be 19 or 20 digits !')

    else:
        if opts.num is None:
            raise ValueError('Neither ICCID nor card number specified !')

        iccid = (
            '89' +  # Common prefix (telecom)
            cc_digits +  # Country Code on 2/3 digits
            plmn_digits  # MCC/MNC on 5/6 digits
        )

        ml = 18 - len(iccid)

        if opts.secret is None:
            # The raw number
            iccid += ('%%0%dd' % ml) % opts.num
        else:
            # Randomized digits
            iccid += _digits(opts.secret, 'ccid', ml, opts.num)

        # Add checksum digit
        iccid += ('%1d' % calculate_luhn(iccid))

    # IMSI (15 digits usually)
    if opts.imsi is not None:
        imsi = opts.imsi
        if not _isnum(imsi):
            raise ValueError('IMSI must be digits only !')

    else:
        if opts.num is None:
            raise ValueError('Neither IMSI nor card number specified !')

        ml = 15 - len(plmn_digits)

        if opts.secret is None:
            # The raw number
            msin = ('%%0%dd' % ml) % opts.num
        else:
            # Randomized digits
            msin = _digits(opts.secret, 'imsi', ml, opts.num)

        imsi = (
            plmn_digits +  # MCC/MNC on 5/6 digits
            msin  # MSIN
        )

    # SMSP
    if opts.smsp is not None:
        smsp = opts.smsp
        if not _ishex(smsp):
            raise ValueError('SMSP must be hex digits only !')
        if len(smsp) < 28 * 2:
            raise ValueError('SMSP must be at least 28 bytes')

    else:
        if opts.smsc is not None:
            smsc = opts.smsc
            if not _isnum(smsc):
                raise ValueError('SMSC must be digits only !')
        else:
            smsc = '00%d' % opts.country + '5555'  # Hack ...

        smsc = '%02d' % (
            (len(smsc) + 3) // 2, ) + "81" + swap_nibbles(rpad(smsc, 20))

        smsp = (
            'e1' +  # Parameters indicator
            'ff' * 12 +  # TP-Destination address
            smsc +  # TP-Service Centre Address
            '00' +  # TP-Protocol identifier
            '00' +  # TP-Data coding scheme
            '00'  # TP-Validity period
        )

    # ACC
    if opts.acc is not None:
        acc = opts.acc
        if not _ishex(acc):
            raise ValueError('ACC must be hex digits only !')
        if len(acc) != 2 * 2:
            raise ValueError('ACC must be exactly 2 bytes')

    else:
        acc = None

    # Ki (random)
    if opts.ki is not None:
        ki = opts.ki
        if not re.match('^[0-9a-fA-F]{32}$', ki):
            raise ValueError('Ki needs to be 128 bits, in hex format')
    else:
        ki = ''.join(['%02x' % random.randrange(0, 256) for i in range(16)])

    # OPC (random)
    if opts.opc is not None:
        opc = opts.opc
        if not re.match('^[0-9a-fA-F]{32}$', opc):
            raise ValueError('OPC needs to be 128 bits, in hex format')

    elif opts.op is not None:
        opc = derive_milenage_opc(ki, opts.op)
    else:
        opc = ''.join(['%02x' % random.randrange(0, 256) for i in range(16)])

    if opts.pin_adm is not None:
        if len(opts.pin_adm) <= 8:
            pin_adm = ''.join(['%02x' % (ord(x)) for x in opts.pin_adm])
            pin_adm = rpad(pin_adm, 16)
        elif len(opts.pin_adm) == 16:
            pin_adm = opts.pin_adm
        else:
            raise ValueError(
                "PIN-ADM needs to be <=8 digits (ascii) or exactly 16 digits (raw hex)"
            )
    else:
        pin_adm = None

    # Return that
    return {
        'name': opts.name,
        'iccid': iccid,
        'mcc': mcc,
        'mnc': mnc,
        'imsi': imsi,
        'smsp': smsp,
        'ki': ki,
        'opc': opc,
        'acc': acc,
        'pin_adm': pin_adm,
    }