File: yubiclient

package info (click to toggle)
python-yubiotp 1.0.0.post1-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 196 kB
  • sloc: python: 671; makefile: 130
file content (87 lines) | stat: -rwxr-xr-x 3,324 bytes parent folder | download
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()