More fixed from Fabien COELHO <coelho@cri.ensmp.fr>. Check for
current OTP before allowing the update. git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@1251 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
112
appl/otp/otp.c
112
appl/otp/otp.c
@@ -73,6 +73,11 @@ usage (void)
|
|||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Renew the OTP for a user.
|
||||||
|
* The pass-phrase is not required (RFC 1938/8.0)
|
||||||
|
*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
renew (int argc, char **argv, OtpAlgorithm *alg, char *user)
|
renew (int argc, char **argv, OtpAlgorithm *alg, char *user)
|
||||||
{
|
{
|
||||||
@@ -85,28 +90,21 @@ renew (int argc, char **argv, OtpAlgorithm *alg, char *user)
|
|||||||
if (argc != 2)
|
if (argc != 2)
|
||||||
usage();
|
usage();
|
||||||
|
|
||||||
ctx = &oldctx;
|
newctx.alg = alg;
|
||||||
if(otp_challenge (ctx, user, prompt, sizeof(prompt)))
|
newctx.user = user;
|
||||||
return 1;
|
newctx.n = atoi (argv[0]);
|
||||||
if(des_read_pw_string (pw, sizeof(pw), prompt, 0))
|
strncpy (newctx.seed, argv[1], sizeof(newctx.seed));
|
||||||
return 1;
|
newctx.seed[sizeof(newctx.seed) - 1] = '\0';
|
||||||
ret = otp_verify_user_1 (ctx, pw);
|
strlwr(newctx.seed);
|
||||||
if (ret == 0) {
|
sprintf (prompt, "[ otp-%s %u %s ]",
|
||||||
newctx.alg = alg;
|
newctx.alg->name,
|
||||||
newctx.user = user;
|
newctx.n,
|
||||||
newctx.n = atoi (argv[0]);
|
newctx.seed);
|
||||||
strncpy (newctx.seed, argv[1], sizeof(newctx.seed));
|
if (des_read_pw_string (pw, sizeof(pw), prompt, 0) == 0 &&
|
||||||
newctx.seed[sizeof(newctx.seed) - 1] = '\0';
|
otp_parse (newctx.key, pw, alg) == 0) {
|
||||||
strlwr(newctx.seed);
|
ctx = &newctx;
|
||||||
sprintf (prompt, "[ otp-%s %u %s ]",
|
|
||||||
newctx.alg->name,
|
|
||||||
newctx.n,
|
|
||||||
newctx.seed);
|
|
||||||
if (des_read_pw_string (pw, sizeof(pw), prompt, 0) == 0 &&
|
|
||||||
otp_parse (newctx.key, pw, alg) == 0) {
|
|
||||||
ctx = &newctx;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dbm = otp_db_open ();
|
dbm = otp_db_open ();
|
||||||
if (dbm == NULL) {
|
if (dbm == NULL) {
|
||||||
fprintf (stderr, "%s: otp_db_open failed\n", prog);
|
fprintf (stderr, "%s: otp_db_open failed\n", prog);
|
||||||
@@ -117,6 +115,32 @@ renew (int argc, char **argv, OtpAlgorithm *alg, char *user)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return 0 if the user could enter the next OTP.
|
||||||
|
* I would rather have returned !=0 but it's shell-like here around.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int
|
||||||
|
verify_user_otp(char *username)
|
||||||
|
{
|
||||||
|
OtpContext ctx;
|
||||||
|
char passwd[OTP_MAX_PASSPHRASE + 1];
|
||||||
|
char prompt[128], ss[256];
|
||||||
|
|
||||||
|
if (otp_challenge (&ctx, username, ss, sizeof(ss)) != 0) {
|
||||||
|
fprintf(stderr, "%s: no otp challenge found\n", prog);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf (prompt, "%s's %s Password: ", username, ss);
|
||||||
|
des_read_pw_string(passwd, sizeof(passwd)-1, prompt, 0);
|
||||||
|
return otp_verify_user (&ctx, passwd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the OTP for a user
|
||||||
|
*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
set (int argc, char **argv, OtpAlgorithm *alg, char *user)
|
set (int argc, char **argv, OtpAlgorithm *alg, char *user)
|
||||||
{
|
{
|
||||||
@@ -187,6 +211,31 @@ delete_otp (int argc, char **argv, char *user)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tell whether the user has an otp
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int
|
||||||
|
has_an_otp(char *user)
|
||||||
|
{
|
||||||
|
void *db;
|
||||||
|
OtpContext ctx;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
db = otp_db_open ();
|
||||||
|
if(db == NULL) {
|
||||||
|
fprintf (stderr, "%s: otp_db_open failed\n", prog);
|
||||||
|
return 0; /* if no db no otp! */
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.user = user;
|
||||||
|
ret = otp_simple_get(db, &ctx);
|
||||||
|
if (!ret) free(ctx.alg);
|
||||||
|
|
||||||
|
otp_db_close (db);
|
||||||
|
return !ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get and print out the otp entry for some user
|
* Get and print out the otp entry for some user
|
||||||
*/
|
*/
|
||||||
@@ -290,8 +339,8 @@ main (int argc, char **argv)
|
|||||||
if (!(listp || deletep || renewp))
|
if (!(listp || deletep || renewp))
|
||||||
defaultp = 1;
|
defaultp = 1;
|
||||||
|
|
||||||
if ( listp + deletep + renewp + defaultp != 1) /* one of -d or -l or -r or none */
|
if ( listp + deletep + renewp + defaultp != 1)
|
||||||
usage();
|
usage(); /* one of -d or -l or -r or none */
|
||||||
|
|
||||||
if (listp)
|
if (listp)
|
||||||
return list_otps (argc, argv, user);
|
return list_otps (argc, argv, user);
|
||||||
@@ -307,6 +356,23 @@ main (int argc, char **argv)
|
|||||||
user = pwd->pw_name;
|
user = pwd->pw_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* users other that root must provide the next OTP to update the sequence.
|
||||||
|
* it avoids someone to use a pending session to change an OTP sequence.
|
||||||
|
* see RFC 1938/8.0.
|
||||||
|
*/
|
||||||
|
if (uid != 0 && (defaultp || renewp)) {
|
||||||
|
if (!has_an_otp(user)) {
|
||||||
|
fprintf(stderr, "%s: Only root can set an initial OTP\n", prog);
|
||||||
|
return 1;
|
||||||
|
} else { /* Check the next OTP (RFC 1938/8.0: SHOULD) */
|
||||||
|
if (verify_user_otp(user) != 0) {
|
||||||
|
fprintf(stderr, "%s: User authentification failed\n", prog);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (deletep)
|
if (deletep)
|
||||||
return delete_otp (argc, argv, user);
|
return delete_otp (argc, argv, user);
|
||||||
else if (renewp)
|
else if (renewp)
|
||||||
|
Reference in New Issue
Block a user