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