|
reSIProcate/rutil
9694
|
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
1.7.5.1