00001 /* validate.c --- Validate consistency of DIGEST-MD5 tokens. 00002 * Copyright (C) 2004, 2006 Simon Josefsson 00003 * 00004 * This file is part of GNU SASL Library. 00005 * 00006 * GNU SASL Library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public License 00008 * as published by the Free Software Foundation; either version 2.1 of 00009 * the License, or (at your option) any later version. 00010 * 00011 * GNU SASL Library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with GNU SASL Library; if not, write to the Free 00018 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00019 * Boston, MA 02110-1301, USA. 00020 * 00021 */ 00022 00023 #if HAVE_CONFIG_H 00024 # include "config.h" 00025 #endif 00026 00027 /* Get prototypes. */ 00028 #include "validate.h" 00029 00030 /* Get strcmp, strlen. */ 00031 #include <string.h> 00032 00033 int 00034 digest_md5_validate_challenge (digest_md5_challenge * c) 00035 { 00036 /* This directive is required and MUST appear exactly once; if 00037 not present, or if multiple instances are present, the 00038 client should abort the authentication exchange. */ 00039 if (!c->nonce) 00040 return -1; 00041 00042 /* This directive must be present exactly once if "auth-conf" is 00043 offered in the "qop-options" directive */ 00044 if (c->ciphers && !(c->qops & DIGEST_MD5_QOP_AUTH_CONF)) 00045 return -1; 00046 if (!c->ciphers && (c->qops & DIGEST_MD5_QOP_AUTH_CONF)) 00047 return -1; 00048 00049 return 0; 00050 } 00051 00052 int 00053 digest_md5_validate_response (digest_md5_response * r) 00054 { 00055 /* This directive is required and MUST be present exactly 00056 once; otherwise, authentication fails. */ 00057 if (!r->username) 00058 return -1; 00059 00060 /* This directive is required and MUST be present exactly 00061 once; otherwise, authentication fails. */ 00062 if (!r->nonce) 00063 return -1; 00064 00065 /* This directive is required and MUST be present exactly once; 00066 otherwise, authentication fails. */ 00067 if (!r->cnonce) 00068 return -1; 00069 00070 /* This directive is required and MUST be present exactly once; 00071 otherwise, or if the value is 0, authentication fails. */ 00072 if (!r->nc) 00073 return -1; 00074 00075 /* This directive is required and MUST be present exactly 00076 once; if multiple instances are present, the client MUST 00077 abort the authentication exchange. */ 00078 if (!r->digesturi) 00079 return -1; 00080 00081 /* This directive is required and MUST be present exactly 00082 once; otherwise, authentication fails. */ 00083 if (!*r->response) 00084 return -1; 00085 00086 if (strlen (r->response) != DIGEST_MD5_RESPONSE_LENGTH) 00087 return -1; 00088 00089 /* This directive MUST appear exactly once if "auth-conf" is 00090 negotiated; if required and not present, authentication fails. 00091 If the client recognizes no cipher and the server only advertised 00092 "auth-conf" in the qop option, the client MUST abort the 00093 authentication exchange. */ 00094 if (r->qop == DIGEST_MD5_QOP_AUTH_CONF && !r->cipher) 00095 return -1; 00096 if (r->qop != DIGEST_MD5_QOP_AUTH_CONF && r->cipher) 00097 return -1; 00098 00099 return 0; 00100 } 00101 00102 int 00103 digest_md5_validate_finish (digest_md5_finish * f) 00104 { 00105 if (!f->rspauth) 00106 return -1; 00107 00108 /* A string of 32 hex digits */ 00109 if (strlen (f->rspauth) != DIGEST_MD5_RESPONSE_LENGTH) 00110 return -1; 00111 00112 return 0; 00113 } 00114 00115 int 00116 digest_md5_validate (digest_md5_challenge * c, digest_md5_response * r) 00117 { 00118 if (!c->nonce || !r->nonce) 00119 return -1; 00120 00121 if (strcmp (c->nonce, r->nonce) != 0) 00122 return -1; 00123 00124 if (r->nc != 1) 00125 return -1; 00126 00127 if (c->utf8 != r->utf8) 00128 return -1; 00129 00130 if (!((c->qops ? c->qops : DIGEST_MD5_QOP_AUTH) & 00131 (r->qop ? r->qop : DIGEST_MD5_QOP_AUTH))) 00132 return -1; 00133 00134 if ((r->qop & DIGEST_MD5_QOP_AUTH_CONF) && !(c->ciphers & r->cipher)) 00135 return -1; 00136 00137 /* FIXME: Check more? */ 00138 00139 return 0; 00140 }