Implement keyfile writeback.
git-svn-id: svn+ssh://svn.openpam.org/svn/openpam/trunk@784 185d5e19-27fe-0310-9dcf-9bff6b9f3609
This commit is contained in:
parent
ebdefa45ca
commit
38622bad18
|
@ -36,7 +36,7 @@
|
|||
.Nd OATH key management tool
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl hv
|
||||
.Op Fl hvw
|
||||
.Op Fl u Ar user
|
||||
.Op Fl k Ar keyfile
|
||||
.Ar command
|
||||
|
@ -61,12 +61,16 @@ The default is the current user.
|
|||
Only root may operate on other users.
|
||||
.It Fl v
|
||||
Enable verbose mode.
|
||||
.It Fl w
|
||||
Enable writeback mode (see below).
|
||||
.El
|
||||
.Pp
|
||||
The commands are:
|
||||
.Bl -tag -width 6n
|
||||
.It Cm genkey
|
||||
Generate a new key.
|
||||
If writeback mode is enabled, the user's key is set; otherwise, it is
|
||||
printed to standard output.
|
||||
.It Cm setkey Ar uri
|
||||
Set the user's key to the given otpauth URI.
|
||||
.It Cm uri
|
||||
|
@ -74,6 +78,8 @@ Print the user's key in otpauth URI form.
|
|||
.It Cm verify Ar code
|
||||
Verify that the given code is the correct current response for the
|
||||
user's key.
|
||||
If writeback mode is enabled and the response matched, the user's
|
||||
keyfile is updated to prevent reuse.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr oath_hotp 3 ,
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <pwd.h>
|
||||
#include <stdint.h>
|
||||
|
@ -54,10 +55,60 @@ enum { RET_SUCCESS, RET_FAILURE, RET_ERROR, RET_USAGE, RET_UNAUTH };
|
|||
static char *user;
|
||||
static char *keyfile;
|
||||
static int verbose;
|
||||
static int writeback;
|
||||
|
||||
static int isroot; /* running as root */
|
||||
static int issameuser; /* real user same as target user */
|
||||
|
||||
/*
|
||||
* Print key in otpauth URI form
|
||||
*/
|
||||
static int
|
||||
oathkey_print(struct oath_key *key)
|
||||
{
|
||||
char *keyuri;
|
||||
|
||||
if ((keyuri = oath_key_to_uri(key)) == NULL) {
|
||||
warnx("failed to convert key to otpauth URI");
|
||||
return (RET_ERROR);
|
||||
}
|
||||
printf("%s\n", keyuri);
|
||||
free(keyuri);
|
||||
return (RET_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Save key to file
|
||||
* XXX liboath should take care of this for us
|
||||
*/
|
||||
static int
|
||||
oathkey_save(struct oath_key *key)
|
||||
{
|
||||
char *keyuri;
|
||||
int fd, len, ret;
|
||||
|
||||
keyuri = NULL;
|
||||
len = 0;
|
||||
fd = ret = -1;
|
||||
if ((keyuri = oath_key_to_uri(key)) == NULL) {
|
||||
warnx("failed to convert key to otpauth URI");
|
||||
goto done;
|
||||
}
|
||||
len = strlen(keyuri);
|
||||
if ((fd = open(keyfile, O_WRONLY|O_CREAT|O_TRUNC, 0600)) < 0 ||
|
||||
write(fd, keyuri, len) != len || write(fd, "\n", 1) != 1) {
|
||||
warn("%s", keyfile);
|
||||
goto done;
|
||||
}
|
||||
ret = 0;
|
||||
done:
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
if (keyuri != NULL)
|
||||
free(keyuri);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate a new key
|
||||
*/
|
||||
|
@ -65,6 +116,7 @@ static int
|
|||
oathkey_genkey(int argc, char *argv[])
|
||||
{
|
||||
struct oath_key *key;
|
||||
int ret;
|
||||
|
||||
/* XXX add parameters later */
|
||||
if (argc != 0)
|
||||
|
@ -77,10 +129,9 @@ oathkey_genkey(int argc, char *argv[])
|
|||
|
||||
if ((key = oath_key_create(user, om_totp, oh_undef, NULL, 0)) == NULL)
|
||||
return (RET_ERROR);
|
||||
/* XXX should save to file, not print */
|
||||
printf("%s\n", oath_key_to_uri(key));
|
||||
ret = writeback ? oathkey_save(key) : oathkey_print(key);
|
||||
oath_key_free(key);
|
||||
return (RET_SUCCESS);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -90,6 +141,7 @@ static int
|
|||
oathkey_setkey(int argc, char *argv[])
|
||||
{
|
||||
struct oath_key *key;
|
||||
int ret;
|
||||
|
||||
/* XXX add parameters later */
|
||||
if (argc != 1)
|
||||
|
@ -102,10 +154,9 @@ oathkey_setkey(int argc, char *argv[])
|
|||
|
||||
if ((key = oath_key_from_uri(argv[0])) == NULL)
|
||||
return (RET_ERROR);
|
||||
/* XXX should save to file, not print */
|
||||
printf("%s\n", oath_key_to_uri(key));
|
||||
ret = oathkey_save(key);
|
||||
oath_key_free(key);
|
||||
return (RET_SUCCESS);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -115,6 +166,7 @@ static int
|
|||
oathkey_uri(int argc, char *argv[])
|
||||
{
|
||||
struct oath_key *key;
|
||||
int ret;
|
||||
|
||||
if (argc != 0)
|
||||
return (RET_USAGE);
|
||||
|
@ -126,9 +178,9 @@ oathkey_uri(int argc, char *argv[])
|
|||
|
||||
if ((key = oath_key_from_file(keyfile)) == NULL)
|
||||
return (RET_ERROR);
|
||||
printf("%s\n", oath_key_to_uri(key));
|
||||
ret = oathkey_print(key);
|
||||
oath_key_free(key);
|
||||
return (RET_SUCCESS);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -140,7 +192,7 @@ oathkey_verify(int argc, char *argv[])
|
|||
struct oath_key *key;
|
||||
unsigned long response;
|
||||
char *end;
|
||||
int match;
|
||||
int match, ret;
|
||||
|
||||
if (argc < 1)
|
||||
return (RET_USAGE);
|
||||
|
@ -163,11 +215,11 @@ oathkey_verify(int argc, char *argv[])
|
|||
if (verbose)
|
||||
warnx("response: %lu %s", response,
|
||||
match ? "matched" : "did not match");
|
||||
if (match) {
|
||||
/* XXX write key back! */
|
||||
}
|
||||
ret = match ? RET_SUCCESS : RET_FAILURE;
|
||||
if (match && writeback)
|
||||
ret = oathkey_save(key);
|
||||
oath_key_free(key);
|
||||
return (match ? RET_SUCCESS : RET_FAILURE);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -177,7 +229,7 @@ static void
|
|||
usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"usage: oathkey [-hv] [-u user] [-k keyfile] <command>\n"
|
||||
"usage: oathkey [-hvw] [-u user] [-k keyfile] <command>\n"
|
||||
"\n"
|
||||
"Commands:\n"
|
||||
" genkey Generate a new key\n"
|
||||
|
@ -198,7 +250,7 @@ main(int argc, char *argv[])
|
|||
/*
|
||||
* Parse command-line options
|
||||
*/
|
||||
while ((opt = getopt(argc, argv, "hk:u:v")) != -1)
|
||||
while ((opt = getopt(argc, argv, "hk:u:vw")) != -1)
|
||||
switch (opt) {
|
||||
case 'k':
|
||||
keyfile = optarg;
|
||||
|
@ -209,6 +261,9 @@ main(int argc, char *argv[])
|
|||
case 'v':
|
||||
++verbose;
|
||||
break;
|
||||
case 'w':
|
||||
++writeback;
|
||||
break;
|
||||
case 'h':
|
||||
default:
|
||||
usage();
|
||||
|
|
Loading…
Reference in New Issue