shithub: utotp

ref: 2ab93fd7168a7d0ad8e1bc19f4e9cbee45237c99
dir: /utotp.c/

View raw version
#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);
}