Sat Apr 26 2014 22:03:15

Asterisk developer's documentation


channels/sip/security_events.c File Reference

Generate security events in the SIP channel. More...

#include "asterisk.h"
#include "include/sip.h"
#include "include/security_events.h"
Include dependency graph for channels/sip/security_events.c:

Go to the source code of this file.

Functions

static enum
ast_security_event_transport_type 
security_event_get_transport (const struct sip_pvt *p)
 Determine transport type used to receive request.
void sip_report_auth_success (const struct sip_pvt *p, uint32_t *using_password)
void sip_report_chal_sent (const struct sip_pvt *p)
void sip_report_failed_acl (const struct sip_pvt *p, const char *aclname)
void sip_report_failed_challenge_response (const struct sip_pvt *p, const char *response, const char *expected_response)
void sip_report_inval_password (const struct sip_pvt *p, const char *response_challenge, const char *response_hash)
void sip_report_inval_transport (const struct sip_pvt *p, const char *transport)
void sip_report_invalid_peer (const struct sip_pvt *p)
int sip_report_security_event (const struct sip_pvt *p, const struct sip_request *req, const int res)
void sip_report_session_limit (const struct sip_pvt *p)

Detailed Description

Generate security events in the SIP channel.

Author:
Michael L. Young <elgueromexicano@gmail.com>

Definition in file channels/sip/security_events.c.


Function Documentation

static enum ast_security_event_transport_type security_event_get_transport ( const struct sip_pvt *  p) [static]

Determine transport type used to receive request.

Definition at line 42 of file channels/sip/security_events.c.

References AST_SECURITY_EVENT_TRANSPORT_TCP, AST_SECURITY_EVENT_TRANSPORT_TLS, and AST_SECURITY_EVENT_TRANSPORT_UDP.

Referenced by sip_report_auth_success(), sip_report_chal_sent(), sip_report_failed_acl(), sip_report_failed_challenge_response(), sip_report_inval_password(), sip_report_inval_transport(), sip_report_invalid_peer(), and sip_report_session_limit().

{
   int res = 0;

   switch (p->socket.type) {
   case SIP_TRANSPORT_UDP:
      return AST_SECURITY_EVENT_TRANSPORT_UDP;
   case SIP_TRANSPORT_TCP:
   case SIP_TRANSPORT_WS:
      return AST_SECURITY_EVENT_TRANSPORT_TCP;
   case SIP_TRANSPORT_TLS:
   case SIP_TRANSPORT_WSS:
      return AST_SECURITY_EVENT_TRANSPORT_TLS;
   }

   return res;
}
void sip_report_auth_success ( const struct sip_pvt *  p,
uint32_t *  using_password 
)

Definition at line 140 of file channels/sip/security_events.c.

References AST_SEC_EVT, ast_security_event_report(), AST_SECURITY_EVENT_SUCCESSFUL_AUTH, AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION, ast_security_event_successful_auth::common, ast_security_event_common::event_type, security_event_get_transport(), and ast_security_event_successful_auth::using_password.

Referenced by sip_report_security_event().

{
        char session_id[32];

        struct ast_security_event_successful_auth successful_auth = {
                .common.event_type  = AST_SECURITY_EVENT_SUCCESSFUL_AUTH,
                .common.version     = AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION,
                .common.service     = "SIP",
                .common.account_id  = p->exten,
                .common.local_addr  = {
                        .addr       = &p->ourip,
                        .transport  = security_event_get_transport(p)
                },
                .common.remote_addr = {
                        .addr       = &p->sa,
                        .transport  = security_event_get_transport(p)
                },
                .common.session_id  = session_id,
                .using_password     = using_password,
        };

        snprintf(session_id, sizeof(session_id), "%p", p);

        ast_security_event_report(AST_SEC_EVT(&successful_auth));
}
void sip_report_chal_sent ( const struct sip_pvt *  p)

Definition at line 227 of file channels/sip/security_events.c.

References ast_copy_string(), AST_SEC_EVT, AST_SECURITY_EVENT_CHAL_SENT, AST_SECURITY_EVENT_CHAL_SENT_VERSION, ast_security_event_report(), ast_strlen_zero(), ast_security_event_chal_sent::common, ast_security_event_common::event_type, and security_event_get_transport().

Referenced by sip_report_security_event().

{
   char session_id[32];
   char account_id[256];

   struct ast_security_event_chal_sent chal_sent = {
                .common.event_type = AST_SECURITY_EVENT_CHAL_SENT,
                .common.version    = AST_SECURITY_EVENT_CHAL_SENT_VERSION,
                .common.service    = "SIP",
                .common.account_id = account_id,
                .common.local_addr = {
                        .addr      = &p->ourip,
                        .transport = security_event_get_transport(p)
                },
                .common.remote_addr = {
                        .addr      = &p->sa,
                        .transport = security_event_get_transport(p)
                },
                .common.session_id = session_id,

                .challenge         = p->nonce,
        };

   if (!ast_strlen_zero(p->from)) { /* When dialing, show account making call */
      ast_copy_string(account_id, p->from, sizeof(account_id));
   } else {
      ast_copy_string(account_id, p->exten, sizeof(account_id));
   }

        snprintf(session_id, sizeof(session_id), "%p", p);

        ast_security_event_report(AST_SEC_EVT(&chal_sent));
}
void sip_report_failed_acl ( const struct sip_pvt *  p,
const char *  aclname 
)

Definition at line 85 of file channels/sip/security_events.c.

References AST_SEC_EVT, AST_SECURITY_EVENT_FAILED_ACL, AST_SECURITY_EVENT_FAILED_ACL_VERSION, ast_security_event_report(), ast_security_event_failed_acl::common, ast_security_event_common::event_type, and security_event_get_transport().

Referenced by sip_report_security_event().

{
        char session_id[32];

        struct ast_security_event_failed_acl failed_acl_event = {
                .common.event_type  = AST_SECURITY_EVENT_FAILED_ACL,
                .common.version     = AST_SECURITY_EVENT_FAILED_ACL_VERSION,
                .common.service     = "SIP",
                .common.account_id  = p->exten,
                .common.local_addr  = {
                        .addr       = &p->ourip,
                        .transport  = security_event_get_transport(p)
                },
                .common.remote_addr = {
                        .addr       = &p->sa,
                        .transport  = security_event_get_transport(p)
                },
                .common.session_id  = session_id,
                .acl_name           = aclname,
        };

        snprintf(session_id, sizeof(session_id), "%p", p);

        ast_security_event_report(AST_SEC_EVT(&failed_acl_event));
}
void sip_report_failed_challenge_response ( const struct sip_pvt *  p,
const char *  response,
const char *  expected_response 
)

Definition at line 191 of file channels/sip/security_events.c.

References ast_copy_string(), AST_SEC_EVT, AST_SECURITY_EVENT_CHAL_RESP_FAILED, AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION, ast_security_event_report(), ast_strlen_zero(), ast_security_event_chal_resp_failed::common, ast_security_event_common::event_type, ast_security_event_chal_resp_failed::expected_response, ast_security_event_chal_resp_failed::response, and security_event_get_transport().

Referenced by sip_report_security_event().

{
   char session_id[32];
   char account_id[256];

   struct ast_security_event_chal_resp_failed chal_resp_failed = {
                .common.event_type = AST_SECURITY_EVENT_CHAL_RESP_FAILED,
                .common.version    = AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION,
                .common.service    = "SIP",
                .common.account_id = account_id,
                .common.local_addr = {
                        .addr      = &p->ourip,
                        .transport = security_event_get_transport(p)
                },
                .common.remote_addr = {
                        .addr      = &p->sa,
                        .transport = security_event_get_transport(p)
                },
                .common.session_id = session_id,

                .challenge         = p->nonce,
                .response          = response,
                .expected_response = expected_response,
        };

   if (!ast_strlen_zero(p->from)) { /* When dialing, show account making call */
                ast_copy_string(account_id, p->from, sizeof(account_id));
        } else {
                ast_copy_string(account_id, p->exten, sizeof(account_id));
        }

        snprintf(session_id, sizeof(session_id), "%p", p);

        ast_security_event_report(AST_SEC_EVT(&chal_resp_failed));
}
void sip_report_inval_password ( const struct sip_pvt *  p,
const char *  response_challenge,
const char *  response_hash 
)

Definition at line 111 of file channels/sip/security_events.c.

References AST_SEC_EVT, AST_SECURITY_EVENT_INVAL_PASSWORD, AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION, ast_security_event_report(), ast_security_event_inval_password::common, ast_security_event_common::event_type, and security_event_get_transport().

Referenced by sip_report_security_event().

{
        char session_id[32];

        struct ast_security_event_inval_password inval_password = {
                .common.event_type  = AST_SECURITY_EVENT_INVAL_PASSWORD,
                .common.version     = AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION,
                .common.service     = "SIP",
                .common.account_id  = p->exten,
                .common.local_addr  = {
                        .addr       = &p->ourip,
                        .transport  = security_event_get_transport(p)
                },
                .common.remote_addr = {
                        .addr       = &p->sa,
                        .transport  = security_event_get_transport(p)
                },
                .common.session_id  = session_id,

      .challenge      = p->nonce,
      .received_challenge = response_challenge,
      .received_hash     = response_hash,
        };

        snprintf(session_id, sizeof(session_id), "%p", p);

        ast_security_event_report(AST_SEC_EVT(&inval_password));
}
void sip_report_inval_transport ( const struct sip_pvt *  p,
const char *  transport 
)

Definition at line 261 of file channels/sip/security_events.c.

References AST_SEC_EVT, AST_SECURITY_EVENT_INVAL_TRANSPORT, AST_SECURITY_EVENT_INVAL_TRANSPORT_VERSION, ast_security_event_report(), ast_security_event_inval_transport::common, ast_security_event_common::event_type, security_event_get_transport(), and ast_security_event_inval_transport::transport.

Referenced by sip_report_security_event().

{
        char session_id[32];

        struct ast_security_event_inval_transport inval_transport = {
                .common.event_type = AST_SECURITY_EVENT_INVAL_TRANSPORT,
                .common.version    = AST_SECURITY_EVENT_INVAL_TRANSPORT_VERSION,
                .common.service    = "SIP",
                .common.account_id = p->exten,
                .common.local_addr = {
                        .addr      = &p->ourip,
                        .transport = security_event_get_transport(p)
                },
                .common.remote_addr = {
                        .addr      = &p->sa,
                        .transport = security_event_get_transport(p)
                },
                .common.session_id = session_id,

                .transport         = transport,
        };

        snprintf(session_id, sizeof(session_id), "%p", p);

        ast_security_event_report(AST_SEC_EVT(&inval_transport));
}
void sip_report_invalid_peer ( const struct sip_pvt *  p)

Definition at line 60 of file channels/sip/security_events.c.

References AST_SEC_EVT, AST_SECURITY_EVENT_INVAL_ACCT_ID, AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION, ast_security_event_report(), ast_security_event_inval_acct_id::common, ast_security_event_common::event_type, and security_event_get_transport().

Referenced by sip_report_security_event().

{
   char session_id[32];

   struct ast_security_event_inval_acct_id inval_acct_id = {
      .common.event_type = AST_SECURITY_EVENT_INVAL_ACCT_ID,
      .common.version    = AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION,
      .common.service    = "SIP",
      .common.account_id = p->exten,
      .common.local_addr = {
         .addr      = &p->ourip,
         .transport = security_event_get_transport(p)
      },
      .common.remote_addr = {
         .addr       = &p->sa,
         .transport = security_event_get_transport(p)
      },
      .common.session_id = session_id,
   };

   snprintf(session_id, sizeof(session_id), "%p", p);

   ast_security_event_report(AST_SEC_EVT(&inval_acct_id));
}
int sip_report_security_event ( const struct sip_pvt *  p,
const struct sip_request *  req,
const int  res 
)

Definition at line 288 of file channels/sip/security_events.c.

References ast_str_set(), ast_str_thread_get(), ast_strlen_zero(), FALSE, sip_auth_headers(), sip_digest_parser(), sip_find_peer(), sip_get_header(), sip_get_transport(), sip_report_auth_success(), sip_report_chal_sent(), sip_report_failed_acl(), sip_report_failed_challenge_response(), sip_report_inval_password(), sip_report_inval_transport(), sip_report_invalid_peer(), sip_report_session_limit(), sip_unref_peer(), and TRUE.

Referenced by handle_incoming().

                                                                                                     {

   struct sip_peer *peer_report;
   enum check_auth_result res_report = res;
   struct ast_str *buf;
   char *c;
   const char *authtoken;
   char *reqheader, *respheader;
   int result = 0;
   char aclname[256];
   struct digestkeys keys[] = {
      [K_RESP]  = { "response=", "" },
      [K_URI]   = { "uri=", "" },
      [K_USER]  = { "username=", "" },
      [K_NONCE] = { "nonce=", "" },
      [K_LAST]  = { NULL, NULL}
   };

   peer_report = sip_find_peer(p->exten, NULL, TRUE, FINDPEERS, FALSE, 0);

   switch(res_report) {
   case AUTH_DONT_KNOW:
      break;
   case AUTH_SUCCESSFUL:
      if (peer_report) {
         if (ast_strlen_zero(peer_report->secret) && ast_strlen_zero(peer_report->md5secret)) {
         sip_report_auth_success(p, (uint32_t *) 0);
         } else {
            sip_report_auth_success(p, (uint32_t *) 1);
         }
      }
      break;
   case AUTH_CHALLENGE_SENT:
      sip_report_chal_sent(p);
      break;
   case AUTH_SECRET_FAILED:
   case AUTH_USERNAME_MISMATCH:
      sip_auth_headers(WWW_AUTH, &respheader, &reqheader);
      authtoken = sip_get_header(req, reqheader);
      buf = ast_str_thread_get(&check_auth_buf, CHECK_AUTH_BUF_INITLEN);
      ast_str_set(&buf, 0, "%s", authtoken);
      c = buf->str;

      sip_digest_parser(c, keys);

      if (res_report == AUTH_SECRET_FAILED) {
         sip_report_inval_password(p, keys[K_NONCE].s, keys[K_RESP].s);
      } else {
         if (peer_report) {
            sip_report_failed_challenge_response(p, keys[K_USER].s, peer_report->username);
         }
      }
      break;
   case AUTH_NOT_FOUND:
      /* with sip_cfg.alwaysauthreject on, generates 2 events */
      sip_report_invalid_peer(p);
      break;
   case AUTH_UNKNOWN_DOMAIN:
      snprintf(aclname, sizeof(aclname), "domain_must_match");
      sip_report_failed_acl(p, aclname);
      break;
   case AUTH_PEER_NOT_DYNAMIC:
      snprintf(aclname, sizeof(aclname), "peer_not_dynamic");
      sip_report_failed_acl(p, aclname);
      break;
   case AUTH_ACL_FAILED:
      /* with sip_cfg.alwaysauthreject on, generates 2 events */
      snprintf(aclname, sizeof(aclname), "device_must_match_acl");
      sip_report_failed_acl(p, aclname);
      break;
   case AUTH_BAD_TRANSPORT:
      sip_report_inval_transport(p, sip_get_transport(req->socket.type));
      break;
   case AUTH_RTP_FAILED:
      break;
   case AUTH_SESSION_LIMIT:
      sip_report_session_limit(p);
      break;
   }

   if (peer_report) {
      sip_unref_peer(peer_report, "sip_report_security_event: sip_unref_peer: from handle_incoming");
   }

   return result;
}
void sip_report_session_limit ( const struct sip_pvt *  p)

Definition at line 166 of file channels/sip/security_events.c.

References AST_SEC_EVT, ast_security_event_report(), AST_SECURITY_EVENT_SESSION_LIMIT, AST_SECURITY_EVENT_SESSION_LIMIT_VERSION, ast_security_event_session_limit::common, ast_security_event_common::event_type, and security_event_get_transport().

Referenced by sip_report_security_event().

{
        char session_id[32];

        struct ast_security_event_session_limit session_limit = {
                .common.event_type = AST_SECURITY_EVENT_SESSION_LIMIT,
                .common.version    = AST_SECURITY_EVENT_SESSION_LIMIT_VERSION,
                .common.service    = "SIP",
                .common.account_id = p->exten,
                .common.local_addr = {
                        .addr      = &p->ourip,
                        .transport = security_event_get_transport(p)
                },
                .common.remote_addr = {
                        .addr      = &p->sa,
                        .transport = security_event_get_transport(p)
                },
                .common.session_id = session_id,
        };

        snprintf(session_id, sizeof(session_id), "%p", p);

        ast_security_event_report(AST_SEC_EVT(&session_limit));
}