verify.c revision 22347
1/* verify.c: The opieverify() library function.
2
3%%% copyright-cmetz
4This software is Copyright 1996 by Craig Metz, All Rights Reserved.
5The Inner Net License Version 2 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	Created by cmetz for OPIE 2.3 using the old verify.c as a guide.
12*/
13
14#include "opie_cfg.h"
15#ifdef HAVE_STRING_H
16#include <string.h>
17#endif /* HAVE_STRING_H */
18#include "opie.h"
19
20#define RESPONSE_STANDARD  0
21#define RESPONSE_WORD      1
22#define RESPONSE_HEX       2
23#define RESPONSE_INIT      3
24#define RESPONSE_INIT_WORD 4
25#define RESPONSE_UNKNOWN   5
26
27struct _rtrans {
28  int type;
29  char *name;
30};
31
32static struct _rtrans rtrans[] = {
33  { RESPONSE_WORD, "word" },
34  { RESPONSE_HEX, "hex" },
35  { RESPONSE_INIT, "init" },
36  { RESPONSE_INIT_WORD, "init-word" },
37  { RESPONSE_STANDARD, "" },
38  { RESPONSE_UNKNOWN, NULL }
39};
40
41static char *algids[] = { NULL, NULL, NULL, "sha1", "md4", "md5" };
42
43static int changed FUNCTION((opie), struct opie *opie)
44{
45  struct opie opie2;
46
47  memset(&opie2, 0, sizeof(struct opie));
48  opie2.opie_principal = opie->opie_principal;
49  if (__opiereadrec(&opie2))
50    return 1;
51
52  if ((opie2.opie_n != opie->opie_n) || strcmp(opie2.opie_val, opie->opie_val) || strcmp(opie2.opie_seed, opie->opie_seed))
53    return 1;
54
55  memset(&opie2, 0, sizeof(struct opie));
56  return 0;
57}
58
59int opieverify FUNCTION((opie, response), struct opie *opie AND char *response)
60{
61  int i, rval = -1;
62  char *c;
63  char key[8], fkey[8], lastkey[8];
64  struct opie nopie;
65
66  if (!opie || !response)
67    goto verret;
68
69  if (!opie->opie_principal)
70#if DEBUG
71    abort();
72#else /* DEBUG */
73    goto verret;
74#endif /* DEBUG */
75
76  if (!opieatob8(lastkey, opie->opie_val))
77    goto verret;
78
79  if (c = strchr(response, ':')) {
80    *(c++) = 0;
81    {
82      struct _rtrans *r;
83      for (r = rtrans; r->name && strcmp(r->name, response); r++);
84      i = r->type;
85    }
86  } else
87    i = RESPONSE_STANDARD;
88
89  switch(i) {
90  case RESPONSE_STANDARD:
91    i = 1;
92
93    if (opieetob(key, response) == 1) {
94      memcpy(fkey, key, sizeof(key));
95      opiehash(fkey, MDX);
96      i = memcmp(fkey, lastkey, sizeof(key));
97    }
98    if (i && opieatob8(key, response)) {
99      memcpy(fkey, key, sizeof(key));
100      opiehash(fkey, MDX);
101      i = memcmp(fkey, lastkey, sizeof(key));
102    }
103    break;
104  case RESPONSE_WORD:
105    i = 1;
106
107    if (opieetob(key, c) == 1) {
108      memcpy(fkey, key, sizeof(key));
109      opiehash(fkey, MDX);
110      i = memcmp(fkey, lastkey, sizeof(key));
111    }
112    break;
113  case RESPONSE_HEX:
114    i = 1;
115
116    if (opieatob8(key, c)) {
117      memcpy(fkey, key, sizeof(key));
118      opiehash(fkey, MDX);
119      i = memcmp(fkey, lastkey, sizeof(key));
120    }
121    break;
122  case RESPONSE_INIT:
123  case RESPONSE_INIT_WORD:
124    {
125      char *c2;
126      char newkey[8], ckxor[8], ck[8], cv[8], cvc[8];
127      char buf[OPIE_SEED_MAX + 48 + 1];
128
129      if (!(c2 = strchr(c, ':')))
130	goto verret;
131
132      *(c2++) = 0;
133
134      if (i == RESPONSE_INIT) {
135	if (!opieatob8(key, c))
136	  goto verret;
137      } else {
138	if (opieetob(key, c) != 1)
139	  goto verret;
140      }
141
142      memcpy(fkey, key, sizeof(key));
143      opiehash(fkey, MDX);
144
145      if (memcmp(fkey, lastkey, sizeof(key)))
146	goto verret;
147
148      if (changed(opie))
149	goto verret;
150
151      opie->opie_n--;
152
153      if (!opiebtoa8(opie->opie_val, key))
154	goto verret;
155
156      if (__opiewriterec(opie))
157	goto verret;
158
159      if (!(c2 = strchr(c = c2, ':')))
160	goto verret;
161
162      *(c2++) = 0;
163
164      {
165	int j;
166
167	if (_opieparsechallenge(c, &j, &(opie->opie_n), &(opie->opie_seed)) || (j != MDX))
168	  goto verret;
169      }
170
171      if (!(c2 = strchr(c = c2, ':')))
172	goto verret;
173
174      *(c2++) = 0;
175
176      if (i == RESPONSE_INIT) {
177	if (!opieatob8(newkey, c))
178	  goto verret;
179      } else {
180	if (opieetob(newkey, c) != 1)
181	  goto verret;
182      }
183
184      if (!opie->opie_reinitkey || (opie->opie_reinitkey[0] == '*'))
185	goto verwrt;
186
187      if (!(c2 = strchr(c = c2, ':')))
188	goto verret;
189
190      *(c2++) = 0;
191
192      if (i == RESPONSE_INIT) {
193	if (!opieatob8(ckxor, c))
194	  goto verret;
195	if (!opieatob8(cv, c2))
196	  goto verret;
197      } else {
198	if (opieetob(ckxor, c) != 1)
199	  goto verret;
200	if (opieetob(cv, c2) != 1)
201	  goto verret;
202      }
203
204      if (!opieatob8(ck, opie->opie_reinitkey))
205	goto verret;
206
207      c = buf;
208      memcpy(c, ck, sizeof(ck)); c += sizeof(ck);
209      memcpy(c, key, sizeof(key)); c += sizeof(key);
210      c += sprintf(c, "%s 499 %s", algids[MDX], opie->opie_seed);
211      memcpy(c, newkey, sizeof(newkey)); c += sizeof(newkey);
212      memcpy(c, ckxor, sizeof(ckxor)); c += sizeof(ckxor);
213      memcpy(c, ck, sizeof(ck)); c += sizeof(ck);
214      opiehashlen(MDX, buf, cvc, (unsigned int)c - (unsigned int)buf);
215
216      if (memcmp(cv, cvc, sizeof(cv)))
217	goto verret;
218
219      for (i = 0; i < 8; i++)
220	ck[i] ^= ckxor[i];
221
222      if (!opiebtoa8(opie->opie_reinitkey, ck))
223	goto verret;
224
225      memcpy(key, newkey, sizeof(key));
226    }
227    goto verwrt;
228  case RESPONSE_UNKNOWN:
229    rval = 1;
230    goto verret;
231  default:
232    rval = -1;
233    goto verret;
234  }
235
236  if (i) {
237    rval = 1;
238    goto verret;
239  }
240
241  if (changed(opie))
242    goto verret;
243
244  opie->opie_n--;
245
246verwrt:
247  if (!opiebtoa8(opie->opie_val, key))
248    goto verret;
249  rval = __opiewriterec(opie);
250
251verret:
252  opieunlock();
253  memset(opie, 0, sizeof(struct opie));
254  return rval;
255}
256