1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
|
#!/usr/bin/env python
from __future__ import print_function
import sys
from base64 import b64decode
from optparse import OptionParser
from yubiotp.client import YubiClient10, YubiClient11, YubiClient20
def main():
options, args = parse_args()
api_key = b64decode(options.api_key.encode()) if (options.api_key is not None) else None
if options.version == '1.0':
client = YubiClient10(options.api_id, api_key, options.ssl)
elif options.version == '1.1':
client = YubiClient11(options.api_id, api_key, options.ssl, options.timestamp)
elif options.version == '2.0':
client = YubiClient20(options.api_id, api_key, options.ssl, options.timestamp, options.sl, options.timeout)
if options.base_url:
client.base_url = options.base_url
is_valid = True
for token in args:
if options.noexec:
print(client.url(token))
else:
if not verify_otp(client, token, options.verbose):
is_valid = False
sys.exit(0 if is_valid else 2)
def parse_args():
parser = OptionParser(
usage='%prog [options] otp ...',
description="Verifies one or more YubiKey OTP tokens against a YubiCloud service. If you don't supply an API id and key, signatures will be ignored."
)
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help="Print request URL and full responst to stderr.")
parser.add_option('-n', '--noexec', action='store_true', dest='noexec', help="Don't send the request, just print the URL.")
parser.add_option('-V', '--version', dest='version', type='choice', choices=['1.0', '1.1', '2.0'], default='2.0', help="The API version to use (1.0, 1.1, 2.0). [%default]")
parser.add_option('-u', '--base-url', dest='base_url', help="Base URL of the api. Defaults to a version-appropriate URL on api.yubico.com.")
parser.add_option('-s', '--ssl', action='store_true', dest='ssl', help="Use an https url by default.")
parser.add_option('-i', '--api-id', dest='api_id', default='1', help="Your API ID. [%default]")
parser.add_option('-k', '--api-key', dest='api_key', help="Your base64-encoded API key.")
parser.add_option('-t', '--timestamp', action='store_true', dest='timestamp', help="(Version 1.1+) include timestamp and counter information in response.")
parser.add_option('--sl', dest='sl', help="(Version 2.0+) Request server syncing.")
parser.add_option('--timeout', dest='timeout', help="(Version 2.0+) Seconds to wait for sync response.")
options, args = parser.parse_args()
return options, args
def verify_otp(client, otp, verbose=False):
response = client.verify(otp)
if verbose:
print(client.url(otp), file=sys.stderr)
print(file=sys.stderr)
for line in filter(None, response.raw.splitlines()):
print(line, file=sys.stderr)
print(file=sys.stderr)
if response.public_id is not None:
print('public_id: {0}'.format(response.public_id), file=sys.stderr)
print(file=sys.stderr)
if response.is_ok():
is_valid = True
print('{0}: OK (strict)'.format(otp))
else:
is_valid = False
print('{0}: {1}'.format(otp, response.status()))
return is_valid
if __name__ == '__main__':
main()
|