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