rfc2617.c

Go to the documentation of this file.
00001 /*
00002  * $Id: rfc2617.c 2 2005-06-13 16:47:24Z bogdan_iancu $
00003  *
00004  * Copyright (C) 2001-2003 FhG Fokus
00005  *
00006  * This file is part of Kamailio, a free SIP server.
00007  *
00008  * Kamailio is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * Kamailio is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License 
00019  * along with this program; if not, write to the Free Software 
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  */
00022 
00023 /*!
00024  * \file
00025  * \brief Digest response calculation as per RFC2617
00026  * \ingroup auth
00027  * - Module: \ref auth
00028  */
00029 
00030 #include <sys/types.h>
00031 #include <stdlib.h>
00032 #include <string.h>
00033 
00034 #include "rfc2617.h"
00035 #include "../../md5.h"
00036 
00037 
00038 /*!
00039  * \brief Convert to hex form
00040  * \param _b hash value
00041  * \param _h hex value
00042  */
00043 inline void cvt_hex(HASH _b, HASHHEX _h)
00044 {
00045    unsigned short i;
00046    unsigned char j;
00047    
00048    for (i = 0; i < HASHLEN; i++) {
00049       j = (_b[i] >> 4) & 0xf;
00050       if (j <= 9) {
00051          _h[i * 2] = (j + '0');
00052       } else {
00053          _h[i * 2] = (j + 'a' - 10);
00054       }
00055 
00056       j = _b[i] & 0xf;
00057 
00058       if (j <= 9) {
00059          _h[i * 2 + 1] = (j + '0');
00060       } else {
00061          _h[i * 2 + 1] = (j + 'a' - 10);
00062       }
00063    };
00064 
00065    _h[HASHHEXLEN] = '\0';
00066 }
00067 
00068 
00069 /*!
00070  * \brief Calculate H(A1) as per HTTP Digest spec
00071  * \param _alg type of hash algorithm
00072  * \param _username username
00073  * \param _realm authentification realm
00074  * \param _password password
00075  * \param _nonce nonce value
00076  * \param _cnonce cnonce value
00077  * \param _sess_key session key, result will be stored there
00078  */
00079 void calc_HA1(ha_alg_t _alg, str* _username, str* _realm, str* _password,
00080          str* _nonce, str* _cnonce, HASHHEX _sess_key)
00081 {
00082    MD5_CTX Md5Ctx;
00083    HASH HA1;
00084    
00085    MD5Init(&Md5Ctx);
00086    MD5Update(&Md5Ctx, _username->s, _username->len);
00087    MD5Update(&Md5Ctx, ":", 1);
00088    MD5Update(&Md5Ctx, _realm->s, _realm->len);
00089    MD5Update(&Md5Ctx, ":", 1);
00090    MD5Update(&Md5Ctx, _password->s, _password->len);
00091    MD5Final(HA1, &Md5Ctx);
00092 
00093    if (_alg == HA_MD5_SESS) {
00094       MD5Init(&Md5Ctx);
00095       MD5Update(&Md5Ctx, HA1, HASHLEN);
00096       MD5Update(&Md5Ctx, ":", 1);
00097       MD5Update(&Md5Ctx, _nonce->s, _nonce->len);
00098       MD5Update(&Md5Ctx, ":", 1);
00099       MD5Update(&Md5Ctx, _cnonce->s, _cnonce->len);
00100       MD5Final(HA1, &Md5Ctx);
00101    };
00102 
00103    cvt_hex(HA1, _sess_key);
00104 }
00105 
00106 
00107 /*!
00108  * \brief Calculate request-digest/response-digest as per HTTP Digest spec
00109  * \param _ha1 H(A1)
00110  * \param _nonce nonce from server
00111  * \param _nc 8 hex digits
00112  * \param _cnonce cnonce value
00113  * \param _qop qop-value: "", "auth", "auth-int
00114  * \param _auth_int  1 if auth-int is used
00115  * \param _method method from the request
00116  * \param _uri requested URL/ URI
00117  * \param _hentity  H(entity body) if qop="auth-int"
00118  * \param _response request-digest or response-digest
00119  */
00120 void calc_response(HASHHEX _ha1,      /* H(A1) */
00121          str* _nonce,       /* nonce from server */
00122          str* _nc,          /* 8 hex digits */
00123          str* _cnonce,      /* client nonce */
00124          str* _qop,         /* qop-value: "", "auth", "auth-int" */
00125          int _auth_int,     /* 1 if auth-int is used */
00126          str* _method,      /* method from the request */
00127          str* _uri,         /* requested URL */
00128          HASHHEX _hentity,  /* H(entity body) if qop="auth-int" */
00129          HASHHEX _response) /* request-digest or response-digest */
00130 {
00131    MD5_CTX Md5Ctx;
00132    HASH HA2;
00133    HASH RespHash;
00134    HASHHEX HA2Hex;
00135    
00136    /* calculate H(A2) */
00137    MD5Init(&Md5Ctx);
00138    MD5Update(&Md5Ctx, _method->s, _method->len);
00139    MD5Update(&Md5Ctx, ":", 1);
00140    MD5Update(&Md5Ctx, _uri->s, _uri->len);
00141 
00142    if (_auth_int) {
00143       MD5Update(&Md5Ctx, ":", 1);
00144       MD5Update(&Md5Ctx, _hentity, HASHHEXLEN);
00145    };
00146 
00147    MD5Final(HA2, &Md5Ctx);
00148    cvt_hex(HA2, HA2Hex);
00149    
00150    /* calculate response */
00151    MD5Init(&Md5Ctx);
00152    MD5Update(&Md5Ctx, _ha1, HASHHEXLEN);
00153    MD5Update(&Md5Ctx, ":", 1);
00154    MD5Update(&Md5Ctx, _nonce->s, _nonce->len);
00155    MD5Update(&Md5Ctx, ":", 1);
00156 
00157    if (_qop->len) {
00158       MD5Update(&Md5Ctx, _nc->s, _nc->len);
00159       MD5Update(&Md5Ctx, ":", 1);
00160       MD5Update(&Md5Ctx, _cnonce->s, _cnonce->len);
00161       MD5Update(&Md5Ctx, ":", 1);
00162       MD5Update(&Md5Ctx, _qop->s, _qop->len);
00163       MD5Update(&Md5Ctx, ":", 1);
00164    };
00165    MD5Update(&Md5Ctx, HA2Hex, HASHHEXLEN);
00166    MD5Final(RespHash, &Md5Ctx);
00167    cvt_hex(RespHash, _response);
00168 }

Generated on Thu May 24 10:00:30 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6