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