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