xref: /netbsd-src/external/bsd/pam-u2f/dist/tests/regenerate_credentials.py (revision 540ca2718c85d7b6631d382e3e93f4dc91e51282)
1*540ca271Schristos#!/usr/bin/env python3
23ff1169cSchristos
33ff1169cSchristosimport collections
4*540ca271Schristosimport itertools
5*540ca271Schristosimport os
63ff1169cSchristosimport re
73ff1169cSchristosimport subprocess
83ff1169cSchristosimport sys
9*540ca271Schristosimport os
103ff1169cSchristos
11*540ca271SchristosPUC = os.getenv("PAMU2FCFG", "../pamu2fcfg/pamu2fcfg")
123ff1169cSchristos
133ff1169cSchristosresident = ["", "-r"]
143ff1169cSchristos
153ff1169cSchristospresence = ["", "-P"]
163ff1169cSchristos
173ff1169cSchristospin = ["", "-N"]
183ff1169cSchristos
193ff1169cSchristosverification = ["", "-V"]
203ff1169cSchristos
21*540ca271SchristosCredential = collections.namedtuple(
22*540ca271Schristos    "Credential", "keyhandle pubkey attributes oldformat"
23*540ca271Schristos)
243ff1169cSchristos
253ff1169cSchristos
26*540ca271Schristosdef read_credentials(filename):
27*540ca271Schristos    with open(filename, "r") as handle:
28*540ca271Schristos        line = handle.readline()
293ff1169cSchristos
30*540ca271Schristos    credentials = []
31*540ca271Schristos    for credstr in line.split(":")[1:]:
32*540ca271Schristos        matches = re.match(r"^(.*?),(.*?),es256,(.*)$", credstr, re.M)
33*540ca271Schristos        credentials.append(
34*540ca271Schristos            Credential(
35*540ca271Schristos                keyhandle=matches.group(1),
36*540ca271Schristos                pubkey=matches.group(2),
37*540ca271Schristos                attributes=matches.group(3),
38*540ca271Schristos                oldformat=0,
39*540ca271Schristos            )
40*540ca271Schristos        )
41*540ca271Schristos    return credentials
42*540ca271Schristos
43*540ca271Schristos
44*540ca271Schristosdef print_test_case(filename, credentials):
45*540ca271Schristos    start = """\
46*540ca271Schristos  dev = calloc(cfg.max_devs, sizeof(*dev));
47*540ca271Schristos  assert(dev != NULL);
483ff1169cSchristos  cfg.auth_file = "{authfile}";
493ff1169cSchristos  rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
50*540ca271Schristos  assert(rc == PAM_SUCCESS);
513ff1169cSchristos  assert(n_devs == {devices});
523ff1169cSchristos"""
533ff1169cSchristos
54*540ca271Schristos    checks = """\
553ff1169cSchristos  assert(strcmp(dev[{i}].coseType, "es256") == 0);
563ff1169cSchristos  assert(strcmp(dev[{i}].keyHandle, "{kh}") == 0);
573ff1169cSchristos  assert(strcmp(dev[{i}].publicKey, "{pk}") == 0);
583ff1169cSchristos  assert(strcmp(dev[{i}].attributes, "{attr}") == 0);
593ff1169cSchristos  assert(dev[{i}].old_format == {old});
603ff1169cSchristos"""
613ff1169cSchristos
62*540ca271Schristos    end = """\
63*540ca271Schristos  free_devices(dev, n_devs);
643ff1169cSchristos"""
653ff1169cSchristos
663ff1169cSchristos    code = ""
673ff1169cSchristos    free_block = ""
683ff1169cSchristos
69*540ca271Schristos    code += start.format(authfile=filename, devices=len(credentials))
703ff1169cSchristos    for c, v in enumerate(credentials):
71*540ca271Schristos        code += checks.format(
72*540ca271Schristos            i=c, kh=v.keyhandle, pk=v.pubkey, attr=v.attributes, old=v.oldformat
73*540ca271Schristos        )
743ff1169cSchristos
75*540ca271Schristos    code += end
763ff1169cSchristos
773ff1169cSchristos    print(code)
783ff1169cSchristos
793ff1169cSchristos
80*540ca271Schristosdef generate_credential(filename, mode, *args):
81*540ca271Schristos    command = [PUC, "-u@USERNAME@" if mode == "w" else "-n"]
82*540ca271Schristos    command.extend([x for x in args if x.strip() != ""])
83*540ca271Schristos    line = subprocess.check_output(command).decode("utf-8")
84*540ca271Schristos    with open(filename, mode) as handle:
85*540ca271Schristos        handle.write(line)
863ff1169cSchristos
87*540ca271Schristos    matches = re.match(r"^.*?:(.*?),(.*?),es256,(.*)", line, re.M)
88*540ca271Schristos    return Credential(
89*540ca271Schristos        keyhandle=matches.group(1),
903ff1169cSchristos        pubkey=matches.group(2),
913ff1169cSchristos        attributes=matches.group(3),
92*540ca271Schristos        oldformat=0,
93*540ca271Schristos    )
943ff1169cSchristos
95*540ca271Schristos
96*540ca271Schristos# Single credentials
97*540ca271Schristosprint("Generating single credentials", file=sys.stderr)
98*540ca271Schristos
99*540ca271Schristosfor (r, p, n, v) in itertools.product(resident, presence, pin, verification):
100*540ca271Schristos    filename = "credentials/new_" + r + p + v + n + ".cred.in"
101*540ca271Schristos    if not os.path.exists(filename):
102*540ca271Schristos        print("Generating " + filename, file=sys.stderr)
103*540ca271Schristos        generate_credential(filename, "w", r, p, v, n)
104*540ca271Schristos    credentials = read_credentials(filename)
105*540ca271Schristos    filename = os.path.splitext(filename)[0]
106*540ca271Schristos    print_test_case(filename, credentials)
1073ff1169cSchristos
1083ff1169cSchristos
1093ff1169cSchristos# Double credentials
110*540ca271Schristosprint("Generating double credentials", file=sys.stderr)
1113ff1169cSchristos
112*540ca271Schristosfor (r, p, n, v) in itertools.product(resident, presence, pin, verification):
113*540ca271Schristos    filename = "credentials/new_double_" + r + p + v + n + ".cred.in"
114*540ca271Schristos    if not os.path.exists(filename):
115*540ca271Schristos        print("Generating " + filename, file=sys.stderr)
116*540ca271Schristos        generate_credential(filename, "w", r, p, v, n),
117*540ca271Schristos        generate_credential(filename, "a", r, p, v, n),
118*540ca271Schristos    credentials = read_credentials(filename)
119*540ca271Schristos    filename = os.path.splitext(filename)[0]
120*540ca271Schristos    print_test_case(filename, credentials)
1213ff1169cSchristos
1223ff1169cSchristos# Mixed credentials
123*540ca271Schristosprint("Mixed double credentials", file=sys.stderr)
1243ff1169cSchristos
125*540ca271Schristosfor (p1, p2) in itertools.product(presence, presence):
126*540ca271Schristos    filename = "credentials/new_mixed_" + p1 + "1" + p2 + "2" + ".cred.in"
127*540ca271Schristos    if not os.path.exists(filename):
128*540ca271Schristos        print("Generating " + filename, file=sys.stderr)
129*540ca271Schristos        generate_credential(filename, "w", p1),
130*540ca271Schristos        generate_credential(filename, "a", p2),
131*540ca271Schristos    credentials = read_credentials(filename)
132*540ca271Schristos    filename = os.path.splitext(filename)[0]
133*540ca271Schristos    print_test_case(filename, credentials)
134