Sat Apr 26 2014 22:01:41

Asterisk developer's documentation


channels/sip/security_events.c
Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 2012, Digium, Inc.
00005  *
00006  * Michael L. Young <elgueromexicano@gmail.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*!
00020  * \file
00021  *
00022  * \brief Generate security events in the SIP channel
00023  *
00024  * \author Michael L. Young <elgueromexicano@gmail.com>
00025  */
00026 
00027 /*** MODULEINFO
00028    <support_level>core</support_level>
00029  ***/
00030 
00031 #include "asterisk.h"
00032 
00033 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 385689 $")
00034 
00035 /* #define  REF_DEBUG 1 */
00036 
00037 #include "include/sip.h"
00038 #include "include/security_events.h"
00039 
00040 /*! \brief Determine transport type used to receive request*/
00041 
00042 static enum ast_security_event_transport_type security_event_get_transport(const struct sip_pvt *p)
00043 {
00044    int res = 0;
00045 
00046    switch (p->socket.type) {
00047    case SIP_TRANSPORT_UDP:
00048       return AST_SECURITY_EVENT_TRANSPORT_UDP;
00049    case SIP_TRANSPORT_TCP:
00050    case SIP_TRANSPORT_WS:
00051       return AST_SECURITY_EVENT_TRANSPORT_TCP;
00052    case SIP_TRANSPORT_TLS:
00053    case SIP_TRANSPORT_WSS:
00054       return AST_SECURITY_EVENT_TRANSPORT_TLS;
00055    }
00056 
00057    return res;
00058 }
00059 
00060 void sip_report_invalid_peer(const struct sip_pvt *p)
00061 {
00062    char session_id[32];
00063 
00064    struct ast_security_event_inval_acct_id inval_acct_id = {
00065       .common.event_type = AST_SECURITY_EVENT_INVAL_ACCT_ID,
00066       .common.version    = AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION,
00067       .common.service    = "SIP",
00068       .common.account_id = p->exten,
00069       .common.local_addr = {
00070          .addr      = &p->ourip,
00071          .transport = security_event_get_transport(p)
00072       },
00073       .common.remote_addr = {
00074          .addr       = &p->sa,
00075          .transport = security_event_get_transport(p)
00076       },
00077       .common.session_id = session_id,
00078    };
00079 
00080    snprintf(session_id, sizeof(session_id), "%p", p);
00081 
00082    ast_security_event_report(AST_SEC_EVT(&inval_acct_id));
00083 }
00084 
00085 void sip_report_failed_acl(const struct sip_pvt *p, const char *aclname)
00086 {
00087         char session_id[32];
00088 
00089         struct ast_security_event_failed_acl failed_acl_event = {
00090                 .common.event_type  = AST_SECURITY_EVENT_FAILED_ACL,
00091                 .common.version     = AST_SECURITY_EVENT_FAILED_ACL_VERSION,
00092                 .common.service     = "SIP",
00093                 .common.account_id  = p->exten,
00094                 .common.local_addr  = {
00095                         .addr       = &p->ourip,
00096                         .transport  = security_event_get_transport(p)
00097                 },
00098                 .common.remote_addr = {
00099                         .addr       = &p->sa,
00100                         .transport  = security_event_get_transport(p)
00101                 },
00102                 .common.session_id  = session_id,
00103                 .acl_name           = aclname,
00104         };
00105 
00106         snprintf(session_id, sizeof(session_id), "%p", p);
00107 
00108         ast_security_event_report(AST_SEC_EVT(&failed_acl_event));
00109 }
00110 
00111 void sip_report_inval_password(const struct sip_pvt *p, const char *response_challenge, const char *response_hash)
00112 {
00113         char session_id[32];
00114 
00115         struct ast_security_event_inval_password inval_password = {
00116                 .common.event_type  = AST_SECURITY_EVENT_INVAL_PASSWORD,
00117                 .common.version     = AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION,
00118                 .common.service     = "SIP",
00119                 .common.account_id  = p->exten,
00120                 .common.local_addr  = {
00121                         .addr       = &p->ourip,
00122                         .transport  = security_event_get_transport(p)
00123                 },
00124                 .common.remote_addr = {
00125                         .addr       = &p->sa,
00126                         .transport  = security_event_get_transport(p)
00127                 },
00128                 .common.session_id  = session_id,
00129 
00130       .challenge      = p->nonce,
00131       .received_challenge = response_challenge,
00132       .received_hash     = response_hash,
00133         };
00134 
00135         snprintf(session_id, sizeof(session_id), "%p", p);
00136 
00137         ast_security_event_report(AST_SEC_EVT(&inval_password));
00138 }
00139 
00140 void sip_report_auth_success(const struct sip_pvt *p, uint32_t *using_password)
00141 {
00142         char session_id[32];
00143 
00144         struct ast_security_event_successful_auth successful_auth = {
00145                 .common.event_type  = AST_SECURITY_EVENT_SUCCESSFUL_AUTH,
00146                 .common.version     = AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION,
00147                 .common.service     = "SIP",
00148                 .common.account_id  = p->exten,
00149                 .common.local_addr  = {
00150                         .addr       = &p->ourip,
00151                         .transport  = security_event_get_transport(p)
00152                 },
00153                 .common.remote_addr = {
00154                         .addr       = &p->sa,
00155                         .transport  = security_event_get_transport(p)
00156                 },
00157                 .common.session_id  = session_id,
00158                 .using_password     = using_password,
00159         };
00160 
00161         snprintf(session_id, sizeof(session_id), "%p", p);
00162 
00163         ast_security_event_report(AST_SEC_EVT(&successful_auth));
00164 }
00165 
00166 void sip_report_session_limit(const struct sip_pvt *p)
00167 {
00168         char session_id[32];
00169 
00170         struct ast_security_event_session_limit session_limit = {
00171                 .common.event_type = AST_SECURITY_EVENT_SESSION_LIMIT,
00172                 .common.version    = AST_SECURITY_EVENT_SESSION_LIMIT_VERSION,
00173                 .common.service    = "SIP",
00174                 .common.account_id = p->exten,
00175                 .common.local_addr = {
00176                         .addr      = &p->ourip,
00177                         .transport = security_event_get_transport(p)
00178                 },
00179                 .common.remote_addr = {
00180                         .addr      = &p->sa,
00181                         .transport = security_event_get_transport(p)
00182                 },
00183                 .common.session_id = session_id,
00184         };
00185 
00186         snprintf(session_id, sizeof(session_id), "%p", p);
00187 
00188         ast_security_event_report(AST_SEC_EVT(&session_limit));
00189 }
00190 
00191 void sip_report_failed_challenge_response(const struct sip_pvt *p, const char *response, const char *expected_response)
00192 {
00193    char session_id[32];
00194    char account_id[256];
00195 
00196    struct ast_security_event_chal_resp_failed chal_resp_failed = {
00197                 .common.event_type = AST_SECURITY_EVENT_CHAL_RESP_FAILED,
00198                 .common.version    = AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION,
00199                 .common.service    = "SIP",
00200                 .common.account_id = account_id,
00201                 .common.local_addr = {
00202                         .addr      = &p->ourip,
00203                         .transport = security_event_get_transport(p)
00204                 },
00205                 .common.remote_addr = {
00206                         .addr      = &p->sa,
00207                         .transport = security_event_get_transport(p)
00208                 },
00209                 .common.session_id = session_id,
00210 
00211                 .challenge         = p->nonce,
00212                 .response          = response,
00213                 .expected_response = expected_response,
00214         };
00215 
00216    if (!ast_strlen_zero(p->from)) { /* When dialing, show account making call */
00217                 ast_copy_string(account_id, p->from, sizeof(account_id));
00218         } else {
00219                 ast_copy_string(account_id, p->exten, sizeof(account_id));
00220         }
00221 
00222         snprintf(session_id, sizeof(session_id), "%p", p);
00223 
00224         ast_security_event_report(AST_SEC_EVT(&chal_resp_failed));
00225 }
00226 
00227 void sip_report_chal_sent(const struct sip_pvt *p)
00228 {
00229    char session_id[32];
00230    char account_id[256];
00231 
00232    struct ast_security_event_chal_sent chal_sent = {
00233                 .common.event_type = AST_SECURITY_EVENT_CHAL_SENT,
00234                 .common.version    = AST_SECURITY_EVENT_CHAL_SENT_VERSION,
00235                 .common.service    = "SIP",
00236                 .common.account_id = account_id,
00237                 .common.local_addr = {
00238                         .addr      = &p->ourip,
00239                         .transport = security_event_get_transport(p)
00240                 },
00241                 .common.remote_addr = {
00242                         .addr      = &p->sa,
00243                         .transport = security_event_get_transport(p)
00244                 },
00245                 .common.session_id = session_id,
00246 
00247                 .challenge         = p->nonce,
00248         };
00249 
00250    if (!ast_strlen_zero(p->from)) { /* When dialing, show account making call */
00251       ast_copy_string(account_id, p->from, sizeof(account_id));
00252    } else {
00253       ast_copy_string(account_id, p->exten, sizeof(account_id));
00254    }
00255 
00256         snprintf(session_id, sizeof(session_id), "%p", p);
00257 
00258         ast_security_event_report(AST_SEC_EVT(&chal_sent));
00259 }
00260 
00261 void sip_report_inval_transport(const struct sip_pvt *p, const char *transport)
00262 {
00263         char session_id[32];
00264 
00265         struct ast_security_event_inval_transport inval_transport = {
00266                 .common.event_type = AST_SECURITY_EVENT_INVAL_TRANSPORT,
00267                 .common.version    = AST_SECURITY_EVENT_INVAL_TRANSPORT_VERSION,
00268                 .common.service    = "SIP",
00269                 .common.account_id = p->exten,
00270                 .common.local_addr = {
00271                         .addr      = &p->ourip,
00272                         .transport = security_event_get_transport(p)
00273                 },
00274                 .common.remote_addr = {
00275                         .addr      = &p->sa,
00276                         .transport = security_event_get_transport(p)
00277                 },
00278                 .common.session_id = session_id,
00279 
00280                 .transport         = transport,
00281         };
00282 
00283         snprintf(session_id, sizeof(session_id), "%p", p);
00284 
00285         ast_security_event_report(AST_SEC_EVT(&inval_transport));
00286 }
00287 
00288 int sip_report_security_event(const struct sip_pvt *p, const struct sip_request *req, const int res) {
00289 
00290    struct sip_peer *peer_report;
00291    enum check_auth_result res_report = res;
00292    struct ast_str *buf;
00293    char *c;
00294    const char *authtoken;
00295    char *reqheader, *respheader;
00296    int result = 0;
00297    char aclname[256];
00298    struct digestkeys keys[] = {
00299       [K_RESP]  = { "response=", "" },
00300       [K_URI]   = { "uri=", "" },
00301       [K_USER]  = { "username=", "" },
00302       [K_NONCE] = { "nonce=", "" },
00303       [K_LAST]  = { NULL, NULL}
00304    };
00305 
00306    peer_report = sip_find_peer(p->exten, NULL, TRUE, FINDPEERS, FALSE, 0);
00307 
00308    switch(res_report) {
00309    case AUTH_DONT_KNOW:
00310       break;
00311    case AUTH_SUCCESSFUL:
00312       if (peer_report) {
00313          if (ast_strlen_zero(peer_report->secret) && ast_strlen_zero(peer_report->md5secret)) {
00314          sip_report_auth_success(p, (uint32_t *) 0);
00315          } else {
00316             sip_report_auth_success(p, (uint32_t *) 1);
00317          }
00318       }
00319       break;
00320    case AUTH_CHALLENGE_SENT:
00321       sip_report_chal_sent(p);
00322       break;
00323    case AUTH_SECRET_FAILED:
00324    case AUTH_USERNAME_MISMATCH:
00325       sip_auth_headers(WWW_AUTH, &respheader, &reqheader);
00326       authtoken = sip_get_header(req, reqheader);
00327       buf = ast_str_thread_get(&check_auth_buf, CHECK_AUTH_BUF_INITLEN);
00328       ast_str_set(&buf, 0, "%s", authtoken);
00329       c = buf->str;
00330 
00331       sip_digest_parser(c, keys);
00332 
00333       if (res_report == AUTH_SECRET_FAILED) {
00334          sip_report_inval_password(p, keys[K_NONCE].s, keys[K_RESP].s);
00335       } else {
00336          if (peer_report) {
00337             sip_report_failed_challenge_response(p, keys[K_USER].s, peer_report->username);
00338          }
00339       }
00340       break;
00341    case AUTH_NOT_FOUND:
00342       /* with sip_cfg.alwaysauthreject on, generates 2 events */
00343       sip_report_invalid_peer(p);
00344       break;
00345    case AUTH_UNKNOWN_DOMAIN:
00346       snprintf(aclname, sizeof(aclname), "domain_must_match");
00347       sip_report_failed_acl(p, aclname);
00348       break;
00349    case AUTH_PEER_NOT_DYNAMIC:
00350       snprintf(aclname, sizeof(aclname), "peer_not_dynamic");
00351       sip_report_failed_acl(p, aclname);
00352       break;
00353    case AUTH_ACL_FAILED:
00354       /* with sip_cfg.alwaysauthreject on, generates 2 events */
00355       snprintf(aclname, sizeof(aclname), "device_must_match_acl");
00356       sip_report_failed_acl(p, aclname);
00357       break;
00358    case AUTH_BAD_TRANSPORT:
00359       sip_report_inval_transport(p, sip_get_transport(req->socket.type));
00360       break;
00361    case AUTH_RTP_FAILED:
00362       break;
00363    case AUTH_SESSION_LIMIT:
00364       sip_report_session_limit(p);
00365       break;
00366    }
00367 
00368    if (peer_report) {
00369       sip_unref_peer(peer_report, "sip_report_security_event: sip_unref_peer: from handle_incoming");
00370    }
00371 
00372    return result;
00373 }
00374