nonce.c

Go to the documentation of this file.
00001 /*
00002  * $Id: nonce.c 5299 2008-12-04 18:12:33Z henningw $
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 Nonce related functions
00026  * \ingroup auth
00027  * - Module: \ref auth
00028  */
00029 
00030 #include <time.h>
00031 #include <string.h>
00032 #include <sys/types.h>
00033 #include <netinet/in.h>
00034 #include "../../md5.h"
00035 #include "../../dprint.h"
00036 #include "../../ut.h"
00037 #include "../../timer.h"
00038 #include "nonce.h"
00039 #include "index.h"
00040 #include "auth_mod.h"
00041 
00042 
00043 /*!
00044  * Convert an integer to its hex representation,
00045  * destination array must be at least 8 bytes long,
00046  * this string is NOT zero terminated
00047  */
00048 static inline void integer2hex(char* _d, int _s)
00049 {
00050    int i;
00051    unsigned char j;
00052    char* s;
00053 
00054    _s = htonl(_s);
00055    s = (char*)&_s;
00056 
00057    for (i = 0; i < 4; i++) {
00058       
00059       j = (s[i] >> 4) & 0xf;
00060       if (j <= 9) {
00061          _d[i * 2] = (j + '0');
00062       } else { 
00063          _d[i * 2] = (j + 'a' - 10);
00064       }
00065 
00066       j = s[i] & 0xf;
00067       if (j <= 9) {
00068          _d[i * 2 + 1] = (j + '0');
00069       } else {
00070              _d[i * 2 + 1] = (j + 'a' - 10);
00071       }
00072    }
00073 }
00074 
00075 
00076 /*!
00077  * \brief Convert hex string to integer
00078  * \param _s hex string
00079  * \return integer value, can be 0
00080  */
00081 static inline int hex2integer(char* _s)
00082 {
00083    unsigned int i, res = 0;
00084 
00085    for(i = 0; i < 8; i++) {
00086       res *= 16;
00087       if ((_s[i] >= '0') && (_s[i] <= '9')) {
00088          res += _s[i] - '0';
00089       } else if ((_s[i] >= 'a') && (_s[i] <= 'f')) {
00090          res += _s[i] - 'a' + 10;
00091       } else if ((_s[i] >= 'A') && (_s[i] <= 'F')) {
00092          res += _s[i] - 'A' + 10;
00093       } else return 0;
00094    }
00095 
00096    return res;
00097 }
00098 
00099 
00100 /*!
00101  * \brief Calculate nonce value
00102  *
00103  * Calculate nonce value value. The nonce value consists of the
00104  * expires time (in seconds since 1.1 1970) and a secret phrase.
00105  * \param _nonce nonce value
00106  * \param _expires expires value
00107  * \param _index nonce index
00108  * \param _secret secret
00109  */
00110 void calc_nonce(char* _nonce, int _expires, int _index, str* _secret)
00111 {
00112    MD5_CTX ctx;
00113    unsigned char bin[16];
00114    unsigned int offset = 8;
00115 
00116    MD5Init(&ctx);
00117    
00118 
00119    integer2hex(_nonce, _expires);
00120 
00121    if(nonce_reuse==0)
00122    {
00123        integer2hex(_nonce + 8, _index);
00124       offset = 16;
00125    }
00126    MD5Update(&ctx, _nonce, offset);
00127 
00128    MD5Update(&ctx, _secret->s, _secret->len);
00129    U_MD5Final(bin, &ctx);
00130    string2hex(bin, 16, _nonce + offset);
00131    _nonce[offset + 32] = '\0';
00132 }
00133 
00134 
00135 /*!
00136  * \brief Get index from nonce string
00137  * \param _n nonce string
00138  * \return nonce index
00139  */
00140 int get_nonce_index(str* _n)
00141 {
00142     return hex2integer(_n->s + 8);
00143 }
00144 
00145 
00146 /*!
00147  * \brief Get expiry time from nonce string
00148  * \param _n nonce string
00149  * \return expiry time
00150  */
00151 static inline time_t get_nonce_expires(str* _n)
00152 {
00153    return (time_t)hex2integer(_n->s);
00154 }
00155 
00156 
00157 /*!
00158  * \brief Check nonce value received from user agent
00159  * \param _nonce nonce value
00160  * \param _secret secret phrase
00161  * \return 0 when nonce is valid, -1 on errors, positive if nonce not valid
00162  */
00163 int check_nonce(str* _nonce, str* _secret)
00164 {
00165    int expires;
00166    char non[NONCE_LEN + 1];
00167     int index = 0;
00168 
00169    if (_nonce->s == 0) {
00170       return -1;  /* Invalid nonce */
00171    }
00172 
00173    if (NONCE_LEN != ((nonce_reuse==0)?_nonce->len:_nonce->len+8)) {
00174       return 1; /* Lengths must be equal */
00175    }
00176 
00177    expires = get_nonce_expires(_nonce);
00178    if(nonce_reuse==0)
00179        index = get_nonce_index(_nonce);
00180 
00181     calc_nonce(non, expires, index, _secret);
00182 
00183    
00184    LM_DBG("comparing [%.*s] and [%.*s]\n",
00185          _nonce->len, ZSW(_nonce->s),
00186          ((nonce_reuse==0)?NONCE_LEN:NONCE_LEN-8), non);
00187     if (!memcmp(non, _nonce->s, _nonce->len)) {
00188       return 0;
00189    }
00190    return 2;
00191 }
00192 
00193 
00194 /*!
00195  * \brief Check if a nonce is stale
00196  * \param _n nonce string
00197  * \return 1 if the nonce is stale, 0 otherwise
00198  */
00199 int is_nonce_stale(str* _n) 
00200 {
00201    if (!_n->s) return 0;
00202 
00203    if (get_nonce_expires(_n) < time(0)) {
00204       return 1;
00205    } else {
00206       return 0;
00207    }
00208 }

Generated on Wed May 23 20:00:28 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6