ref: 2ab93fd7168a7d0ad8e1bc19f4e9cbee45237c99
author: kitzman <[email protected]>
date: Thu Nov 16 06:52:47 EST 2023
first commit
--- /dev/null
+++ b/.gitignore
@@ -1,0 +1,2 @@
+*.out
+*.[05678qvt]
--- /dev/null
+++ b/README
@@ -1,0 +1,7 @@
+TOTP tool to use with factotum.
+
+How?
+
+echo 'key proto=pass totp=provider user=account !password=secret' >/mnt/factotum/ctl
+
+utotp provider account
--- /dev/null
+++ b/mkfile
@@ -1,0 +1,14 @@
+</$objtype/mkfile
+BIN=/$objtype/bin
+
+TARG=utotp
+OFILES=\
+ utotp.$O\
+
+UPDATE=\
+ mkfile\
+ $HFILES\
+ ${OFILES:%.$O=%.c}\
+ ${TARG:%=/386/bin/%}\
+
+</sys/src/cmd/mkone
--- /dev/null
+++ b/utotp.c
@@ -1,0 +1,101 @@
+#include <u.h>
+#include <libc.h>
+#include <auth.h>
+#include <libsec.h>
+
+#define FValueLen 32
+#define SecretLen 4096
+#define TotpMKeyLen 4096
+
+char *argv0;
+char provider[FValueLen], account[FValueLen];
+
+void
+beput8(uchar *buf, u64int v)
+{
+ buf[7] = v & 0xff; v >>= 8;
+ buf[6] = v & 0xff; v >>= 8;
+ buf[5] = v & 0xff; v >>= 8;
+ buf[4] = v & 0xff; v >>= 8;
+ buf[3] = v & 0xff; v >>= 8;
+ buf[2] = v & 0xff; v >>= 8;
+ buf[1] = v & 0xff; v >>= 8;
+ buf[0] = v & 0xff;
+}
+
+u32int
+beget4(uchar *buf)
+{
+ return buf[3] | buf[2] << 8 | buf[1] << 16 | buf[0] << 24;
+}
+
+
+u32int
+gettoken(char *secret)
+{
+ ulong ts;
+ u32int token;
+ long keylen;
+
+ uchar key[TotpMKeyLen], digest[SHA1dlen], buf[8], offset;
+
+ ts = (ulong)time(nil) / 30;
+
+ keylen = dec32(key, TotpMKeyLen, secret, strlen(secret));
+ beput8(buf, ts);
+
+ hmac_sha1(buf, 8, key, keylen, digest, nil);
+
+ offset = digest[SHA1dlen - 1] & 0x0f;
+ token = beget4(&digest[offset]);
+ token &= 0x7fffffff;
+ token %= 1000000;
+
+ return token;
+}
+
+char*
+getsecret(void)
+{
+ UserPasswd *up;
+ char *secret;
+
+ up = auth_getuserpasswd(auth_getkey, "proto=pass totp=%s user=%s", provider, account);
+
+ if(up == nil)
+ return nil;
+
+ secret = malloc(sizeof(char) * SecretLen);
+ strcpy(secret, up->passwd);
+
+ return secret;
+}
+
+void
+usage(void)
+{
+ fprint(2, "usage: %s provider account\n", argv0);
+ exits("usage");
+}
+
+void
+main(int argc, char **argv)
+{
+ u32int token;
+ char *secret;
+
+ argv0 = argv[0];
+ if(argc != 3)
+ usage();
+
+ strcpy(provider, argv[1]);
+ strcpy(account, argv[2]);
+
+ if((secret = getsecret()) == nil) {
+ fprint(2, "unable to find secret\n");
+ exits("nocreds\n");
+ }
+
+ token = gettoken(secret);
+ print("%06ud\n", token);
+}