shithub: utotp

Download patch

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);
+}