memory leaks: Memory leak cleanup patch by Corey Farrell (first set)
[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 /*** MODULEINFO
28         <support_level>core</support_level>
29  ***/
30
31 #include "asterisk.h"
32
33 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
34
35 /* #define  REF_DEBUG 1 */
36
37 #include "include/sip.h"
38 #include "include/security_events.h"
39
40 /*! \brief Determine transport type used to receive request*/
41
42 static enum ast_transport security_event_get_transport(const struct sip_pvt *p)
43 {
44         return p->socket.type;
45 }
46
47 void sip_report_invalid_peer(const struct sip_pvt *p)
48 {
49         char session_id[32];
50
51         struct ast_security_event_inval_acct_id inval_acct_id = {
52                 .common.event_type = AST_SECURITY_EVENT_INVAL_ACCT_ID,
53                 .common.version    = AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION,
54                 .common.service    = "SIP",
55                 .common.account_id = p->exten,
56                 .common.local_addr = {
57                         .addr      = &p->ourip,
58                         .transport = security_event_get_transport(p)
59                 },
60                 .common.remote_addr = {
61                         .addr       = &p->sa,
62                         .transport = security_event_get_transport(p)
63                 },
64                 .common.session_id = session_id,
65         };
66
67         snprintf(session_id, sizeof(session_id), "%p", p);
68
69         ast_security_event_report(AST_SEC_EVT(&inval_acct_id));
70 }
71
72 void sip_report_failed_acl(const struct sip_pvt *p, const char *aclname)
73 {
74         char session_id[32];
75
76         struct ast_security_event_failed_acl failed_acl_event = {
77                 .common.event_type  = AST_SECURITY_EVENT_FAILED_ACL,
78                 .common.version     = AST_SECURITY_EVENT_FAILED_ACL_VERSION,
79                 .common.service     = "SIP",
80                 .common.account_id  = p->exten,
81                 .common.local_addr  = {
82                         .addr       = &p->ourip,
83                         .transport  = security_event_get_transport(p)
84                 },
85                 .common.remote_addr = {
86                         .addr       = &p->sa,
87                         .transport  = security_event_get_transport(p)
88                 },
89                 .common.session_id  = session_id,
90                 .acl_name           = aclname,
91         };
92
93         snprintf(session_id, sizeof(session_id), "%p", p);
94
95         ast_security_event_report(AST_SEC_EVT(&failed_acl_event));
96 }
97
98 void sip_report_inval_password(const struct sip_pvt *p, const char *response_challenge, const char *response_hash)
99 {
100         char session_id[32];
101
102         struct ast_security_event_inval_password inval_password = {
103                 .common.event_type  = AST_SECURITY_EVENT_INVAL_PASSWORD,
104                 .common.version     = AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION,
105                 .common.service     = "SIP",
106                 .common.account_id  = p->exten,
107                 .common.local_addr  = {
108                         .addr       = &p->ourip,
109                         .transport  = security_event_get_transport(p)
110                 },
111                 .common.remote_addr = {
112                         .addr       = &p->sa,
113                         .transport  = security_event_get_transport(p)
114                 },
115                 .common.session_id  = session_id,
116
117                 .challenge          = p->nonce,
118                 .received_challenge = response_challenge,
119                 .received_hash      = response_hash,
120         };
121
122         snprintf(session_id, sizeof(session_id), "%p", p);
123
124         ast_security_event_report(AST_SEC_EVT(&inval_password));
125 }
126
127 void sip_report_auth_success(const struct sip_pvt *p, uint32_t *using_password)
128 {
129         char session_id[32];
130
131         struct ast_security_event_successful_auth successful_auth = {
132                 .common.event_type  = AST_SECURITY_EVENT_SUCCESSFUL_AUTH,
133                 .common.version     = AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION,
134                 .common.service     = "SIP",
135                 .common.account_id  = p->exten,
136                 .common.local_addr  = {
137                         .addr       = &p->ourip,
138                         .transport  = security_event_get_transport(p)
139                 },
140                 .common.remote_addr = {
141                         .addr       = &p->sa,
142                         .transport  = security_event_get_transport(p)
143                 },
144                 .common.session_id  = session_id,
145                 .using_password     = using_password,
146         };
147
148         snprintf(session_id, sizeof(session_id), "%p", p);
149
150         ast_security_event_report(AST_SEC_EVT(&successful_auth));
151 }
152
153 void sip_report_session_limit(const struct sip_pvt *p)
154 {
155         char session_id[32];
156
157         struct ast_security_event_session_limit session_limit = {
158                 .common.event_type = AST_SECURITY_EVENT_SESSION_LIMIT,
159                 .common.version    = AST_SECURITY_EVENT_SESSION_LIMIT_VERSION,
160                 .common.service    = "SIP",
161                 .common.account_id = p->exten,
162                 .common.local_addr = {
163                         .addr      = &p->ourip,
164                         .transport = security_event_get_transport(p)
165                 },
166                 .common.remote_addr = {
167                         .addr      = &p->sa,
168                         .transport = security_event_get_transport(p)
169                 },
170                 .common.session_id = session_id,
171         };
172
173         snprintf(session_id, sizeof(session_id), "%p", p);
174
175         ast_security_event_report(AST_SEC_EVT(&session_limit));
176 }
177
178 void sip_report_failed_challenge_response(const struct sip_pvt *p, const char *response, const char *expected_response)
179 {
180         char session_id[32];
181         char account_id[256];
182
183         struct ast_security_event_chal_resp_failed chal_resp_failed = {
184                 .common.event_type = AST_SECURITY_EVENT_CHAL_RESP_FAILED,
185                 .common.version    = AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION,
186                 .common.service    = "SIP",
187                 .common.account_id = account_id,
188                 .common.local_addr = {
189                         .addr      = &p->ourip,
190                         .transport = security_event_get_transport(p)
191                 },
192                 .common.remote_addr = {
193                         .addr      = &p->sa,
194                         .transport = security_event_get_transport(p)
195                 },
196                 .common.session_id = session_id,
197
198                 .challenge         = p->nonce,
199                 .response          = response,
200                 .expected_response = expected_response,
201         };
202
203         if (!ast_strlen_zero(p->from)) { /* When dialing, show account making call */
204                 ast_copy_string(account_id, p->from, sizeof(account_id));
205         } else {
206                 ast_copy_string(account_id, p->exten, sizeof(account_id));
207         }
208
209         snprintf(session_id, sizeof(session_id), "%p", p);
210
211         ast_security_event_report(AST_SEC_EVT(&chal_resp_failed));
212 }
213
214 void sip_report_chal_sent(const struct sip_pvt *p)
215 {
216         char session_id[32];
217         char account_id[256];
218
219         struct ast_security_event_chal_sent chal_sent = {
220                 .common.event_type = AST_SECURITY_EVENT_CHAL_SENT,
221                 .common.version    = AST_SECURITY_EVENT_CHAL_SENT_VERSION,
222                 .common.service    = "SIP",
223                 .common.account_id = account_id,
224                 .common.local_addr = {
225                         .addr      = &p->ourip,
226                         .transport = security_event_get_transport(p)
227                 },
228                 .common.remote_addr = {
229                         .addr      = &p->sa,
230                         .transport = security_event_get_transport(p)
231                 },
232                 .common.session_id = session_id,
233
234                 .challenge         = p->nonce,
235         };
236
237         if (!ast_strlen_zero(p->from)) { /* When dialing, show account making call */
238                 ast_copy_string(account_id, p->from, sizeof(account_id));
239         } else {
240                 ast_copy_string(account_id, p->exten, sizeof(account_id));
241         }
242
243         snprintf(session_id, sizeof(session_id), "%p", p);
244
245         ast_security_event_report(AST_SEC_EVT(&chal_sent));
246 }
247
248 void sip_report_inval_transport(const struct sip_pvt *p, const char *transport)
249 {
250         char session_id[32];
251
252         struct ast_security_event_inval_transport inval_transport = {
253                 .common.event_type = AST_SECURITY_EVENT_INVAL_TRANSPORT,
254                 .common.version    = AST_SECURITY_EVENT_INVAL_TRANSPORT_VERSION,
255                 .common.service    = "SIP",
256                 .common.account_id = p->exten,
257                 .common.local_addr = {
258                         .addr      = &p->ourip,
259                         .transport = security_event_get_transport(p)
260                 },
261                 .common.remote_addr = {
262                         .addr      = &p->sa,
263                         .transport = security_event_get_transport(p)
264                 },
265                 .common.session_id = session_id,
266
267                 .transport         = transport,
268         };
269
270         snprintf(session_id, sizeof(session_id), "%p", p);
271
272         ast_security_event_report(AST_SEC_EVT(&inval_transport));
273 }
274
275 int sip_report_security_event(const struct sip_pvt *p, const struct sip_request *req, const int res) {
276
277         struct sip_peer *peer_report;
278         enum check_auth_result res_report = res;
279         struct ast_str *buf;
280         char *c;
281         const char *authtoken;
282         char *reqheader, *respheader;
283         int result = 0;
284         char aclname[256];
285         struct digestkeys keys[] = {
286                 [K_RESP]  = { "response=", "" },
287                 [K_URI]   = { "uri=", "" },
288                 [K_USER]  = { "username=", "" },
289                 [K_NONCE] = { "nonce=", "" },
290                 [K_LAST]  = { NULL, NULL}
291         };
292
293         peer_report = sip_find_peer(p->exten, NULL, TRUE, FINDPEERS, FALSE, 0);
294
295         switch(res_report) {
296         case AUTH_DONT_KNOW:
297                 break;
298         case AUTH_SUCCESSFUL:
299                 if (peer_report) {
300                         if (ast_strlen_zero(peer_report->secret) && ast_strlen_zero(peer_report->md5secret)) {
301                         sip_report_auth_success(p, (uint32_t *) 0);
302                         } else {
303                                 sip_report_auth_success(p, (uint32_t *) 1);
304                         }
305                 }
306                 break;
307         case AUTH_CHALLENGE_SENT:
308                 sip_report_chal_sent(p);
309                 break;
310         case AUTH_SECRET_FAILED:
311         case AUTH_USERNAME_MISMATCH:
312                 sip_auth_headers(WWW_AUTH, &respheader, &reqheader);
313                 authtoken = sip_get_header(req, reqheader);
314                 buf = ast_str_thread_get(&check_auth_buf, CHECK_AUTH_BUF_INITLEN);
315                 ast_str_set(&buf, 0, "%s", authtoken);
316                 c = buf->str;
317
318                 sip_digest_parser(c, keys);
319
320                 if (res_report == AUTH_SECRET_FAILED) {
321                         sip_report_inval_password(p, keys[K_NONCE].s, keys[K_RESP].s);
322                 } else {
323                         if (peer_report) {
324                                 sip_report_failed_challenge_response(p, keys[K_USER].s, peer_report->username);
325                         }
326                 }
327                 break;
328         case AUTH_NOT_FOUND:
329                 /* with sip_cfg.alwaysauthreject on, generates 2 events */
330                 sip_report_invalid_peer(p);
331                 break;
332         case AUTH_UNKNOWN_DOMAIN:
333                 snprintf(aclname, sizeof(aclname), "domain_must_match");
334                 sip_report_failed_acl(p, aclname);
335                 break;
336         case AUTH_PEER_NOT_DYNAMIC:
337                 snprintf(aclname, sizeof(aclname), "peer_not_dynamic");
338                 sip_report_failed_acl(p, aclname);
339                 break;
340         case AUTH_ACL_FAILED:
341                 /* with sip_cfg.alwaysauthreject on, generates 2 events */
342                 snprintf(aclname, sizeof(aclname), "device_must_match_acl");
343                 sip_report_failed_acl(p, aclname);
344                 break;
345         case AUTH_BAD_TRANSPORT:
346                 sip_report_inval_transport(p, sip_get_transport(req->socket.type));
347                 break;
348         case AUTH_RTP_FAILED:
349                 break;
350         case AUTH_SESSION_LIMIT:
351                 sip_report_session_limit(p);
352                 break;
353         }
354
355         if (peer_report) {
356                 sip_unref_peer(peer_report, "sip_report_security_event: sip_unref_peer: from handle_incoming");
357         }
358
359         return result;
360 }
361