[asterisk-commits] jrose: branch 10 r337597 - in /branches/10/channels/sip: ./ include/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Sep 22 10:47:09 CDT 2011


Author: jrose
Date: Thu Sep 22 10:47:05 2011
New Revision: 337597

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=337597
Log:
Forgot to svn add new files to r337595

Part of Generating security events for chan_sip

(issue ASTERISK-18264)
Reported by: Michael L. Young
Patches:
    security_events_chan_sip_v4.patch (License #5026) by Michael L. Young
Reviewboard: https://reviewboard.asterisk.org/r/1362/

Added:
    branches/10/channels/sip/include/security_events.h   (with props)
    branches/10/channels/sip/security_events.c   (with props)

Added: branches/10/channels/sip/include/security_events.h
URL: http://svnview.digium.com/svn/asterisk/branches/10/channels/sip/include/security_events.h?view=auto&rev=337597
==============================================================================
--- branches/10/channels/sip/include/security_events.h (added)
+++ branches/10/channels/sip/include/security_events.h Thu Sep 22 10:47:05 2011
@@ -1,0 +1,43 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2011, Digium, Inc.
+ *
+ * Michael L. Young <elgueromexicano at gmail.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!
+ * \file
+ *
+ * \brief Generate security events in the SIP channel
+ *
+ * \author Michael L. Young <elgueromexicano at gmail.com>
+ */
+
+#include "sip.h"
+
+#ifndef _SIP_SECURITY_EVENTS_H
+#define _SIP_SECURITY_EVENTS_H
+
+void sip_report_invalid_peer(const struct sip_pvt *p);
+void sip_report_failed_acl(const struct sip_pvt *p, const char *aclname);
+void sip_report_inval_password(const struct sip_pvt *p, const char *responsechallenge, const char *responsehash);
+void sip_report_auth_success(const struct sip_pvt *p, uint32_t *using_password);
+void sip_report_session_limit(const struct sip_pvt *p);
+void sip_report_failed_challenge_response(const struct sip_pvt *p, const char *response, const char *expected_response);
+void sip_report_chal_sent(const struct sip_pvt *p);
+void sip_report_inval_transport(const struct sip_pvt *p, const char *transport);
+void sip_digest_parser(char *c, struct digestkeys *keys);
+int sip_report_security_event(const struct sip_pvt *p, const struct sip_request *req, const int res);
+
+#endif

Propchange: branches/10/channels/sip/include/security_events.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: branches/10/channels/sip/include/security_events.h
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Rev URL"

Propchange: branches/10/channels/sip/include/security_events.h
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: branches/10/channels/sip/security_events.c
URL: http://svnview.digium.com/svn/asterisk/branches/10/channels/sip/security_events.c?view=auto&rev=337597
==============================================================================
--- branches/10/channels/sip/security_events.c (added)
+++ branches/10/channels/sip/security_events.c Thu Sep 22 10:47:05 2011
@@ -1,0 +1,398 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2011, Digium, Inc.
+ *
+ * Michael L. Young <elgueromexicano at gmail.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!
+ * \file
+ *
+ * \brief Generate security events in the SIP channel
+ *
+ * \author Michael L. Young <elgueromexicano at gmail.com>
+ */
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "include/sip.h"
+#include "include/security_events.h"
+
+/*! \brief Determine transport type used to receive request*/
+
+static enum ast_security_event_transport_type security_event_get_transport(const struct sip_pvt *p)
+{
+	int res = 0;
+
+	switch (p->socket.type) {
+	case SIP_TRANSPORT_UDP:
+		return AST_SECURITY_EVENT_TRANSPORT_UDP;
+	case SIP_TRANSPORT_TCP:
+		return AST_SECURITY_EVENT_TRANSPORT_TCP;
+	case SIP_TRANSPORT_TLS:
+		return AST_SECURITY_EVENT_TRANSPORT_TLS;
+	}
+
+	return res;
+}
+
+static struct sockaddr_in *security_event_encode_sin_local(const struct sip_pvt *p, struct sockaddr_in *sin_local)
+{
+	ast_sockaddr_to_sin(&p->ourip, sin_local);
+
+	return sin_local;
+}
+
+static struct sockaddr_in *security_event_encode_sin_remote(const struct sip_pvt *p, struct sockaddr_in *sin_remote)
+{
+        ast_sockaddr_to_sin(&p->sa, sin_remote);
+
+        return sin_remote;
+}
+
+void sip_report_invalid_peer(const struct sip_pvt *p)
+{
+	char session_id[32];
+	struct sockaddr_in sin_local;
+	struct sockaddr_in sin_remote;
+
+	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 = {
+			.sin       = security_event_encode_sin_local(p, &sin_local),
+			.transport = security_event_get_transport(p)
+		},
+		.common.remote_addr = {
+			.sin       = security_event_encode_sin_remote(p, &sin_remote),
+			.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));
+}
+
+void sip_report_failed_acl(const struct sip_pvt *p, const char *aclname)
+{
+        char session_id[32];
+        struct sockaddr_in sin_local;
+        struct sockaddr_in sin_remote;
+
+        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  = {
+                        .sin        = security_event_encode_sin_local(p, &sin_local),
+                        .transport  = security_event_get_transport(p)
+                },
+                .common.remote_addr = {
+                        .sin        = security_event_encode_sin_remote(p, &sin_remote),
+                        .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_inval_password(const struct sip_pvt *p, const char *response_challenge, const char *response_hash)
+{
+        char session_id[32];
+        struct sockaddr_in sin_local;
+        struct sockaddr_in sin_remote;
+
+        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  = {
+                        .sin        = security_event_encode_sin_local(p, &sin_local),
+                        .transport  = security_event_get_transport(p)
+                },
+                .common.remote_addr = {
+                        .sin        = security_event_encode_sin_remote(p, &sin_remote),
+                        .transport  = security_event_get_transport(p)
+                },
+                .common.session_id  = session_id,
+
+		.challenge	    = p->randdata,
+		.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_auth_success(const struct sip_pvt *p, uint32_t *using_password)
+{
+        char session_id[32];
+        struct sockaddr_in sin_local;
+        struct sockaddr_in sin_remote;
+
+        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  = {
+                        .sin        = security_event_encode_sin_local(p, &sin_local),
+                        .transport  = security_event_get_transport(p)
+                },
+                .common.remote_addr = {
+                        .sin        = security_event_encode_sin_remote(p, &sin_remote),
+                        .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_session_limit(const struct sip_pvt *p)
+{
+        char session_id[32];
+        struct sockaddr_in sin_local;
+        struct sockaddr_in sin_remote;
+
+        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 = {
+                        .sin       = security_event_encode_sin_local(p, &sin_local),
+                        .transport = security_event_get_transport(p)
+                },
+                .common.remote_addr = {
+                        .sin       = security_event_encode_sin_remote(p, &sin_remote),
+                        .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));
+}
+
+void sip_report_failed_challenge_response(const struct sip_pvt *p, const char *response, const char *expected_response)
+{
+        char session_id[32];
+        struct sockaddr_in sin_local;
+        struct sockaddr_in sin_remote;
+	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 = {
+                        .sin       = security_event_encode_sin_local(p, &sin_local),
+                        .transport = security_event_get_transport(p)
+                },
+                .common.remote_addr = {
+                        .sin       = security_event_encode_sin_remote(p, &sin_remote),
+                        .transport = security_event_get_transport(p)
+                },
+                .common.session_id = session_id,
+
+                .challenge         = p->randdata,
+                .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_chal_sent(const struct sip_pvt *p)
+{
+        char session_id[32];
+        struct sockaddr_in sin_local;
+        struct sockaddr_in sin_remote;
+	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 = {
+                        .sin       = security_event_encode_sin_local(p, &sin_local),
+                        .transport = security_event_get_transport(p)
+                },
+                .common.remote_addr = {
+                        .sin       = security_event_encode_sin_remote(p, &sin_remote),
+                        .transport = security_event_get_transport(p)
+                },
+                .common.session_id = session_id,
+
+                .challenge         = p->randdata,
+        };
+
+	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_inval_transport(const struct sip_pvt *p, const char *transport)
+{
+        char session_id[32];
+        struct sockaddr_in sin_local;
+        struct sockaddr_in sin_remote;
+
+        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 = {
+                        .sin       = security_event_encode_sin_local(p, &sin_local),
+                        .transport = security_event_get_transport(p)
+                },
+                .common.remote_addr = {
+                        .sin       = security_event_encode_sin_remote(p, &sin_remote),
+                        .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));
+}
+
+int sip_report_security_event(const struct sip_pvt *p, const struct sip_request *req, const int res) {
+
+	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_FAKE_AUTH:
+		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;
+}
+

Propchange: branches/10/channels/sip/security_events.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: branches/10/channels/sip/security_events.c
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Rev URL"

Propchange: branches/10/channels/sip/security_events.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain




More information about the asterisk-commits mailing list