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