Add IPv6 address support to security events framework.
[asterisk/asterisk.git] / channels / sip / security_events.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2012, Digium, Inc.
5  *
6  * Michael L. Young <elgueromexicano@gmail.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*!
20  * \file
21  *
22  * \brief Generate security events in the SIP channel
23  *
24  * \author Michael L. Young <elgueromexicano@gmail.com>
25  */
26
27 #include "asterisk.h"
28
29 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
30
31 #include "include/sip.h"
32 #include "include/security_events.h"
33
34 /*! \brief Determine transport type used to receive request*/
35
36 static enum ast_security_event_transport_type security_event_get_transport(const struct sip_pvt *p)
37 {
38         int res = 0;
39
40         switch (p->socket.type) {
41         case SIP_TRANSPORT_UDP:
42                 return AST_SECURITY_EVENT_TRANSPORT_UDP;
43         case SIP_TRANSPORT_TCP:
44                 return AST_SECURITY_EVENT_TRANSPORT_TCP;
45         case SIP_TRANSPORT_TLS:
46                 return AST_SECURITY_EVENT_TRANSPORT_TLS;
47         }
48
49         return res;
50 }
51
52 void sip_report_invalid_peer(const struct sip_pvt *p)
53 {
54         char session_id[32];
55
56         struct ast_security_event_inval_acct_id inval_acct_id = {
57                 .common.event_type = AST_SECURITY_EVENT_INVAL_ACCT_ID,
58                 .common.version    = AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION,
59                 .common.service    = "SIP",
60                 .common.account_id = p->exten,
61                 .common.local_addr = {
62                         .addr      = &p->ourip,
63                         .transport = security_event_get_transport(p)
64                 },
65                 .common.remote_addr = {
66                         .addr       = &p->sa,
67                         .transport = security_event_get_transport(p)
68                 },
69                 .common.session_id = session_id,
70         };
71
72         snprintf(session_id, sizeof(session_id), "%p", p);
73
74         ast_security_event_report(AST_SEC_EVT(&inval_acct_id));
75 }
76
77 void sip_report_failed_acl(const struct sip_pvt *p, const char *aclname)
78 {
79         char session_id[32];
80
81         struct ast_security_event_failed_acl failed_acl_event = {
82                 .common.event_type  = AST_SECURITY_EVENT_FAILED_ACL,
83                 .common.version     = AST_SECURITY_EVENT_FAILED_ACL_VERSION,
84                 .common.service     = "SIP",
85                 .common.account_id  = p->exten,
86                 .common.local_addr  = {
87                         .addr       = &p->ourip,
88                         .transport  = security_event_get_transport(p)
89                 },
90                 .common.remote_addr = {
91                         .addr       = &p->sa,
92                         .transport  = security_event_get_transport(p)
93                 },
94                 .common.session_id  = session_id,
95                 .acl_name           = aclname,
96         };
97
98         snprintf(session_id, sizeof(session_id), "%p", p);
99
100         ast_security_event_report(AST_SEC_EVT(&failed_acl_event));
101 }
102
103 void sip_report_inval_password(const struct sip_pvt *p, const char *response_challenge, const char *response_hash)
104 {
105         char session_id[32];
106
107         struct ast_security_event_inval_password inval_password = {
108                 .common.event_type  = AST_SECURITY_EVENT_INVAL_PASSWORD,
109                 .common.version     = AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION,
110                 .common.service     = "SIP",
111                 .common.account_id  = p->exten,
112                 .common.local_addr  = {
113                         .addr       = &p->ourip,
114                         .transport  = security_event_get_transport(p)
115                 },
116                 .common.remote_addr = {
117                         .addr       = &p->sa,
118                         .transport  = security_event_get_transport(p)
119                 },
120                 .common.session_id  = session_id,
121
122                 .challenge          = p->randdata,
123                 .received_challenge = response_challenge,
124                 .received_hash      = response_hash,
125         };
126
127         snprintf(session_id, sizeof(session_id), "%p", p);
128
129         ast_security_event_report(AST_SEC_EVT(&inval_password));
130 }
131
132 void sip_report_auth_success(const struct sip_pvt *p, uint32_t *using_password)
133 {
134         char session_id[32];
135
136         struct ast_security_event_successful_auth successful_auth = {
137                 .common.event_type  = AST_SECURITY_EVENT_SUCCESSFUL_AUTH,
138                 .common.version     = AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION,
139                 .common.service     = "SIP",
140                 .common.account_id  = p->exten,
141                 .common.local_addr  = {
142                         .addr       = &p->ourip,
143                         .transport  = security_event_get_transport(p)
144                 },
145                 .common.remote_addr = {
146                         .addr       = &p->sa,
147                         .transport  = security_event_get_transport(p)
148                 },
149                 .common.session_id  = session_id,
150                 .using_password     = using_password,
151         };
152
153         snprintf(session_id, sizeof(session_id), "%p", p);
154
155         ast_security_event_report(AST_SEC_EVT(&successful_auth));
156 }
157
158 void sip_report_session_limit(const struct sip_pvt *p)
159 {
160         char session_id[32];
161
162         struct ast_security_event_session_limit session_limit = {
163                 .common.event_type = AST_SECURITY_EVENT_SESSION_LIMIT,
164                 .common.version    = AST_SECURITY_EVENT_SESSION_LIMIT_VERSION,
165                 .common.service    = "SIP",
166                 .common.account_id = p->exten,
167                 .common.local_addr = {
168                         .addr      = &p->ourip,
169                         .transport = security_event_get_transport(p)
170                 },
171                 .common.remote_addr = {
172                         .addr      = &p->sa,
173                         .transport = security_event_get_transport(p)
174                 },
175                 .common.session_id = session_id,
176         };
177
178         snprintf(session_id, sizeof(session_id), "%p", p);
179
180         ast_security_event_report(AST_SEC_EVT(&session_limit));
181 }
182
183 void sip_report_failed_challenge_response(const struct sip_pvt *p, const char *response, const char *expected_response)
184 {
185         char session_id[32];
186         char account_id[256];
187
188         struct ast_security_event_chal_resp_failed chal_resp_failed = {
189                 .common.event_type = AST_SECURITY_EVENT_CHAL_RESP_FAILED,
190                 .common.version    = AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION,
191                 .common.service    = "SIP",
192                 .common.account_id = account_id,
193                 .common.local_addr = {
194                         .addr      = &p->ourip,
195                         .transport = security_event_get_transport(p)
196                 },
197                 .common.remote_addr = {
198                         .addr      = &p->sa,
199                         .transport = security_event_get_transport(p)
200                 },
201                 .common.session_id = session_id,
202
203                 .challenge         = p->randdata,
204                 .response          = response,
205                 .expected_response = expected_response,
206         };
207
208         if (!ast_strlen_zero(p->from)) { /* When dialing, show account making call */
209                 ast_copy_string(account_id, p->from, sizeof(account_id));
210         } else {
211                 ast_copy_string(account_id, p->exten, sizeof(account_id));
212         }
213
214         snprintf(session_id, sizeof(session_id), "%p", p);
215
216         ast_security_event_report(AST_SEC_EVT(&chal_resp_failed));
217 }
218
219 void sip_report_chal_sent(const struct sip_pvt *p)
220 {
221         char session_id[32];
222         char account_id[256];
223
224         struct ast_security_event_chal_sent chal_sent = {
225                 .common.event_type = AST_SECURITY_EVENT_CHAL_SENT,
226                 .common.version    = AST_SECURITY_EVENT_CHAL_SENT_VERSION,
227                 .common.service    = "SIP",
228                 .common.account_id = account_id,
229                 .common.local_addr = {
230                         .addr      = &p->ourip,
231                         .transport = security_event_get_transport(p)
232                 },
233                 .common.remote_addr = {
234                         .addr      = &p->sa,
235                         .transport = security_event_get_transport(p)
236                 },
237                 .common.session_id = session_id,
238
239                 .challenge         = p->randdata,
240         };
241
242         if (!ast_strlen_zero(p->from)) { /* When dialing, show account making call */
243                 ast_copy_string(account_id, p->from, sizeof(account_id));
244         } else {
245                 ast_copy_string(account_id, p->exten, sizeof(account_id));
246         }
247
248         snprintf(session_id, sizeof(session_id), "%p", p);
249
250         ast_security_event_report(AST_SEC_EVT(&chal_sent));
251 }
252
253 void sip_report_inval_transport(const struct sip_pvt *p, const char *transport)
254 {
255         char session_id[32];
256
257         struct ast_security_event_inval_transport inval_transport = {
258                 .common.event_type = AST_SECURITY_EVENT_INVAL_TRANSPORT,
259                 .common.version    = AST_SECURITY_EVENT_INVAL_TRANSPORT_VERSION,
260                 .common.service    = "SIP",
261                 .common.account_id = p->exten,
262                 .common.local_addr = {
263                         .addr      = &p->ourip,
264                         .transport = security_event_get_transport(p)
265                 },
266                 .common.remote_addr = {
267                         .addr      = &p->sa,
268                         .transport = security_event_get_transport(p)
269                 },
270                 .common.session_id = session_id,
271
272                 .transport         = transport,
273         };
274
275         snprintf(session_id, sizeof(session_id), "%p", p);
276
277         ast_security_event_report(AST_SEC_EVT(&inval_transport));
278 }
279
280 int sip_report_security_event(const struct sip_pvt *p, const struct sip_request *req, const int res) {
281
282         struct sip_peer *peer_report;
283         enum check_auth_result res_report = res;
284         struct ast_str *buf;
285         char *c;
286         const char *authtoken;
287         char *reqheader, *respheader;
288         int result = 0;
289         char aclname[256];
290         struct digestkeys keys[] = {
291                 [K_RESP]  = { "response=", "" },
292                 [K_URI]   = { "uri=", "" },
293                 [K_USER]  = { "username=", "" },
294                 [K_NONCE] = { "nonce=", "" },
295                 [K_LAST]  = { NULL, NULL}
296         };
297
298         peer_report = sip_find_peer(p->exten, NULL, TRUE, FINDPEERS, FALSE, 0);
299
300         switch(res_report) {
301         case AUTH_DONT_KNOW:
302                 break;
303         case AUTH_SUCCESSFUL:
304                 if (peer_report) {
305                         if (ast_strlen_zero(peer_report->secret) && ast_strlen_zero(peer_report->md5secret)) {
306                         sip_report_auth_success(p, (uint32_t *) 0);
307                         } else {
308                                 sip_report_auth_success(p, (uint32_t *) 1);
309                         }
310                 }
311                 break;
312         case AUTH_CHALLENGE_SENT:
313                 sip_report_chal_sent(p);
314                 break;
315         case AUTH_SECRET_FAILED:
316         case AUTH_USERNAME_MISMATCH:
317                 sip_auth_headers(WWW_AUTH, &respheader, &reqheader);
318                 authtoken = sip_get_header(req, reqheader);
319                 buf = ast_str_thread_get(&check_auth_buf, CHECK_AUTH_BUF_INITLEN);
320                 ast_str_set(&buf, 0, "%s", authtoken);
321                 c = buf->str;
322
323                 sip_digest_parser(c, keys);
324
325                 if (res_report == AUTH_SECRET_FAILED) {
326                         sip_report_inval_password(p, keys[K_NONCE].s, keys[K_RESP].s);
327                 } else {
328                         if (peer_report) {
329                                 sip_report_failed_challenge_response(p, keys[K_USER].s, peer_report->username);
330                         }
331                 }
332                 break;
333         case AUTH_NOT_FOUND:
334                 /* with sip_cfg.alwaysauthreject on, generates 2 events */
335                 sip_report_invalid_peer(p);
336                 break;
337         case AUTH_FAKE_AUTH:
338                 sip_report_invalid_peer(p);
339                 break;
340         case AUTH_UNKNOWN_DOMAIN:
341                 snprintf(aclname, sizeof(aclname), "domain_must_match");
342                 sip_report_failed_acl(p, aclname);
343                 break;
344         case AUTH_PEER_NOT_DYNAMIC:
345                 snprintf(aclname, sizeof(aclname), "peer_not_dynamic");
346                 sip_report_failed_acl(p, aclname);
347                 break;
348         case AUTH_ACL_FAILED:
349                 /* with sip_cfg.alwaysauthreject on, generates 2 events */
350                 snprintf(aclname, sizeof(aclname), "device_must_match_acl");
351                 sip_report_failed_acl(p, aclname);
352                 break;
353         case AUTH_BAD_TRANSPORT:
354                 sip_report_inval_transport(p, sip_get_transport(req->socket.type));
355                 break;
356         case AUTH_RTP_FAILED:
357                 break;
358         case AUTH_SESSION_LIMIT:
359                 sip_report_session_limit(p);
360                 break;
361         }
362
363         if (peer_report) {
364                 sip_unref_peer(peer_report, "sip_report_security_event: sip_unref_peer: from handle_incoming");
365         }
366
367         return result;
368 }
369