Asterisk - The Open Source Telephony Project  18.5.0
res/res_pjsip/security_events.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013, Digium, Inc.
5  *
6  * Joshua Colp <[email protected]>
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 PJSIP channel
23  *
24  * \author Joshua Colp <[email protected]>
25  */
26 
27 #include "asterisk.h"
28 
29 #include <pjsip.h>
30 
31 #include "asterisk/res_pjsip.h"
33 
34 static enum ast_transport security_event_get_transport(pjsip_rx_data *rdata)
35 {
36  if (rdata->tp_info.transport->key.type == PJSIP_TRANSPORT_UDP ||
37  rdata->tp_info.transport->key.type == PJSIP_TRANSPORT_UDP6) {
38  return AST_TRANSPORT_UDP;
39  } else if (rdata->tp_info.transport->key.type == PJSIP_TRANSPORT_TCP ||
40  rdata->tp_info.transport->key.type == PJSIP_TRANSPORT_TCP6) {
41  return AST_TRANSPORT_TCP;
42  } else if (rdata->tp_info.transport->key.type == PJSIP_TRANSPORT_TLS ||
43  rdata->tp_info.transport->key.type == PJSIP_TRANSPORT_TLS6) {
44  return AST_TRANSPORT_TLS;
45  } else if (!strcasecmp(rdata->tp_info.transport->type_name, "WS")) {
46  return AST_TRANSPORT_WS;
47  } else if (!strcasecmp(rdata->tp_info.transport->type_name, "WSS")) {
48  return AST_TRANSPORT_WSS;
49  } else {
50  return 0;
51  }
52 }
53 
54 static void security_event_populate(pjsip_rx_data *rdata, char *call_id, size_t call_id_size, struct ast_sockaddr *local, struct ast_sockaddr *remote)
55 {
56  char host[NI_MAXHOST];
57 
58  ast_copy_pj_str(call_id, &rdata->msg_info.cid->id, call_id_size);
59 
60  ast_copy_pj_str(host, &rdata->tp_info.transport->local_name.host, sizeof(host));
62  ast_sockaddr_set_port(local, rdata->tp_info.transport->local_name.port);
63 
64  ast_sockaddr_parse(remote, rdata->pkt_info.src_name, PARSE_PORT_FORBID);
65  ast_sockaddr_set_port(remote, rdata->pkt_info.src_port);
66 }
67 
68 static const char *get_account_id(struct ast_sip_endpoint *endpoint)
69 {
71 
72  return endpoint == artificial ? "<unknown>" : ast_sorcery_object_get_id(endpoint);
73 }
74 
75 void ast_sip_report_invalid_endpoint(const char *name, pjsip_rx_data *rdata)
76 {
77  enum ast_transport transport = security_event_get_transport(rdata);
78  char call_id[pj_strlen(&rdata->msg_info.cid->id) + 1];
79  struct ast_sockaddr local, remote;
80 
81  struct ast_security_event_inval_acct_id inval_acct_id = {
84  .common.service = "PJSIP",
85  .common.account_id = name,
86  .common.local_addr = {
87  .addr = &local,
88  .transport = transport,
89  },
90  .common.remote_addr = {
91  .addr = &remote,
92  .transport = transport,
93  },
94  .common.session_id = call_id,
95  };
96 
97  security_event_populate(rdata, call_id, sizeof(call_id), &local, &remote);
98 
99  ast_security_event_report(AST_SEC_EVT(&inval_acct_id));
100 }
101 
102 void ast_sip_report_failed_acl(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, const char *name)
103 {
104  enum ast_transport transport = security_event_get_transport(rdata);
105  char call_id[pj_strlen(&rdata->msg_info.cid->id) + 1];
106  struct ast_sockaddr local, remote;
107 
108  struct ast_security_event_failed_acl failed_acl_event = {
110  .common.version = AST_SECURITY_EVENT_FAILED_ACL_VERSION,
111  .common.service = "PJSIP",
112  .common.account_id = get_account_id(endpoint),
113  .common.local_addr = {
114  .addr = &local,
115  .transport = transport,
116  },
117  .common.remote_addr = {
118  .addr = &remote,
119  .transport = transport,
120  },
121  .common.session_id = call_id,
122  .acl_name = name,
123  };
124 
125  security_event_populate(rdata, call_id, sizeof(call_id), &local, &remote);
126 
127  ast_security_event_report(AST_SEC_EVT(&failed_acl_event));
128 }
129 
130 void ast_sip_report_auth_failed_challenge_response(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
131 {
132  pjsip_authorization_hdr *auth = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_AUTHORIZATION, NULL);
133  enum ast_transport transport = security_event_get_transport(rdata);
134  char call_id[pj_strlen(&rdata->msg_info.cid->id) + 1];
135  char nonce[64] = "", response[256] = "";
136  struct ast_sockaddr local, remote;
137 
138  struct ast_security_event_chal_resp_failed chal_resp_failed = {
141  .common.service = "PJSIP",
142  .common.account_id = get_account_id(endpoint),
143  .common.local_addr = {
144  .addr = &local,
145  .transport = transport,
146  },
147  .common.remote_addr = {
148  .addr = &remote,
149  .transport = transport,
150  },
151  .common.session_id = call_id,
152 
153  .challenge = nonce,
154  .response = response,
155  .expected_response = "",
156  };
157 
158  if (auth && !pj_strcmp2(&auth->scheme, "Digest")) {
159  ast_copy_pj_str(nonce, &auth->credential.digest.nonce, sizeof(nonce));
160  ast_copy_pj_str(response, &auth->credential.digest.response, sizeof(response));
161  }
162 
163  security_event_populate(rdata, call_id, sizeof(call_id), &local, &remote);
164 
165  ast_security_event_report(AST_SEC_EVT(&chal_resp_failed));
166 }
167 
168 void ast_sip_report_auth_success(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
169 {
170  pjsip_authorization_hdr *auth = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_AUTHORIZATION, NULL);
171  enum ast_transport transport = security_event_get_transport(rdata);
172  char call_id[pj_strlen(&rdata->msg_info.cid->id) + 1];
173  struct ast_sockaddr local, remote;
174 
175  struct ast_security_event_successful_auth successful_auth = {
178  .common.service = "PJSIP",
179  .common.account_id = get_account_id(endpoint),
180  .common.local_addr = {
181  .addr = &local,
182  .transport = transport,
183  },
184  .common.remote_addr = {
185  .addr = &remote,
186  .transport = transport,
187  },
188  .common.session_id = call_id,
189  .using_password = auth ? 1 : 0,
190  };
191 
192  security_event_populate(rdata, call_id, sizeof(call_id), &local, &remote);
193 
194  ast_security_event_report(AST_SEC_EVT(&successful_auth));
195 }
196 
197 void ast_sip_report_auth_challenge_sent(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pjsip_tx_data *tdata)
198 {
199  pjsip_www_authenticate_hdr *auth = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_WWW_AUTHENTICATE, NULL);
200  enum ast_transport transport = security_event_get_transport(rdata);
201  char nonce[64] = "", call_id[pj_strlen(&rdata->msg_info.cid->id) + 1];
202  struct ast_sockaddr local, remote;
203 
204  struct ast_security_event_chal_sent chal_sent = {
206  .common.version = AST_SECURITY_EVENT_CHAL_SENT_VERSION,
207  .common.service = "PJSIP",
208  .common.account_id = get_account_id(endpoint),
209  .common.local_addr = {
210  .addr = &local,
211  .transport = transport,
212  },
213  .common.remote_addr = {
214  .addr = &remote,
215  .transport = transport,
216  },
217  .common.session_id = call_id,
218  .challenge = nonce,
219  };
220 
221  if (auth && !pj_strcmp2(&auth->scheme, "digest")) {
222  ast_copy_pj_str(nonce, &auth->challenge.digest.nonce, sizeof(nonce));
223  }
224 
225  security_event_populate(rdata, call_id, sizeof(call_id), &local, &remote);
226 
228 }
229 
230 void ast_sip_report_req_no_support(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata,
231  const char* req_type)
232 {
233  enum ast_transport transport = security_event_get_transport(rdata);
234  char call_id[pj_strlen(&rdata->msg_info.cid->id) + 1];
235  struct ast_sockaddr local, remote;
236 
237  struct ast_security_event_req_no_support req_no_support_event = {
240  .common.service = "PJSIP",
241  .common.account_id = get_account_id(endpoint),
242  .common.local_addr = {
243  .addr = &local,
244  .transport = transport,
245  },
246  .common.remote_addr = {
247  .addr = &remote,
248  .transport = transport,
249  },
250  .common.session_id = call_id,
251  .request_type = req_type
252  };
253 
254  security_event_populate(rdata, call_id, sizeof(call_id), &local, &remote);
255 
256  ast_security_event_report(AST_SEC_EVT(&req_no_support_event));
257 }
258 
259 void ast_sip_report_mem_limit(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
260 {
261  enum ast_transport transport = security_event_get_transport(rdata);
262  char call_id[pj_strlen(&rdata->msg_info.cid->id) + 1];
263  struct ast_sockaddr local, remote;
264 
265  struct ast_security_event_mem_limit mem_limit_event = {
267  .common.version = AST_SECURITY_EVENT_MEM_LIMIT_VERSION,
268  .common.service = "PJSIP",
269  .common.account_id = get_account_id(endpoint),
270  .common.local_addr = {
271  .addr = &local,
272  .transport = transport,
273  },
274  .common.remote_addr = {
275  .addr = &remote,
276  .transport = transport,
277  },
278  .common.session_id = call_id
279  };
280 
281  security_event_populate(rdata, call_id, sizeof(call_id), &local, &remote);
282 
283  ast_security_event_report(AST_SEC_EVT(&mem_limit_event));
284 }
void ast_sip_report_auth_failed_challenge_response(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
Send a security event notification for when a challenge response has failed.
struct ast_security_event_common common
Common security event descriptor elements.
enum ast_security_event_type event_type
The security event sub-type.
Asterisk main include file. File version handling, generic pbx functions.
FYI FWIW, Successful authentication has occurred.
Security Event Reporting API.
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
#define AST_SECURITY_EVENT_REQ_NO_SUPPORT_VERSION
Event descriptor version.
void ast_sip_report_auth_success(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
Send a security event notification for when authentication succeeds.
An attempt at challenge/response auth failed.
ast_transport
Definition: netsock2.h:59
#define AST_SECURITY_EVENT_CHAL_SENT_VERSION
Event descriptor version.
Request denied because we don&#39;t support it.
Checking against an IP access control list failed.
struct ast_security_event_common common
Common security event descriptor elements.
A challenge was sent out.
const char * response
Response received.
void ast_sip_report_req_no_support(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, const char *req_type)
Send a security event notification for when a request is not supported.
struct ast_security_event_common common
Common security event descriptor elements.
void ast_copy_pj_str(char *dest, const pj_str_t *src, size_t size)
Copy a pj_str_t into a standard character buffer.
Definition: res_pjsip.c:5240
#define NULL
Definition: resample.c:96
#define AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION
Event descriptor version.
Socket address structure.
Definition: netsock2.h:97
#define AST_SEC_EVT(e)
void ast_sip_report_auth_challenge_sent(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pjsip_tx_data *tdata)
Send a security event notification for when an authentication challenge is sent.
static char host[256]
Definition: muted.c:77
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
#define AST_SECURITY_EVENT_FAILED_ACL_VERSION
Event descriptor version.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
Challenge was sent out, informational.
static enum ast_transport security_event_get_transport(pjsip_rx_data *rdata)
struct ast_security_event_common common
Common security event descriptor elements.
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
#define AST_SECURITY_EVENT_MEM_LIMIT_VERSION
Event descriptor version.
#define AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION
Event descriptor version.
Request denied because of a memory limit.
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:537
struct ast_security_event_common common
Common security event descriptor elements.
An attempt at challenge/response authentication failed.
struct ast_sip_endpoint * ast_sip_get_artificial_endpoint(void)
Retrieves a reference to the artificial endpoint.
void ast_sip_report_failed_acl(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, const char *name)
Send a security event notification for when an ACL check fails.
static const char name[]
Definition: cdr_mysql.c:74
struct ast_security_event_common common
Common security event descriptor elements.
Invalid account ID specified (invalid username, for example)
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ast_security_event_common common
Common security event descriptor elements.
void ast_sip_report_mem_limit(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
Send a security event notification for when a memory limit is hit.
void ast_sip_report_invalid_endpoint(const char *name, pjsip_rx_data *rdata)
Send a security event notification for when an invalid endpoint is requested.
#define AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION
Event descriptor version.
static void security_event_populate(pjsip_rx_data *rdata, char *call_id, size_t call_id_size, struct ast_sockaddr *local, struct ast_sockaddr *remote)
int ast_security_event_report(const struct ast_security_event_common *sec)
Report a security event.
static const char * get_account_id(struct ast_sip_endpoint *endpoint)
A request was made that we understand, but do not support.