Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

authorize.c

Go to the documentation of this file.
00001 /*
00002  * $Id: authorize.c,v 1.25 2009/01/04 15:50:15 bpintea Exp $
00003  *
00004  * Digest Authentication - Radius support
00005  *
00006  * Copyright (C) 2001-2003 FhG Fokus
00007  *
00008  * This file is part of ser, a free SIP server.
00009  *
00010  * ser is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version
00014  *
00015  * For a license to use the ser software under conditions
00016  * other than those described here, or to purchase support for this
00017  * software, please contact iptel.org by e-mail at the following addresses:
00018  *    info@iptel.org
00019  *
00020  * ser is distributed in the hope that it will be useful,
00021  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  * GNU General Public License for more details.
00024  *
00025  * You should have received a copy of the GNU General Public License 
00026  * along with this program; if not, write to the Free Software 
00027  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00028  *
00029  * History:
00030  * -------
00031  * 2003-03-09: Based on authorize.c from radius_auth (janakj)
00032  */
00033 
00034 
00035 #include <string.h>
00036 #include <stdlib.h>
00037 #include "../../mem/mem.h"
00038 #include "../../str.h"
00039 #include "../../sr_module.h"
00040 #include "../../parser/hf.h"
00041 #include "../../parser/digest/digest.h"
00042 #include "../../parser/parse_uri.h"
00043 #include "../../parser/parse_from.h"
00044 #include "../../parser/parse_to.h"
00045 #include "../../dprint.h"
00046 #include "../../id.h"
00047 #include "../../ut.h"
00048 #include "../auth/api.h"
00049 #include "authorize.h"
00050 #include "sterman.h"
00051 #include "authrad_mod.h"
00052 
00053 
00054 static void attr_name_value(str* name, str* value, VALUE_PAIR* vp)
00055 {
00056     int i;
00057     
00058     for (i = 0; i < vp->lvalue; i++) {
00059         if (vp->strvalue[i] == ':' || vp->strvalue[i] == '=') {
00060             name->s = vp->strvalue;
00061             name->len = i;
00062             
00063             if (i == (vp->lvalue - 1)) {
00064                 value->s = (char*)0;
00065                 value->len = 0;
00066             } else {
00067                 value->s = vp->strvalue + i + 1;
00068                 value->len = vp->lvalue - i - 1;
00069             }
00070             return;
00071         }
00072     }
00073 
00074     name->len = value->len = 0;
00075     name->s = value->s = (char*)0;
00076 }
00077 
00078 
00079 /*
00080  * Generate AVPs from the database result
00081  */
00082 static int generate_avps(VALUE_PAIR* received)
00083 {
00084         int_str name, val;
00085         VALUE_PAIR *vp;
00086         
00087         vp = rc_avpair_get(received, ATTRID(attrs[A_SER_UID].v), VENDOR(attrs[A_SER_UID].v));
00088         if (vp == NULL) {
00089             WARN("RADIUS server did not send SER-UID attribute in digest authentication reply\n");
00090             return -1;
00091         }
00092         val.s.len = vp->lvalue;
00093         val.s.s = vp->strvalue;
00094         name.s.s = "uid";
00095         name.s.len = 3;
00096 
00097         if (add_avp(AVP_TRACK_FROM | AVP_CLASS_USER | AVP_NAME_STR | AVP_VAL_STR, name, val) < 0) {
00098             ERR("Unable to create UID attribute\n");
00099             return -1;
00100         }
00101 
00102         vp = received;
00103         while ((vp = rc_avpair_get(vp, ATTRID(attrs[A_SER_ATTR].v), VENDOR(attrs[A_SER_ATTR].v)))) {
00104                 attr_name_value(&name.s, &val.s, vp);
00105                 if (name.s.len == 0) {
00106                     ERR("Missing attribute name\n");
00107                     return -1;
00108                 }
00109                 
00110                 if (add_avp(AVP_TRACK_FROM | AVP_CLASS_USER | AVP_NAME_STR | AVP_VAL_STR, name, val) < 0) {
00111                         LOG(L_ERR, "generate_avps: Unable to create a new AVP\n");
00112                         return -1;
00113                 } else {
00114                         DBG("generate_avps: AVP '%.*s'='%.*s' has been added\n",
00115                             name.s.len, ZSW(name.s.s), 
00116                             val.s.len, ZSW(val.s.s));
00117                 }
00118                 vp = vp->next;
00119         }
00120         
00121         return 0;
00122 }
00123 
00124 
00125 
00126 
00127 /* 
00128  * Extract URI depending on the request from To or From header 
00129  */
00130 static inline int get_uri(struct sip_msg* _m, str** _uri)
00131 {
00132         if ((REQ_LINE(_m).method.len == 8) && (memcmp(REQ_LINE(_m).method.s, "REGISTER", 8) == 0)) {
00133                 if (!_m->to && ((parse_headers(_m, HDR_TO_F, 0) == -1) || !_m->to)) {
00134                         LOG(L_ERR, "get_uri(): To header field not found or malformed\n");
00135                         return -1;
00136                 }
00137                 *_uri = &(get_to(_m)->uri);
00138         } else {
00139                 if (parse_from_header(_m) == -1) {
00140                         LOG(L_ERR, "get_uri(): Error while parsing headers\n");
00141                         return -2;
00142                 }
00143                 *_uri = &(get_from(_m)->uri);
00144         }
00145         return 0;
00146 }
00147 
00148 
00149 /*
00150  * Authorize digest credentials
00151  */
00152 static inline int authenticate(struct sip_msg* msg, str* realm,
00153                                hdr_types_t hftype)
00154 {
00155         int res;
00156         auth_result_t ret;
00157         struct hdr_field* h;
00158         auth_body_t* cred;
00159         str* uri;
00160         struct sip_uri puri;
00161         str user, did;
00162         VALUE_PAIR* received;
00163 
00164         cred = 0;
00165         ret = -1;
00166         user.s = 0;
00167         received = NULL;
00168 
00169         switch(auth_api.pre_auth(msg, realm, hftype, &h, NULL)) {
00170         default:
00171                 BUG("unexpected reply '%d'.\n", auth_api.pre_auth(msg, realm, hftype,
00172                                 &h, NULL));
00173 #ifdef EXTRA_DEBUG
00174                 abort();
00175 #endif
00176         case ERROR:
00177         case BAD_CREDENTIALS:
00178             ret = -3;
00179             goto end;
00180 
00181         case NOT_AUTHENTICATED:
00182             ret = -1;
00183             goto end;
00184 
00185         case DO_AUTHENTICATION:
00186             break;
00187 
00188         case AUTHENTICATED:
00189             ret = 1;
00190             goto end;
00191         }
00192 
00193         cred = (auth_body_t*)h->parsed;
00194 
00195         if (use_did) {
00196             if (msg->REQ_METHOD == METHOD_REGISTER) {
00197                         ret = get_to_did(&did, msg);
00198             } else {
00199                         ret = get_from_did(&did, msg);
00200             }
00201             if (ret == 0) {
00202                         did.s = DEFAULT_DID;
00203                         did.len = sizeof(DEFAULT_DID) - 1;
00204             }
00205         } else {
00206             did.len = 0;
00207             did.s = 0;
00208         }
00209 
00210         if (get_uri(msg, &uri) < 0) {
00211                 LOG(L_ERR, "authorize(): From/To URI not found\n");
00212                 ret = -1;
00213                 goto end;
00214         }
00215         
00216         if (parse_uri(uri->s, uri->len, &puri) < 0) {
00217                 LOG(L_ERR, "authorize(): Error while parsing From/To URI\n");
00218                 ret = -1;
00219                 goto end;
00220         }
00221 
00222         user.s = (char *)pkg_malloc(puri.user.len);
00223         if (user.s == NULL) {
00224                 LOG(L_ERR, "authorize: No memory left\n");
00225                 ret = -1;
00226                 goto end;
00227         }
00228         un_escape(&(puri.user), &user);
00229 
00230         res = radius_authorize_sterman(&received, msg, &cred->digest, &msg->first_line.u.request.method, &user);
00231         if (res == 1) {
00232             switch(auth_api.post_auth(msg, h)) {
00233             case ERROR:             
00234             case BAD_CREDENTIALS:
00235                 ret = -2;
00236                 break;
00237 
00238             case NOT_AUTHENTICATED:
00239                 ret = -1;
00240                 break;
00241 
00242             case AUTHENTICATED:
00243                 if (generate_avps(received) < 0) {
00244                     ret = -1;
00245                     break;
00246                 }
00247                 ret = 1;
00248                 break;
00249 
00250             default:
00251                 ret = -1;
00252                 break;
00253             }
00254         } else {
00255             ret = -1;
00256         }
00257 
00258  end:
00259         if (received) rc_avpair_free(received);
00260         if (user.s) pkg_free(user.s);
00261         if (ret < 0) {
00262             if (auth_api.build_challenge(msg, (cred ? cred->stale : 0), realm, NULL, NULL, hftype) < 0) {
00263                 ERR("Error while creating challenge\n");
00264                 ret = -2;
00265             }
00266         }
00267         return ret;
00268 }
00269 
00270 
00271 /*
00272  * Authorize using Proxy-Authorize header field
00273  */
00274 int radius_proxy_authorize(struct sip_msg* _msg, char* p1, char* p2)
00275 {
00276     str realm;
00277 
00278     if (get_str_fparam(&realm, _msg, (fparam_t*)p1) < 0) {
00279         ERR("Cannot obtain digest realm from parameter '%s'\n", ((fparam_t*)p1)->orig);
00280         return -1;
00281     }
00282     
00283          /* realm parameter is converted to str* in str_fixup */
00284     return authenticate(_msg, &realm, HDR_PROXYAUTH_T);
00285 }
00286 
00287 
00288 /*
00289  * Authorize using WWW-Authorize header field
00290  */
00291 int radius_www_authorize(struct sip_msg* _msg, char* p1, char* p2)
00292 {
00293     str realm;
00294 
00295     if (get_str_fparam(&realm, _msg, (fparam_t*)p1) < 0) {
00296         ERR("Cannot obtain digest realm from parameter '%s'\n", ((fparam_t*)p1)->orig);
00297         return -1;
00298     }
00299     
00300     return authenticate(_msg, &realm, HDR_AUTHORIZATION_T);
00301 }
00302 

Generated on Tue Sep 7 04:15:55 2010 for SIPExpressRouter by  doxygen 1.3.9.1