Sat Jul 12 2014 17:18:38

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