Created
May 3, 2022 13:39
-
-
Save mentha/dac51297dc4c47ff0ce8c2f08c91ae4c to your computer and use it in GitHub Desktop.
manage pam_oath auth file
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# update OTP auth file of pam_oath | |
OATHFILE = '/etc/users.oath' | |
from base64 import b16encode, b16decode, b32encode | |
from sys import argv | |
import os | |
import subprocess as sp | |
if len(argv) < 2: | |
print(f'''usage: {argv[0]} [options] user | |
manage otp auth file | |
options: | |
-d remove oath auth | |
-l reset creds but do not show | |
-v view creds''') | |
exit(1) | |
cmd = None | |
user = None | |
for o in argv[1:]: | |
if not (cmd is None) and o in {'-d', '-l', '-v'}: | |
raise RuntimeError('conflicting operations') | |
if o == '-d': | |
cmd = 'delete' | |
elif o == '-l': | |
cmd = 'lock' | |
elif o == '-v': | |
cmd = 'view' | |
elif o.startswith('-'): | |
raise RuntimeError(f'unknown option {o}') | |
else: | |
if user: | |
raise RuntimeError('user already specified') | |
user = o | |
if not cmd: | |
cmd = 'update' | |
lines = None | |
with open(OATHFILE) as f: | |
lines = f.readlines() | |
uline = None | |
if cmd in {'update', 'delete', 'lock'}: | |
uidx = -1 | |
for i in range(len(lines)): | |
l = lines[i].strip() | |
if l.startswith('#'): | |
continue | |
l = l.split() | |
if l[1] == user: | |
uline = l | |
uidx = i | |
break | |
if uidx >= 0: | |
lines.pop(uidx) | |
if cmd in {'update', 'lock'}: | |
k = None | |
with open('/dev/urandom', 'rb') as f: | |
k = f.read(10) | |
uline = ['HOTP/T30/6', user, '-', b16encode(k).decode().lower()] | |
lines.append(' '.join(uline)) | |
with open(OATHFILE, 'w') as f: | |
for l in lines: | |
f.write(l.strip() + '\n') | |
if cmd in {'update', 'view'}: | |
if not uline: | |
raise RuntimeError('user not found') | |
b32 = b32encode(b16decode(uline[3].upper())).decode() | |
print(f'secret in base32 is {b32}') | |
sp.run(['qrencode', '-t', 'ANSI256UTF8'], input=f'otpauth://totp/pam_oath:{user}@{os.uname().nodename}?secret={b32}&issuer=pam_oath', universal_newlines=True) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment