1/* verify.c: The opieverify() library function.
2
3%%% copyright-cmetz-96
4This software is Copyright 1996-2001 by Craig Metz, All Rights Reserved.
5The Inner Net License Version 3 applies to this software.
6You should have received a copy of the license with this software. If
7you didn't get a copy, you may request one from <license@inner.net>.
8
9	History:
10
11	Modified by cmetz for OPIE 2.4. Use struct opie_otpkey for keys.
12		Check that seed and sequence number are valid.
13	Modified by cmetz for OPIE 2.32. Renamed _opieparsechallenge() to
14		__opieparsechallenge() and handle new argument. Fixed init
15		response parsing bug.
16	Modified by cmetz for OPIE 2.31. Renamed "init" to "init-hex".
17	Modified by cmetz for OPIE 2.31. Renamed "init" and "RESPONSE_INIT"
18		to "init-hex" and "RESPONSE_INIT_HEX". Removed active attack
19		protection support.
20	Created by cmetz for OPIE 2.3 using the old verify.c as a guide.
21*/
22
23#include "opie_cfg.h"
24#ifdef HAVE_STRING_H
25#include <string.h>
26#endif /* HAVE_STRING_H */
27#include "opie.h"
28
29#define RESPONSE_STANDARD  0
30#define RESPONSE_WORD      1
31#define RESPONSE_HEX       2
32#define RESPONSE_INIT_HEX  3
33#define RESPONSE_INIT_WORD 4
34#define RESPONSE_UNKNOWN   5
35
36struct _rtrans {
37  int type;
38  char *name;
39};
40
41static struct _rtrans rtrans[] = {
42  { RESPONSE_WORD, "word" },
43  { RESPONSE_HEX, "hex" },
44  { RESPONSE_INIT_HEX, "init-hex" },
45  { RESPONSE_INIT_WORD, "init-word" },
46  { RESPONSE_STANDARD, "" },
47  { RESPONSE_UNKNOWN, NULL }
48};
49
50static char *algids[] = { NULL, NULL, NULL, "sha1", "md4", "md5" };
51
52static int changed FUNCTION((opie), struct opie *opie)
53{
54  struct opie opie2;
55
56  memset(&opie2, 0, sizeof(struct opie));
57  opie2.opie_principal = opie->opie_principal;
58  if (__opiereadrec(&opie2))
59    return 1;
60
61  if ((opie2.opie_n != opie->opie_n) || strcmp(opie2.opie_val, opie->opie_val) || strcmp(opie2.opie_seed, opie->opie_seed))
62    return 1;
63
64  memset(&opie2, 0, sizeof(struct opie));
65  return 0;
66}
67
68int opieverify FUNCTION((opie, response), struct opie *opie AND char *response)
69{
70  int i, rval = -1;
71  char *c;
72  struct opie_otpkey key, fkey, lastkey;
73  struct opie nopie;
74
75  if (!opie || !response)
76    goto verret;
77
78  if (!opie->opie_principal)
79#if DEBUG
80    abort();
81#else /* DEBUG */
82    goto verret;
83#endif /* DEBUG */
84
85  if (!opieatob8(&lastkey, opie->opie_val))
86    goto verret;
87
88  for (c = opie->opie_seed; *c; c++)
89    if (!isalnum(*c))
90      goto verret;
91
92  if (opie->opie_n <= 0)
93    goto verret;
94
95  if (c = strchr(response, ':')) {
96    *(c++) = 0;
97    {
98      struct _rtrans *r;
99      for (r = rtrans; r->name && strcmp(r->name, response); r++);
100      i = r->type;
101    }
102  } else
103    i = RESPONSE_STANDARD;
104
105  switch(i) {
106  case RESPONSE_STANDARD:
107    i = 1;
108
109    if (opieetob(&key, response) == 1) {
110      memcpy(&fkey, &key, sizeof(struct opie_otpkey));
111      opiehash(&fkey, MDX);
112      i = memcmp(&fkey, &lastkey, sizeof(struct opie_otpkey));
113    }
114    if (i && opieatob8(&key, response)) {
115      memcpy(&fkey, &key, sizeof(struct opie_otpkey));
116      opiehash(&fkey, MDX);
117      i = memcmp(&fkey, &lastkey, sizeof(struct opie_otpkey));
118    }
119    break;
120  case RESPONSE_WORD:
121    i = 1;
122
123    if (opieetob(&key, c) == 1) {
124      memcpy(&fkey, &key, sizeof(struct opie_otpkey));
125      opiehash(&fkey, MDX);
126      i = memcmp(&fkey, &lastkey, sizeof(struct opie_otpkey));
127    }
128    break;
129  case RESPONSE_HEX:
130    i = 1;
131
132    if (opieatob8(&key, c)) {
133      memcpy(&fkey, &key, sizeof(struct opie_otpkey));
134      opiehash(&fkey, MDX);
135      i = memcmp(&fkey, &lastkey, sizeof(struct opie_otpkey));
136    }
137    break;
138  case RESPONSE_INIT_HEX:
139  case RESPONSE_INIT_WORD:
140    {
141      char *c2;
142
143      if (!(c2 = strchr(c, ':')))
144	goto verret;
145
146      *(c2++) = 0;
147
148      if (i == RESPONSE_INIT_HEX) {
149	if (!opieatob8(&key, c))
150	  goto verret;
151      } else {
152	if (opieetob(&key, c) != 1)
153	  goto verret;
154      }
155
156      memcpy(&fkey, &key, sizeof(struct opie_otpkey));
157      opiehash(&fkey, MDX);
158
159      if (memcmp(&fkey, &lastkey, sizeof(struct opie_otpkey)))
160	goto verret;
161
162      if (changed(opie))
163	goto verret;
164
165      opie->opie_n--;
166
167      if (!opiebtoa8(opie->opie_val, &key))
168	goto verret;
169
170      if (__opiewriterec(opie))
171	goto verret;
172
173      if (!(c2 = strchr(c = c2, ':')))
174	goto verret;
175
176      *(c2++) = 0;
177
178      {
179	int j, k;
180
181	if (__opieparsechallenge(c, &j, &(opie->opie_n), &(opie->opie_seed), &k) || (j != MDX) || k)
182	  goto verret;
183      }
184
185      if (i == RESPONSE_INIT_HEX) {
186	if (!opieatob8(&key, c2))
187	  goto verret;
188      } else {
189	if (opieetob(&key, c2) != 1)
190	  goto verret;
191      }
192    }
193    goto verwrt;
194  case RESPONSE_UNKNOWN:
195    rval = 1;
196    goto verret;
197  default:
198    rval = -1;
199    goto verret;
200  }
201
202  if (i) {
203    rval = 1;
204    goto verret;
205  }
206
207  if (changed(opie))
208    goto verret;
209
210  opie->opie_n--;
211
212verwrt:
213  if (!opiebtoa8(opie->opie_val, &key))
214    goto verret;
215  rval = __opiewriterec(opie);
216
217verret:
218  opieunlock();
219  memset(opie, 0, sizeof(struct opie));
220  return rval;
221}
222