159138Smsmith/* verify.c: The opieverify() library function. 259138Smsmith 359138Smsmith%%% copyright-cmetz-96 459138SmsmithThis software is Copyright 1996-2001 by Craig Metz, All Rights Reserved. 559138SmsmithThe Inner Net License Version 3 applies to this software. 659138SmsmithYou should have received a copy of the license with this software. If 759138Smsmithyou didn't get a copy, you may request one from <license@inner.net>. 859138Smsmith 959138Smsmith History: 1059138Smsmith 1159138Smsmith Modified by cmetz for OPIE 2.4. Use struct opie_otpkey for keys. 1259138Smsmith Check that seed and sequence number are valid. 1359138Smsmith Modified by cmetz for OPIE 2.32. Renamed _opieparsechallenge() to 1459138Smsmith __opieparsechallenge() and handle new argument. Fixed init 1559138Smsmith response parsing bug. 1659138Smsmith Modified by cmetz for OPIE 2.31. Renamed "init" to "init-hex". 1759138Smsmith Modified by cmetz for OPIE 2.31. Renamed "init" and "RESPONSE_INIT" 1859138Smsmith to "init-hex" and "RESPONSE_INIT_HEX". Removed active attack 1959138Smsmith protection support. 2059138Smsmith Created by cmetz for OPIE 2.3 using the old verify.c as a guide. 2159138Smsmith*/ 2259138Smsmith 2359138Smsmith#include "opie_cfg.h" 2459138Smsmith#ifdef HAVE_STRING_H 2559138Smsmith#include <string.h> 2659138Smsmith#endif /* HAVE_STRING_H */ 2759138Smsmith#include "opie.h" 2859138Smsmith 2959138Smsmith#define RESPONSE_STANDARD 0 3059138Smsmith#define RESPONSE_WORD 1 3159138Smsmith#define RESPONSE_HEX 2 3259138Smsmith#define RESPONSE_INIT_HEX 3 3359138Smsmith#define RESPONSE_INIT_WORD 4 3459138Smsmith#define RESPONSE_UNKNOWN 5 3559138Smsmith 3659138Smsmithstruct _rtrans { 3759138Smsmith int type; 3859138Smsmith char *name; 3959138Smsmith}; 4059138Smsmith 4159138Smsmithstatic struct _rtrans rtrans[] = { 4259138Smsmith { RESPONSE_WORD, "word" }, 4359138Smsmith { RESPONSE_HEX, "hex" }, 4459138Smsmith { RESPONSE_INIT_HEX, "init-hex" }, 4559138Smsmith { RESPONSE_INIT_WORD, "init-word" }, 4659138Smsmith { RESPONSE_STANDARD, "" }, 4759138Smsmith { RESPONSE_UNKNOWN, NULL } 4859138Smsmith}; 4959138Smsmith 5059138Smsmithstatic char *algids[] = { NULL, NULL, NULL, "sha1", "md4", "md5" }; 5159138Smsmith 5259138Smsmithstatic int changed FUNCTION((opie), struct opie *opie) 5359138Smsmith{ 5459138Smsmith struct opie opie2; 5559138Smsmith 5659138Smsmith memset(&opie2, 0, sizeof(struct opie)); 5759138Smsmith opie2.opie_principal = opie->opie_principal; 5859138Smsmith if (__opiereadrec(&opie2)) 5959138Smsmith return 1; 6059138Smsmith 6159138Smsmith if ((opie2.opie_n != opie->opie_n) || strcmp(opie2.opie_val, opie->opie_val) || strcmp(opie2.opie_seed, opie->opie_seed)) 6259138Smsmith return 1; 6359138Smsmith 6459138Smsmith memset(&opie2, 0, sizeof(struct opie)); 6559138Smsmith return 0; 6659138Smsmith} 6759138Smsmith 6859138Smsmithint opieverify FUNCTION((opie, response), struct opie *opie AND char *response) 6959138Smsmith{ 7059138Smsmith int i, rval = -1; 7159138Smsmith char *c; 7259138Smsmith struct opie_otpkey key, fkey, lastkey; 7359138Smsmith struct opie nopie; 7459138Smsmith 7559138Smsmith if (!opie || !response) 7659138Smsmith goto verret; 7759138Smsmith 7859138Smsmith if (!opie->opie_principal) 7959138Smsmith#if DEBUG 8059138Smsmith abort(); 8159138Smsmith#else /* DEBUG */ 8259138Smsmith goto verret; 8359138Smsmith#endif /* DEBUG */ 8459138Smsmith 8559138Smsmith if (!opieatob8(&lastkey, opie->opie_val)) 8659138Smsmith goto verret; 8759138Smsmith 8859138Smsmith for (c = opie->opie_seed; *c; c++) 8959138Smsmith if (!isalnum(*c)) 9059138Smsmith goto verret; 9159138Smsmith 9259138Smsmith if (opie->opie_n <= 0) 9359138Smsmith goto verret; 9459138Smsmith 9559138Smsmith if (c = strchr(response, ':')) { 9659138Smsmith *(c++) = 0; 9759138Smsmith { 9859138Smsmith struct _rtrans *r; 9959138Smsmith for (r = rtrans; r->name && strcmp(r->name, response); r++); 10059138Smsmith i = r->type; 10159138Smsmith } 10259138Smsmith } else 10359138Smsmith i = RESPONSE_STANDARD; 10459138Smsmith 10559138Smsmith switch(i) { 10659138Smsmith case RESPONSE_STANDARD: 10759138Smsmith i = 1; 10859138Smsmith 10959138Smsmith if (opieetob(&key, response) == 1) { 11059138Smsmith memcpy(&fkey, &key, sizeof(struct opie_otpkey)); 11159138Smsmith opiehash(&fkey, MDX); 11259138Smsmith i = memcmp(&fkey, &lastkey, sizeof(struct opie_otpkey)); 11359138Smsmith } 11459138Smsmith if (i && opieatob8(&key, response)) { 11559138Smsmith memcpy(&fkey, &key, sizeof(struct opie_otpkey)); 11659138Smsmith opiehash(&fkey, MDX); 11759138Smsmith i = memcmp(&fkey, &lastkey, sizeof(struct opie_otpkey)); 11859138Smsmith } 11959138Smsmith break; 12059138Smsmith case RESPONSE_WORD: 12159138Smsmith i = 1; 12259138Smsmith 12359138Smsmith if (opieetob(&key, c) == 1) { 12459138Smsmith memcpy(&fkey, &key, sizeof(struct opie_otpkey)); 12559138Smsmith opiehash(&fkey, MDX); 12659138Smsmith i = memcmp(&fkey, &lastkey, sizeof(struct opie_otpkey)); 12759138Smsmith } 12859138Smsmith break; 12959138Smsmith case RESPONSE_HEX: 13059138Smsmith i = 1; 13159138Smsmith 13259138Smsmith if (opieatob8(&key, c)) { 13359138Smsmith memcpy(&fkey, &key, sizeof(struct opie_otpkey)); 13459138Smsmith opiehash(&fkey, MDX); 13559138Smsmith i = memcmp(&fkey, &lastkey, sizeof(struct opie_otpkey)); 13659138Smsmith } 13759138Smsmith break; 13859138Smsmith case RESPONSE_INIT_HEX: 13959138Smsmith case RESPONSE_INIT_WORD: 14059138Smsmith { 14159138Smsmith char *c2; 14259138Smsmith 14359138Smsmith if (!(c2 = strchr(c, ':'))) 14459138Smsmith goto verret; 14559138Smsmith 14659138Smsmith *(c2++) = 0; 14759138Smsmith 14859138Smsmith if (i == RESPONSE_INIT_HEX) { 14959138Smsmith if (!opieatob8(&key, c)) 15059138Smsmith goto verret; 15159138Smsmith } else { 15259138Smsmith if (opieetob(&key, c) != 1) 15359138Smsmith goto verret; 15459138Smsmith } 15559138Smsmith 15659138Smsmith memcpy(&fkey, &key, sizeof(struct opie_otpkey)); 15759138Smsmith opiehash(&fkey, MDX); 15859138Smsmith 15959138Smsmith if (memcmp(&fkey, &lastkey, sizeof(struct opie_otpkey))) 16059138Smsmith goto verret; 16159138Smsmith 16259138Smsmith if (changed(opie)) 16359138Smsmith goto verret; 16459138Smsmith 16559138Smsmith opie->opie_n--; 16659138Smsmith 16759138Smsmith if (!opiebtoa8(opie->opie_val, &key)) 16859138Smsmith goto verret; 16959138Smsmith 17059138Smsmith if (__opiewriterec(opie)) 17159138Smsmith goto verret; 17259138Smsmith 17359138Smsmith if (!(c2 = strchr(c = c2, ':'))) 17459138Smsmith goto verret; 17559138Smsmith 17659138Smsmith *(c2++) = 0; 17759138Smsmith 17859138Smsmith { 17959138Smsmith int j, k; 18059138Smsmith 18159138Smsmith if (__opieparsechallenge(c, &j, &(opie->opie_n), &(opie->opie_seed), &k) || (j != MDX) || k) 18259138Smsmith goto verret; 18359138Smsmith } 18459138Smsmith 18559138Smsmith if (i == RESPONSE_INIT_HEX) { 18659138Smsmith if (!opieatob8(&key, c2)) 18759138Smsmith goto verret; 18859138Smsmith } else { 18959138Smsmith if (opieetob(&key, c2) != 1) 19059138Smsmith goto verret; 19159138Smsmith } 19259138Smsmith } 19359138Smsmith goto verwrt; 19459138Smsmith case RESPONSE_UNKNOWN: 19559138Smsmith rval = 1; 19659138Smsmith goto verret; 19759138Smsmith default: 19859138Smsmith rval = -1; 19959138Smsmith goto verret; 20059138Smsmith } 20159138Smsmith 20259138Smsmith if (i) { 20359138Smsmith rval = 1; 20459138Smsmith goto verret; 20559138Smsmith } 20659138Smsmith 20759138Smsmith if (changed(opie)) 20859138Smsmith goto verret; 20959138Smsmith 21059138Smsmith opie->opie_n--; 21159138Smsmith 21259138Smsmithverwrt: 21359138Smsmith if (!opiebtoa8(opie->opie_val, &key)) 21459138Smsmith goto verret; 21559138Smsmith rval = __opiewriterec(opie); 21659138Smsmith 21759138Smsmithverret: 21859138Smsmith opieunlock(); 21959138Smsmith memset(opie, 0, sizeof(struct opie)); 22059138Smsmith return rval; 22159138Smsmith} 22259138Smsmith