verify.c revision 257264
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 <ctype.h>
28#include "opie.h"
29
30#define RESPONSE_STANDARD  0
31#define RESPONSE_WORD      1
32#define RESPONSE_HEX       2
33#define RESPONSE_INIT_HEX  3
34#define RESPONSE_INIT_WORD 4
35#define RESPONSE_UNKNOWN   5
36
37struct _rtrans {
38  int type;
39  char *name;
40};
41
42static struct _rtrans rtrans[] = {
43  { RESPONSE_WORD, "word" },
44  { RESPONSE_HEX, "hex" },
45  { RESPONSE_INIT_HEX, "init-hex" },
46  { RESPONSE_INIT_WORD, "init-word" },
47  { RESPONSE_STANDARD, "" },
48  { RESPONSE_UNKNOWN, NULL }
49};
50
51static char *algids[] = { NULL, NULL, NULL, "sha1", "md4", "md5" };
52
53static int changed FUNCTION((opie), struct opie *opie)
54{
55  struct opie opie2;
56
57  memset(&opie2, 0, sizeof(struct opie));
58  opie2.opie_principal = opie->opie_principal;
59  if (__opiereadrec(&opie2))
60    return 1;
61
62  if ((opie2.opie_n != opie->opie_n) || strcmp(opie2.opie_val, opie->opie_val) || strcmp(opie2.opie_seed, opie->opie_seed))
63    return 1;
64
65  memset(&opie2, 0, sizeof(struct opie));
66  return 0;
67}
68
69int opieverify FUNCTION((opie, response), struct opie *opie AND char *response)
70{
71  int i, rval = -1;
72  char *c;
73  struct opie_otpkey key, fkey, lastkey;
74  struct opie nopie;
75
76  if (!opie || !response)
77    goto verret;
78
79  if (!opie->opie_principal)
80#if DEBUG
81    abort();
82#else /* DEBUG */
83    goto verret;
84#endif /* DEBUG */
85
86  if (!opieatob8(&lastkey, opie->opie_val))
87    goto verret;
88
89  for (c = opie->opie_seed; *c; c++)
90    if (!isalnum(*c))
91      goto verret;
92
93  if (opie->opie_n <= 0)
94    goto verret;
95
96  if (c = strchr(response, ':')) {
97    *(c++) = 0;
98    {
99      struct _rtrans *r;
100      for (r = rtrans; r->name && strcmp(r->name, response); r++);
101      i = r->type;
102    }
103  } else
104    i = RESPONSE_STANDARD;
105
106  switch(i) {
107  case RESPONSE_STANDARD:
108    i = 1;
109
110    if (opieetob(&key, response) == 1) {
111      memcpy(&fkey, &key, sizeof(struct opie_otpkey));
112      opiehash(&fkey, MDX);
113      i = memcmp(&fkey, &lastkey, sizeof(struct opie_otpkey));
114    }
115    if (i && opieatob8(&key, response)) {
116      memcpy(&fkey, &key, sizeof(struct opie_otpkey));
117      opiehash(&fkey, MDX);
118      i = memcmp(&fkey, &lastkey, sizeof(struct opie_otpkey));
119    }
120    break;
121  case RESPONSE_WORD:
122    i = 1;
123
124    if (opieetob(&key, c) == 1) {
125      memcpy(&fkey, &key, sizeof(struct opie_otpkey));
126      opiehash(&fkey, MDX);
127      i = memcmp(&fkey, &lastkey, sizeof(struct opie_otpkey));
128    }
129    break;
130  case RESPONSE_HEX:
131    i = 1;
132
133    if (opieatob8(&key, c)) {
134      memcpy(&fkey, &key, sizeof(struct opie_otpkey));
135      opiehash(&fkey, MDX);
136      i = memcmp(&fkey, &lastkey, sizeof(struct opie_otpkey));
137    }
138    break;
139  case RESPONSE_INIT_HEX:
140  case RESPONSE_INIT_WORD:
141    {
142      char *c2;
143
144      if (!(c2 = strchr(c, ':')))
145	goto verret;
146
147      *(c2++) = 0;
148
149      if (i == RESPONSE_INIT_HEX) {
150	if (!opieatob8(&key, c))
151	  goto verret;
152      } else {
153	if (opieetob(&key, c) != 1)
154	  goto verret;
155      }
156
157      memcpy(&fkey, &key, sizeof(struct opie_otpkey));
158      opiehash(&fkey, MDX);
159
160      if (memcmp(&fkey, &lastkey, sizeof(struct opie_otpkey)))
161	goto verret;
162
163      if (changed(opie))
164	goto verret;
165
166      opie->opie_n--;
167
168      if (!opiebtoa8(opie->opie_val, &key))
169	goto verret;
170
171      if (__opiewriterec(opie))
172	goto verret;
173
174      if (!(c2 = strchr(c = c2, ':')))
175	goto verret;
176
177      *(c2++) = 0;
178
179      {
180	int j, k;
181
182	if (__opieparsechallenge(c, &j, &(opie->opie_n), &(opie->opie_seed), &k) || (j != MDX) || k)
183	  goto verret;
184      }
185
186      if (i == RESPONSE_INIT_HEX) {
187	if (!opieatob8(&key, c2))
188	  goto verret;
189      } else {
190	if (opieetob(&key, c2) != 1)
191	  goto verret;
192      }
193    }
194    goto verwrt;
195  case RESPONSE_UNKNOWN:
196    rval = 1;
197    goto verret;
198  default:
199    rval = -1;
200    goto verret;
201  }
202
203  if (i) {
204    rval = 1;
205    goto verret;
206  }
207
208  if (changed(opie))
209    goto verret;
210
211  opie->opie_n--;
212
213verwrt:
214  if (!opiebtoa8(opie->opie_val, &key))
215    goto verret;
216  rval = __opiewriterec(opie);
217
218verret:
219  opieunlock();
220  memset(opie, 0, sizeof(struct opie));
221  return rval;
222}
223