29 #include "asterisk/res_pjsip.h"
129 memset(&addr, 0,
sizeof(addr));
133 if (
ast_apply_acl(acl, &addr,
"SIP ACL: ") != AST_SENSE_ALLOW) {
134 ast_log(LOG_WARNING,
"Incoming SIP message from %s did not pass ACL test\n",
ast_sockaddr_stringify(&addr));
140 static int extract_contact_addr(pjsip_contact_hdr *contact,
struct ast_sockaddr **addrs)
142 pjsip_sip_uri *sip_uri;
145 if (!contact || contact->star) {
149 if (!PJSIP_URI_SCHEME_IS_SIP(contact->uri) && !PJSIP_URI_SCHEME_IS_SIPS(contact->uri)) {
153 sip_uri = pjsip_uri_get_uri(contact->uri);
154 ast_copy_pj_str(host, &sip_uri->host,
sizeof(host));
158 static int apply_contact_acl(pjsip_rx_data *rdata,
struct ast_acl_list *contact_acl)
160 int num_contact_addrs;
164 pjsip_contact_hdr *contact = (pjsip_contact_hdr *)&rdata->msg_info.msg->hdr;
170 while ((contact = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, contact->next))) {
171 num_contact_addrs = extract_contact_addr(contact, &contact_addrs);
172 if (num_contact_addrs <= 0) {
175 for (i = 0; i < num_contact_addrs; ++i) {
176 if (
ast_apply_acl(contact_acl, &contact_addrs[i],
"SIP Contact ACL: ") != AST_SENSE_ALLOW) {
177 ast_log(LOG_WARNING,
"Incoming SIP message from %s did not pass ACL test\n",
ast_sockaddr_stringify(&contact_addrs[i]));
182 ast_free(contact_addrs);
192 #define SIP_SORCERY_ACL_TYPE "acl"
198 SORCERY_OBJECT(details);
203 static int check_acls(
void *obj,
void *arg,
int flags)
206 pjsip_rx_data *rdata = arg;
208 if (apply_acl(rdata, sip_acl->acl) ||
209 apply_contact_acl(rdata, sip_acl->contact_acl)) {
215 static pj_bool_t acl_on_rx_msg(pjsip_rx_data *rdata)
218 ast_sip_get_sorcery(), SIP_SORCERY_ACL_TYPE,
223 ast_log(LOG_ERROR,
"Unable to retrieve ACL sorcery data\n");
227 if ((matched_acl =
ao2_callback(acls, 0, check_acls, rdata))) {
228 if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) {
229 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 403, NULL, NULL, NULL);
243 if (!strncmp(var->
name,
"contact_", 8)) {
246 ast_log(LOG_ERROR,
"Bad contact ACL '%s' at line '%d' of pjsip.conf\n",
247 var->
value, var->lineno);
252 ast_log(LOG_ERROR,
"Bad ACL '%s' at line '%d' of pjsip.conf\n",
253 var->
value, var->lineno);
258 ast_log(LOG_ERROR,
"There is an error in ACL configuration. Blocking ALL SIP traffic.\n");
259 ast_append_acl(
"deny",
"0.0.0.0/0.0.0.0", &sip_acl->acl, NULL, &ignore);
265 static pjsip_module acl_module = {
266 .name = {
"ACL Module", 14 },
269 .on_rx_request = acl_on_rx_msg,
272 static void acl_destroy(
void *obj)
279 static void *acl_alloc(
const char *name)
297 static int load_module(
void)
299 ast_sorcery_apply_config(ast_sip_get_sorcery(), SIP_SORCERY_ACL_TYPE);
300 ast_sorcery_apply_default(ast_sip_get_sorcery(), SIP_SORCERY_ACL_TYPE,
301 "config",
"pjsip.conf,criteria=type=acl");
304 acl_alloc, NULL, NULL)) {
306 ast_log(LOG_ERROR,
"Failed to register SIP %s object with sorcery\n",
307 SIP_SORCERY_ACL_TYPE);
325 ast_sip_register_service(&acl_module);
330 static int unload_module(
void)
333 ast_sip_unregister_service(&acl_module);
337 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER,
"PJSIP ACL Resource",
338 .support_level = AST_MODULE_SUPPORT_CORE,
340 .unload = unload_module,
342 .requires =
"res_pjsip",
Security Event Reporting API.
Asterisk main include file. File version handling, generic pbx functions.
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
void ast_sorcery_force_reload_object(const struct ast_sorcery *sorcery, const char *type)
Inform any wizards of a specific object type to reload persistent objects even if no changes determin...
Stasis Message Bus API. See Stasis Message Bus API for detailed documentation.
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.
Structure for variables, used for configurations and for channel variables.
Perform no matching, return all objects.
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
Type for a default handler that should do nothing.
int stasis_subscription_set_filter(struct stasis_subscription *subscription, enum stasis_subscription_message_filter filter)
Set the message type filtering level on a subscription.
struct stasis_message_type * ast_named_acl_change_type(void)
a stasis_message_type for changes against a named ACL or the set of all named ACLs ...
Return all matching objects.
Wrapper for an ast_acl linked list.
void ast_sorcery_load_object(const struct ast_sorcery *sorcery, const char *type)
Inform any wizards of a specific object type to load persistent objects.
Socket address structure.
#define ast_sorcery_object_field_register_custom(sorcery, type, name, default_val, config_handler, sorcery_handler, multiple_handler, flags,...)
Register a field within an object with custom handlers.
Access Control of various sorts.
#define ast_sorcery_object_register(sorcery, type, alloc, transform, apply)
Register an object type.
enum ast_acl_sense ast_apply_acl(struct ast_acl_list *acl_list, const struct ast_sockaddr *addr, const char *purpose)
Apply a set of rules to a given IP address.
int ast_acl_list_is_empty(struct ast_acl_list *acl_list)
Determines if an ACL is empty or if it contains entries.
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
struct ast_acl_list * ast_free_acl_list(struct ast_acl_list *acl)
Free a list of ACLs.
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Support for logging to various files, console and syslog Configuration in file logger.conf.
struct stasis_subscription * stasis_unsubscribe_and_join(struct stasis_subscription *subscription)
Cancel a subscription, blocking until the last message is processed.
Module has failed to load, may be in an inconsistent state.
void * ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields)
Retrieve an object or multiple objects using specific fields.
#define ast_sorcery_object_field_register(sorcery, type, name, default_val, opt_type, flags,...)
Register a field within an object.
static struct stasis_subscription * acl_change_sub
void ast_append_acl(const char *sense, const char *stuff, struct ast_acl_list **path, int *error, int *named_acl_flag)
Add a rule to an ACL struct.
int stasis_subscription_accept_message_type(struct stasis_subscription *subscription, const struct stasis_message_type *type)
Indicate to a subscription that we are interested in a message type.
struct stasis_topic * ast_security_topic(void)
A stasis_topic which publishes messages for security related issues.
void * ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor)
Allocate a generic sorcery capable object.
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
SIP ACL details and configuration.
Sorcery Data Access Layer API.
int ast_sockaddr_resolve(struct ast_sockaddr **addrs, const char *str, int flags, int family)
Parses a string with an IPv4 or IPv6 address and place results into an array.