123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317 |
- /*
- * $Id$
- *
- * Copyright (C) 2012 Smile Communications, [email protected]
- * Copyright (C) 2012 Smile Communications, [email protected]
- *
- * The initial version of this code was written by Dragos Vingarzan
- * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
- * Fruanhofer Institute. It was and still is maintained in a separate
- * branch of the original SER. We are therefore migrating it to
- * Kamailio/SR and look forward to maintaining it from here on out.
- * 2011/2012 Smile Communications, Pty. Ltd.
- * ported/maintained/improved by
- * Jason Penton (jason(dot)penton(at)smilecoms.com and
- * Richard Good (richard(dot)good(at)smilecoms.com) as part of an
- * effort to add full IMS support to Kamailio/SR using a new and
- * improved architecture
- *
- * NB: Alot of this code was originally part of OpenIMSCore,
- * FhG Fokus.
- * Copyright (C) 2004-2006 FhG Fokus
- * Thanks for great work! This is an effort to
- * break apart the various CSCF functions into logically separate
- * components. We hope this will drive wider use. We also feel
- * that in this way the architecture is more complete and thereby easier
- * to manage in the Kamailio/SR environment
- *
- * This file is part of Kamailio, a free SIP server.
- *
- * Kamailio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
- *
- * Kamailio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
- #include "utils.h"
- /*
- * Find credentials with given realm in a SIP message header
- */
- inline int ims_find_credentials(struct sip_msg* _m, str* _realm,
- hdr_types_t _hftype, struct hdr_field** _h) {
- struct hdr_field** hook, *ptr, *prev;
- hdr_flags_t hdr_flags;
- int res;
- str* r;
- LM_DBG("Searching credentials in realm [%.*s]\n", _realm->len, _realm->s);
- /*
- * Determine if we should use WWW-Authorization or
- * Proxy-Authorization header fields, this parameter
- * is set in www_authorize and proxy_authorize
- */
- switch (_hftype) {
- case HDR_AUTHORIZATION_T:
- hook = &(_m->authorization);
- hdr_flags = HDR_AUTHORIZATION_F;
- break;
- case HDR_PROXYAUTH_T:
- hook = &(_m->proxy_auth);
- hdr_flags = HDR_PROXYAUTH_F;
- break;
- default:
- hook = &(_m->authorization);
- hdr_flags = HDR_T2F(_hftype);
- break;
- }
- /*
- * If the credentials haven't been parsed yet, do it now
- */
- if (*hook == 0) {
- /* No credentials parsed yet */
- LM_DBG("*hook == 0, No credentials parsed yet\n");
- if (parse_headers(_m, hdr_flags, 0) == -1) {
- LM_ERR("Error while parsing headers\n");
- return -1;
- }
- }
- ptr = *hook;
- LM_DBG("*hook = %p\n", ptr);
- /*
- * Iterate through the credentials in the message and
- * find credentials with given realm
- */
- while (ptr) {
- res = parse_credentials(ptr);
- if (res < 0) {
- LM_ERR("Error while parsing credentials\n");
- return (res == -1) ? -2 : -3;
- } else if (res == 0) {
- LM_DBG("Credential parsed successfully\n");
- if (_realm->len) {
- r = &(((auth_body_t*) (ptr->parsed))->digest.realm);
- LM_DBG("Comparing realm <%.*s> and <%.*s>\n", _realm->len, _realm->s, r->len, r->s);
- if (r->len == _realm->len) {
- if (!strncasecmp(_realm->s, r->s, r->len)) {
- *_h = ptr;
- return 0;
- }
- }
- } else {
- *_h = ptr;
- return 0;
- }
- }
- prev = ptr;
- if (parse_headers(_m, hdr_flags, 1) == -1) {
- LM_ERR("Error while parsing headers\n");
- return -4;
- } else {
- if (prev != _m->last_header) {
- if (_m->last_header->type == _hftype)
- ptr = _m->last_header;
- else
- break;
- } else
- break;
- }
- }
- /*
- * Credentials with given realm not found
- */
- LM_DBG("Credentials with given realm not found\n");
- return 1;
- }
- /**
- * Looks for the nonce and response parameters in the Authorization header and returns them
- * @param msg - the SIP message
- * @param realm - realm to match the right Authorization header
- * @param nonce - param to fill with the nonce found
- * @param response - param to fill with the response
- * @returns 1 if found, 0 if not
- */
- int get_nonce_response(struct sip_msg *msg, str realm,str *nonce,str *response,
- enum qop_type *qop,str *qop_str,str *nc,str *cnonce,str *uri, int is_proxy_auth)
- {
- struct hdr_field* h = 0;
- int ret;
- ret = parse_headers(msg, is_proxy_auth ? HDR_PROXYAUTH_F : HDR_AUTHORIZATION_F, 0);
- if (ret != 0) {
- return 0;
- }
- if ((!is_proxy_auth && !msg->authorization)
- || (is_proxy_auth && !msg->proxy_auth)) {
- return 0;
- }
- LM_DBG("Calling find_credentials with realm [%.*s]\n", realm.len, realm.s);
- ret = ims_find_credentials(msg, &realm, is_proxy_auth ? HDR_PROXYAUTH_T : HDR_AUTHORIZATION_T, &h);
- if (ret < 0) {
- return 0;
- } else if (ret > 0) {
- LM_DBG("ret > 0");
- return 0;
- }
- if (h && h->parsed) {
- if (nonce)
- *nonce = ((auth_body_t*) h->parsed)->digest.nonce;
- if (response)
- *response = ((auth_body_t*) h->parsed)->digest.response;
- if (qop)
- *qop = ((auth_body_t*) h->parsed)->digest.qop.qop_parsed;
- if (qop_str)
- *qop_str = ((auth_body_t*) h->parsed)->digest.qop.qop_str;
- if (nc)
- *nc = ((auth_body_t*) h->parsed)->digest.nc;
- if (cnonce)
- *cnonce = ((auth_body_t*) h->parsed)->digest.cnonce;
- if (uri)
- *uri = ((auth_body_t*) h->parsed)->digest.uri;
- }
- LM_DBG("Found nonce response\n");
- return 1;
- }
- str ims_get_body(struct sip_msg * msg)
- {
- str x={0,0};
-
- if (parse_headers(msg,HDR_CONTENTLENGTH_F,0)!=0) {
- LM_DBG("Error parsing until header Content-Length: \n");
- return x;
- }
- x.len = (int)(long)msg->content_length->parsed;
-
- if (x.len>0)
- x.s = get_body(msg);
-
- return x;
- }
- /**
- * Looks for the auts parameter in the Authorization header and returns its value.
- * @param msg - the SIP message
- * @param realm - realm to match the right Authorization header
- * @returns the auts value or an empty string if not found
- */
- str ims_get_auts(struct sip_msg *msg, str realm, int is_proxy_auth)
- {
- str name={"auts=\"",6};
- struct hdr_field* h=0;
- int i,ret;
- str auts={0,0};
- if (parse_headers(msg, is_proxy_auth ? HDR_PROXYAUTH_F : HDR_AUTHORIZATION_F,0)!=0) {
- LM_ERR("Error parsing until header Authorization: \n");
- return auts;
- }
- if ((!is_proxy_auth && !msg->authorization)
- || (is_proxy_auth && !msg->proxy_auth)){
- LM_ERR("Message does not contain Authorization nor Proxy-Authorization header.\n");
- return auts;
- }
- ret = find_credentials(msg, &realm, is_proxy_auth ? HDR_PROXYAUTH_F : HDR_AUTHORIZATION_F, &h);
- if (ret < 0) {
- LM_ERR("Error while looking for credentials.\n");
- return auts;
- } else
- if (ret > 0) {
- LM_ERR("No credentials for this realm found.\n");
- return auts;
- }
-
- if (h) {
- for(i=0;i<h->body.len-name.len;i++)
- if (strncasecmp(h->body.s+i,name.s,name.len)==0){
- auts.s = h->body.s+i+name.len;
- while(i+auts.len<h->body.len && auts.s[auts.len]!='\"')
- auts.len++;
- }
- }
-
- return auts;
- }
- /**
- * Looks for the nonce parameter in the Authorization header and returns its value.
- * @param msg - the SIP message
- * @param realm - realm to match the right Authorization header
- * @returns the nonce or an empty string if none found
- */
- str ims_get_nonce(struct sip_msg *msg, str realm)
- {
- struct hdr_field* h=0;
- int ret;
- str nonce={0,0};
- if (parse_headers(msg,HDR_AUTHORIZATION_F,0)!=0) {
- LM_ERR("Error parsing until header Authorization: \n");
- return nonce;
- }
- if (!msg->authorization){
- LM_ERR("Message does not contain Authorization header.\n");
- return nonce;
- }
- ret = find_credentials(msg, &realm, HDR_AUTHORIZATION_F, &h);
- if (ret < 0) {
- LM_ERR("Error while looking for credentials.\n");
- return nonce;
- } else
- if (ret > 0) {
- LM_ERR("No credentials for this realm found.\n");
- return nonce;
- }
-
- if (h&&h->parsed) {
- nonce = ((auth_body_t*)h->parsed)->digest.nonce;
- }
-
- return nonce;
- }
- /**
- * Adds a header to the reply message
- * @param msg - the request to add a header to its reply
- * @param content - the str containing the new header
- * @returns 1 on succes, 0 on failure
- */
- int ims_add_header_rpl(struct sip_msg *msg, str *hdr)
- {
- if (add_lump_rpl( msg, hdr->s, hdr->len, LUMP_RPL_HDR)==0) {
- LM_ERR("Can't add header <%.*s>\n",
- hdr->len,hdr->s);
- return 0;
- }
- return 1;
- }
|