xref: /NextBSD/contrib/opie/libopie/verify.c (revision 5e568154a01fb6be74908baed265f265a56f002f)
1 /* verify.c: The opieverify() library function.
2 
3 %%% copyright-cmetz-96
4 This software is Copyright 1996-2001 by Craig Metz, All Rights Reserved.
5 The Inner Net License Version 3 applies to this software.
6 You should have received a copy of the license with this software. If
7 you 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 
37 struct _rtrans {
38   int type;
39   char *name;
40 };
41 
42 static 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 
51 static char *algids[] = { NULL, NULL, NULL, "sha1", "md4", "md5" };
52 
53 static 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 
69 int 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 
213 verwrt:
214   if (!opiebtoa8(opie->opie_val, &key))
215     goto verret;
216   rval = __opiewriterec(opie);
217 
218 verret:
219   opieunlock();
220   memset(opie, 0, sizeof(struct opie));
221   return rval;
222 }
223