122347Spst/* verify.c: The opieverify() library function.
222347Spst
329964Sache%%% copyright-cmetz-96
492906SmarkmThis software is Copyright 1996-2001 by Craig Metz, All Rights Reserved.
592906SmarkmThe Inner Net License Version 3 applies to this software.
622347SpstYou should have received a copy of the license with this software. If
722347Spstyou didn't get a copy, you may request one from <license@inner.net>.
822347Spst
922347Spst	History:
1022347Spst
1192906Smarkm	Modified by cmetz for OPIE 2.4. Use struct opie_otpkey for keys.
1292906Smarkm		Check that seed and sequence number are valid.
1359118Skris	Modified by cmetz for OPIE 2.32. Renamed _opieparsechallenge() to
1459118Skris		__opieparsechallenge() and handle new argument. Fixed init
1559118Skris		response parsing bug.
1659118Skris	Modified by cmetz for OPIE 2.31. Renamed "init" to "init-hex".
1729964Sache	Modified by cmetz for OPIE 2.31. Renamed "init" and "RESPONSE_INIT"
1829964Sache		to "init-hex" and "RESPONSE_INIT_HEX". Removed active attack
1929964Sache		protection support.
2022347Spst	Created by cmetz for OPIE 2.3 using the old verify.c as a guide.
2122347Spst*/
2222347Spst
2322347Spst#include "opie_cfg.h"
2422347Spst#ifdef HAVE_STRING_H
2522347Spst#include <string.h>
2622347Spst#endif /* HAVE_STRING_H */
2722347Spst#include "opie.h"
2822347Spst
2922347Spst#define RESPONSE_STANDARD  0
3022347Spst#define RESPONSE_WORD      1
3122347Spst#define RESPONSE_HEX       2
3229964Sache#define RESPONSE_INIT_HEX  3
3322347Spst#define RESPONSE_INIT_WORD 4
3422347Spst#define RESPONSE_UNKNOWN   5
3522347Spst
3622347Spststruct _rtrans {
3722347Spst  int type;
3822347Spst  char *name;
3922347Spst};
4022347Spst
4122347Spststatic struct _rtrans rtrans[] = {
4222347Spst  { RESPONSE_WORD, "word" },
4322347Spst  { RESPONSE_HEX, "hex" },
4429964Sache  { RESPONSE_INIT_HEX, "init-hex" },
4522347Spst  { RESPONSE_INIT_WORD, "init-word" },
4622347Spst  { RESPONSE_STANDARD, "" },
4722347Spst  { RESPONSE_UNKNOWN, NULL }
4822347Spst};
4922347Spst
5022347Spststatic char *algids[] = { NULL, NULL, NULL, "sha1", "md4", "md5" };
5122347Spst
5222347Spststatic int changed FUNCTION((opie), struct opie *opie)
5322347Spst{
5422347Spst  struct opie opie2;
5522347Spst
5622347Spst  memset(&opie2, 0, sizeof(struct opie));
5722347Spst  opie2.opie_principal = opie->opie_principal;
5822347Spst  if (__opiereadrec(&opie2))
5922347Spst    return 1;
6022347Spst
6122347Spst  if ((opie2.opie_n != opie->opie_n) || strcmp(opie2.opie_val, opie->opie_val) || strcmp(opie2.opie_seed, opie->opie_seed))
6222347Spst    return 1;
6322347Spst
6422347Spst  memset(&opie2, 0, sizeof(struct opie));
6522347Spst  return 0;
6622347Spst}
6722347Spst
6822347Spstint opieverify FUNCTION((opie, response), struct opie *opie AND char *response)
6922347Spst{
7022347Spst  int i, rval = -1;
7122347Spst  char *c;
7292906Smarkm  struct opie_otpkey key, fkey, lastkey;
7322347Spst  struct opie nopie;
7422347Spst
7522347Spst  if (!opie || !response)
7622347Spst    goto verret;
7722347Spst
7822347Spst  if (!opie->opie_principal)
7922347Spst#if DEBUG
8022347Spst    abort();
8122347Spst#else /* DEBUG */
8222347Spst    goto verret;
8322347Spst#endif /* DEBUG */
8422347Spst
8592906Smarkm  if (!opieatob8(&lastkey, opie->opie_val))
8622347Spst    goto verret;
8722347Spst
8892906Smarkm  for (c = opie->opie_seed; *c; c++)
8992906Smarkm    if (!isalnum(*c))
9092906Smarkm      goto verret;
9192906Smarkm
9292906Smarkm  if (opie->opie_n <= 0)
9392906Smarkm    goto verret;
9492906Smarkm
9522347Spst  if (c = strchr(response, ':')) {
9622347Spst    *(c++) = 0;
9722347Spst    {
9822347Spst      struct _rtrans *r;
9922347Spst      for (r = rtrans; r->name && strcmp(r->name, response); r++);
10022347Spst      i = r->type;
10122347Spst    }
10222347Spst  } else
10322347Spst    i = RESPONSE_STANDARD;
10422347Spst
10522347Spst  switch(i) {
10622347Spst  case RESPONSE_STANDARD:
10722347Spst    i = 1;
10822347Spst
10992906Smarkm    if (opieetob(&key, response) == 1) {
11092906Smarkm      memcpy(&fkey, &key, sizeof(struct opie_otpkey));
11192906Smarkm      opiehash(&fkey, MDX);
11292906Smarkm      i = memcmp(&fkey, &lastkey, sizeof(struct opie_otpkey));
11322347Spst    }
11492906Smarkm    if (i && opieatob8(&key, response)) {
11592906Smarkm      memcpy(&fkey, &key, sizeof(struct opie_otpkey));
11692906Smarkm      opiehash(&fkey, MDX);
11792906Smarkm      i = memcmp(&fkey, &lastkey, sizeof(struct opie_otpkey));
11822347Spst    }
11922347Spst    break;
12022347Spst  case RESPONSE_WORD:
12122347Spst    i = 1;
12222347Spst
12392906Smarkm    if (opieetob(&key, c) == 1) {
12492906Smarkm      memcpy(&fkey, &key, sizeof(struct opie_otpkey));
12592906Smarkm      opiehash(&fkey, MDX);
12692906Smarkm      i = memcmp(&fkey, &lastkey, sizeof(struct opie_otpkey));
12722347Spst    }
12822347Spst    break;
12922347Spst  case RESPONSE_HEX:
13022347Spst    i = 1;
13122347Spst
13292906Smarkm    if (opieatob8(&key, c)) {
13392906Smarkm      memcpy(&fkey, &key, sizeof(struct opie_otpkey));
13492906Smarkm      opiehash(&fkey, MDX);
13592906Smarkm      i = memcmp(&fkey, &lastkey, sizeof(struct opie_otpkey));
13622347Spst    }
13722347Spst    break;
13829964Sache  case RESPONSE_INIT_HEX:
13922347Spst  case RESPONSE_INIT_WORD:
14022347Spst    {
14122347Spst      char *c2;
14222347Spst
14322347Spst      if (!(c2 = strchr(c, ':')))
14422347Spst	goto verret;
14522347Spst
14622347Spst      *(c2++) = 0;
14722347Spst
14829964Sache      if (i == RESPONSE_INIT_HEX) {
14992906Smarkm	if (!opieatob8(&key, c))
15022347Spst	  goto verret;
15122347Spst      } else {
15292906Smarkm	if (opieetob(&key, c) != 1)
15322347Spst	  goto verret;
15422347Spst      }
15522347Spst
15692906Smarkm      memcpy(&fkey, &key, sizeof(struct opie_otpkey));
15792906Smarkm      opiehash(&fkey, MDX);
15822347Spst
15992906Smarkm      if (memcmp(&fkey, &lastkey, sizeof(struct opie_otpkey)))
16022347Spst	goto verret;
16122347Spst
16222347Spst      if (changed(opie))
16322347Spst	goto verret;
16422347Spst
16522347Spst      opie->opie_n--;
16622347Spst
16792906Smarkm      if (!opiebtoa8(opie->opie_val, &key))
16822347Spst	goto verret;
16922347Spst
17022347Spst      if (__opiewriterec(opie))
17122347Spst	goto verret;
17222347Spst
17322347Spst      if (!(c2 = strchr(c = c2, ':')))
17422347Spst	goto verret;
17522347Spst
17622347Spst      *(c2++) = 0;
17722347Spst
17822347Spst      {
17959118Skris	int j, k;
18022347Spst
18159118Skris	if (__opieparsechallenge(c, &j, &(opie->opie_n), &(opie->opie_seed), &k) || (j != MDX) || k)
18222347Spst	  goto verret;
18322347Spst      }
18422347Spst
18529964Sache      if (i == RESPONSE_INIT_HEX) {
18692906Smarkm	if (!opieatob8(&key, c2))
18722347Spst	  goto verret;
18822347Spst      } else {
18992906Smarkm	if (opieetob(&key, c2) != 1)
19022347Spst	  goto verret;
19122347Spst      }
19222347Spst    }
19322347Spst    goto verwrt;
19422347Spst  case RESPONSE_UNKNOWN:
19522347Spst    rval = 1;
19622347Spst    goto verret;
19722347Spst  default:
19822347Spst    rval = -1;
19922347Spst    goto verret;
20022347Spst  }
20122347Spst
20222347Spst  if (i) {
20322347Spst    rval = 1;
20422347Spst    goto verret;
20522347Spst  }
20622347Spst
20722347Spst  if (changed(opie))
20822347Spst    goto verret;
20922347Spst
21022347Spst  opie->opie_n--;
21122347Spst
21222347Spstverwrt:
21392906Smarkm  if (!opiebtoa8(opie->opie_val, &key))
21422347Spst    goto verret;
21522347Spst  rval = __opiewriterec(opie);
21622347Spst
21722347Spstverret:
21822347Spst  opieunlock();
21922347Spst  memset(opie, 0, sizeof(struct opie));
22022347Spst  return rval;
22122347Spst}
222