reSIProcate/rutil  9694
RADIUSDigestAuthenticator.cxx
Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include "config.h"
00003 #endif
00004 
00005 #ifdef USE_RADIUS_CLIENT
00006 
00007 #include "Logger.hxx"
00008 #include "RADIUSDigestAuthenticator.hxx"
00009 
00010 
00011 using namespace resip;
00012 using namespace std;
00013 
00014 #define RESIPROCATE_SUBSYSTEM Subsystem::SIP
00015 
00016 struct attr *RADIUSDigestAuthenticator::attrs = NULL;
00017 struct val *RADIUSDigestAuthenticator::vals = NULL;
00018 rc_handle *RADIUSDigestAuthenticator::rh = NULL;
00019 
00020 inline void init_av(rc_handle *rh, struct attr *at, struct val *vl, char *fn)
00021 {
00022    int i;
00023    DICT_ATTR *da;
00024    DICT_VALUE *dv;
00025 
00026    for (i = 0; i < A_MAX; i++)
00027    {
00028       if (at[i].n == NULL)
00029       continue;
00030       da = rc_dict_findattr(rh, at[i].n);
00031       if (da == NULL)
00032       {
00033          ErrLog( <<"ERROR: " << Data(fn) << ": can't get code for the " << Data(at[i].n) << " attribute\n");
00034          throw;
00035       }
00036       at[i].v = da->value;
00037    }
00038    for (i = 0; i < V_MAX; i++)
00039    {
00040       if (vl[i].n == NULL)
00041       continue;
00042       dv = rc_dict_findval(rh, vl[i].n);
00043       if (dv == NULL)
00044       {
00045          ErrLog( <<"ERROR: " << fn << ": can't get code for the " << vl[i].n << " attribute value\n");
00046          throw;
00047       }
00048       vl[i].v = dv->value;
00049    }
00050 }
00051 
00052 RADIUSDigestAuthListener::~RADIUSDigestAuthListener() {
00053 }
00054 
00055 
00056 void RADIUSDigestAuthenticator::init(const char *radiusConfigFile)
00057 {
00058    if(attrs != NULL)
00059       throw; // may only be called once
00060 
00061    if((attrs = (struct attr *)malloc(sizeof(struct attr) * A_MAX)) == NULL)
00062    {
00063       ErrLog( <<"malloc failed");
00064       throw;
00065    }
00066    if((vals = (struct val *)malloc(sizeof(struct val) * V_MAX)) == NULL)
00067    {
00068       ErrLog(<< "malloc failed");
00069       throw;
00070    }
00071 
00072    memset(attrs, 0, sizeof(struct attr) * A_MAX);
00073    memset(vals, 0, sizeof(struct val) * V_MAX);
00074    attrs[A_SERVICE_TYPE].n = "Service-Type";
00075    attrs[A_SIP_RPID].n = "Sip-RPId";
00076    attrs[A_SIP_URI_USER].n = "Sip-URI-User";
00077    attrs[A_DIGEST_RESPONSE].n = "Digest-Response";
00078    attrs[A_DIGEST_ALGORITHM].n = "Digest-Algorithm";
00079    attrs[A_DIGEST_BODY_DIGEST].n = "Digest-Body-Digest";
00080    attrs[A_DIGEST_CNONCE].n = "Digest-CNonce";
00081    attrs[A_DIGEST_NONCE_COUNT].n = "Digest-Nonce-Count";
00082    attrs[A_DIGEST_QOP].n = "Digest-QOP";
00083    attrs[A_DIGEST_METHOD].n = "Digest-Method";
00084    attrs[A_DIGEST_URI].n = "Digest-URI";
00085    attrs[A_DIGEST_NONCE].n = "Digest-Nonce";
00086    attrs[A_DIGEST_REALM].n = "Digest-Realm";
00087    attrs[A_DIGEST_USER_NAME].n = "Digest-User-Name";
00088    attrs[A_USER_NAME].n = "User-Name";
00089    attrs[A_CISCO_AVPAIR].n = NULL;
00090    //attrs[A_CISCO_AVPAIR].n                 = "Cisco-AVPair";
00091    vals[V_SIP_SESSION].n = "Sip-Session";
00092 
00093    const char *myRADIUSConfigFile = RADIUS_CONFIG;
00094    if(radiusConfigFile != NULL)
00095    myRADIUSConfigFile = radiusConfigFile;
00096    if((rh = rc_read_config((char *)myRADIUSConfigFile)) == NULL)
00097    {
00098       ErrLog(<< "radius: Error opening configuration file \n");
00099       throw;
00100    }
00101 
00102    if (rc_read_dictionary(rh, rc_conf_str(rh, "dictionary")) != 0)
00103    {
00104       ErrLog(<< "radius: Error opening dictionary file \n");
00105       throw;
00106    }
00107 
00108    init_av(rh, attrs, vals, "radius");
00109 
00110 }
00111 
00112 RADIUSDigestAuthenticator::RADIUSDigestAuthenticator(
00113    const resip::Data& username,
00114    const resip::Data& digestUsername,
00115    const resip::Data& digestRealm,
00116    const resip::Data& digestNonce,
00117    const resip::Data& digestUri, const resip::Data& digestMethod,
00118    const resip::Data& digestResponse, RADIUSDigestAuthListener *listener) :
00119    username(username),
00120    digestUsername(digestUsername),
00121    digestRealm(digestRealm),
00122    digestNonce(digestNonce),
00123    digestUri(digestUri),
00124    digestMethod(digestMethod),
00125    digestQop(""),
00126    digestNonceCount(""),
00127    digestCNonce(""),
00128    digestBodyDigest(""),
00129    digestResponse(digestResponse),
00130    listener(listener)
00131 {
00132 }
00133 
00134 // QoP auth
00135 RADIUSDigestAuthenticator::RADIUSDigestAuthenticator(
00136    const resip::Data& username,
00137    const resip::Data& digestUsername,
00138    const resip::Data& digestRealm,
00139    const resip::Data& digestNonce,
00140    const resip::Data& digestUri,
00141    const resip::Data& digestMethod,
00142    const resip::Data& digestQop,
00143    const resip::Data& digestNonceCount,
00144    const resip::Data& digestCNonce,
00145    const resip::Data& digestResponse,
00146    RADIUSDigestAuthListener *listener) :
00147    username(username),
00148    digestUsername(digestUsername),
00149    digestRealm(digestRealm),
00150    digestNonce(digestNonce),
00151    digestUri(digestUri),
00152    digestMethod(digestMethod),
00153    digestQop(digestQop),
00154    digestNonceCount(digestNonceCount),
00155    digestCNonce(digestCNonce),
00156    digestBodyDigest(""),
00157    digestResponse(digestResponse),
00158    listener(listener)
00159 {
00160 }
00161 
00162 // QoP auth-int
00163 RADIUSDigestAuthenticator::RADIUSDigestAuthenticator(
00164    const resip::Data& username,
00165    const resip::Data& digestUsername,
00166    const resip::Data& digestRealm,
00167    const resip::Data& digestNonce,
00168    const resip::Data& digestUri,
00169    const resip::Data& digestMethod,
00170    const resip::Data& digestQop,
00171    const resip::Data& digestNonceCount,
00172    const resip::Data& digestCNonce,
00173    const resip::Data& digestBodyDigest,
00174    const resip::Data& digestResponse,
00175    RADIUSDigestAuthListener *listener) :
00176    username(username),
00177    digestUsername(digestUsername),
00178    digestRealm(digestRealm),
00179    digestNonce(digestNonce),
00180    digestUri(digestUri),
00181    digestMethod(digestMethod),
00182    digestQop(digestQop),
00183    digestNonceCount(digestNonceCount),
00184    digestCNonce(digestCNonce),
00185    digestBodyDigest(digestBodyDigest),
00186    digestResponse(digestResponse),
00187    listener(listener)
00188 {
00189 }
00190 
00191 RADIUSDigestAuthenticator::~RADIUSDigestAuthenticator()
00192 {
00193    DebugLog(<<"RADIUSDigestAuthenticator::~RADIUSDigestAuthenticator() entered");
00194    //terminate();
00195    DebugLog(<<"RADIUSDigestAuthenticator::~RADIUSDigestAuthenticator() done");
00196 }
00197 
00198 int RADIUSDigestAuthenticator::doRADIUSCheck()
00199 {
00200    run();
00201    detach();
00202    return 0;
00203    // return detach();
00204 }
00205 
00206 void RADIUSDigestAuthenticator::thread()
00207 {
00208 
00209    DebugLog(<<"RADIUSDigestAuthenticator::thread() entered");
00210 
00211    VALUE_PAIR *vp_s_start = createRADIUSRequest();
00212    VALUE_PAIR *vp_r_start;
00213 
00214    if(vp_s_start == NULL)
00215    {
00216       WarningLog(<<"vp_s_start == NULL");
00217       listener->onError();
00218       delete listener;
00219       //exit();
00220       delete this;
00221       return;
00222    }
00223 
00224    char msg[RADIUS_MSG_SIZE];
00225    int i;
00226    if ((i = rc_auth(rh, RADIUS_SIP_PORT, vp_s_start, &vp_r_start, msg)) == OK_RC)
00227    {
00228       DebugLog(<<"rc_auth success for " << username.c_str());
00229       rc_avpair_free(vp_s_start);
00230       Data rpid("");
00231       VALUE_PAIR *vp;
00232       if ((vp = rc_avpair_get(vp_r_start, attrs[A_SIP_RPID].v, 0)))
00233       {
00234          rpid = Data(vp->strvalue, vp->lvalue);
00235       }
00236       listener->onSuccess(rpid);
00237       rc_avpair_free(vp_r_start);
00238    }
00239    else
00240    {
00241       DebugLog(<<"rc_auth failure for " << username.c_str());
00242       rc_avpair_free(vp_s_start);
00243       rc_avpair_free(vp_r_start);
00244       if(i == BADRESP_RC)
00245       listener->onAccessDenied();
00246       else
00247       listener->onError();
00248    }
00249    delete listener;
00250    DebugLog(<<"RADIUSDigestAuthenticator::thread() exiting");
00251    //exit();
00252    delete this;
00253 }
00254 
00255 void RADIUSDigestAuthenticator::final()
00256 {
00257    DebugLog(<<"RADIUSDigestAuthenticator::final() entered");
00258 }
00259 
00260 VALUE_PAIR *RADIUSDigestAuthenticator::createRADIUSRequest()
00261 {
00262    VALUE_PAIR *vp_start = NULL;
00263 
00264    if(!rc_avpair_add(rh, &vp_start, attrs[A_USER_NAME].v, (char *)username.data(), username.size(), 0))
00265    {
00266       rc_avpair_free(vp_start);
00267       return NULL;
00268    }
00269    if(!rc_avpair_add(rh, &vp_start, attrs[A_DIGEST_USER_NAME].v, (char *)digestUsername.data(), digestUsername.size(), 0))
00270    {
00271       rc_avpair_free(vp_start);
00272       return NULL;
00273    }
00274    if(!rc_avpair_add(rh, &vp_start, attrs[A_DIGEST_REALM].v, (char *)digestRealm.data(), digestRealm.size(), 0))
00275    {
00276       rc_avpair_free(vp_start);
00277       return NULL;
00278    }
00279    if(!rc_avpair_add(rh, &vp_start, attrs[A_DIGEST_NONCE].v, (char *)digestNonce.data(), digestNonce.size(), 0))
00280    {
00281       rc_avpair_free(vp_start);
00282       return NULL;
00283    }
00284    if(!rc_avpair_add(rh, &vp_start, attrs[A_DIGEST_URI].v, (char *)digestUri.data(), digestUri.size(), 0))
00285    {
00286       rc_avpair_free(vp_start);
00287       return NULL;
00288    }
00289    if(!rc_avpair_add(rh, &vp_start, attrs[A_DIGEST_METHOD].v, (char *)digestMethod.data(), digestMethod.size(), 0))
00290    {
00291       rc_avpair_free(vp_start);
00292       return NULL;
00293    }
00294    if(!digestQop.empty())
00295    {
00296       if(!rc_avpair_add(rh, &vp_start, attrs[A_DIGEST_QOP].v, (char *)digestQop.data(), digestQop.size(), 0))
00297       {
00298          rc_avpair_free(vp_start);
00299          return NULL;
00300       }
00301       if(!rc_avpair_add(rh, &vp_start, attrs[A_DIGEST_NONCE_COUNT].v, (char *)digestNonceCount.data(), digestNonceCount.size(), 0))
00302       {
00303          rc_avpair_free(vp_start);
00304          return NULL;
00305       }
00306       if(!rc_avpair_add(rh, &vp_start, attrs[A_DIGEST_CNONCE].v, (char *)digestCNonce.data(), digestCNonce.size(), 0))
00307       {
00308          rc_avpair_free(vp_start);
00309          return NULL;
00310       }
00311       if(!digestBodyDigest.empty())
00312       {
00313          if(!rc_avpair_add(rh, &vp_start, attrs[A_USER_NAME].v, (char *)username.data(), username.size(), 0))
00314          {
00315             rc_avpair_free(vp_start);
00316             return NULL;
00317          }
00318       }
00319    } // end QoP
00320 
00321    if(!rc_avpair_add(rh, &vp_start, attrs[A_DIGEST_RESPONSE].v, (char *)digestResponse.data(), digestResponse.size(), 0))
00322    {
00323       rc_avpair_free(vp_start);
00324       return NULL;
00325    }
00326 
00327    UINT4 service = vals[V_SIP_SESSION].v;
00328    if (!rc_avpair_add(rh, &vp_start, attrs[A_SERVICE_TYPE].v, &service, -1, 0))
00329    {
00330       rc_avpair_free(vp_start);
00331       return NULL;
00332    }
00333 
00334    /* Add SIP URI as a check item */
00335    // xxx
00336    if (!rc_avpair_add(rh, &vp_start, attrs[A_SIP_URI_USER].v, (char *)digestUsername.data(), digestUsername.size(), 0))
00337    {
00338       rc_avpair_free(vp_start);
00339       return NULL;
00340    }
00341 
00342    return vp_start;
00343 }
00344 
00345 TestRADIUSDigestAuthListener::TestRADIUSDigestAuthListener()
00346 {
00347 }
00348 
00349 void TestRADIUSDigestAuthListener::onSuccess(const resip::Data& rpid)
00350 {
00351    DebugLog(<<"TestRADIUSDigestAuthListener::onSuccess");
00352    if(!rpid.empty())
00353    DebugLog(<<"TestRADIUSDigestAuthListener::onSuccess rpid = " << rpid);
00354    else
00355    DebugLog(<<"TestRADIUSDigestAuthListener::onSuccess, no rpid");
00356 }
00357 
00358 void TestRADIUSDigestAuthListener::onAccessDenied()
00359 {
00360    DebugLog(<<"TestRADIUSDigestAuthListener::onAccessDenied");
00361 }
00362 
00363 void TestRADIUSDigestAuthListener::onError()
00364 {
00365    WarningLog(<<"TestRADIUSDigestAuthListener::onError");
00366 }
00367 
00368 #endif
00369 
00370 
00371 /* ====================================================================
00372  * The Vovida Software License, Version 1.0
00373  *
00374  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
00375  *
00376  * Redistribution and use in source and binary forms, with or without
00377  * modification, are permitted provided that the following conditions
00378  * are met:
00379  *
00380  * 1. Redistributions of source code must retain the above copyright
00381  *    notice, this list of conditions and the following disclaimer.
00382  *
00383  * 2. Redistributions in binary form must reproduce the above copyright
00384  *    notice, this list of conditions and the following disclaimer in
00385  *    the documentation and/or other materials provided with the
00386  *    distribution.
00387  *
00388  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00389  *    and "Vovida Open Communication Application Library (VOCAL)" must
00390  *    not be used to endorse or promote products derived from this
00391  *    software without prior written permission. For written
00392  *    permission, please contact vocal@vovida.org.
00393  *
00394  * 4. Products derived from this software may not be called "VOCAL", nor
00395  *    may "VOCAL" appear in their name, without prior written
00396  *    permission of Vovida Networks, Inc.
00397  *
00398  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00399  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00400  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00401  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00402  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00403  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00404  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00405  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00406  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00407  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00408  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00409  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00410  * DAMAGE.
00411  *
00412  * ====================================================================
00413  *
00414  * This software consists of voluntary contributions made by Vovida
00415  * Networks, Inc. and many individuals on behalf of Vovida Networks,
00416  * Inc.  For more information on Vovida Networks, Inc., please see
00417  * <http://www.vovida.org/>.
00418  *
00419  */
00420