Asterisk - The Open Source Telephony Project  GIT-master-a24979a
Data Structures | Macros | Functions | Variables
res_pjsip_acl.c File Reference
#include "asterisk.h"
#include <pjsip.h>
#include "asterisk/res_pjsip.h"
#include "asterisk/module.h"
#include "asterisk/logger.h"
#include "asterisk/sorcery.h"
#include "asterisk/acl.h"
#include "asterisk/stasis.h"
#include "asterisk/security_events.h"
Include dependency graph for res_pjsip_acl.c:

Go to the source code of this file.

Data Structures

struct  ast_sip_acl
 SIP ACL details and configuration. More...
 

Macros

#define SIP_SORCERY_ACL_TYPE   "acl"
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static void * acl_alloc (const char *name)
 
static void acl_change_stasis_cb (void *data, struct stasis_subscription *sub, struct stasis_message *message)
 
static void acl_destroy (void *obj)
 
static int acl_handler (const struct aco_option *opt, struct ast_variable *var, void *obj)
 
static pj_bool_t acl_on_rx_msg (pjsip_rx_data *rdata)
 
static int apply_acl (pjsip_rx_data *rdata, struct ast_acl_list *acl)
 
static int apply_contact_acl (pjsip_rx_data *rdata, struct ast_acl_list *contact_acl)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static int check_acls (void *obj, void *arg, int flags)
 
static int extract_contact_addr (pjsip_contact_hdr *contact, struct ast_sockaddr **addrs)
 
static int load_module (void)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP ACL Resource" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND, .requires = "res_pjsip", }
 
static struct stasis_subscriptionacl_change_sub
 
static pjsip_module acl_module
 
static const struct ast_module_infoast_module_info = &__mod_info
 

Macro Definition Documentation

◆ SIP_SORCERY_ACL_TYPE

#define SIP_SORCERY_ACL_TYPE   "acl"

Definition at line 192 of file res_pjsip_acl.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 343 of file res_pjsip_acl.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 343 of file res_pjsip_acl.c.

◆ acl_alloc()

static void* acl_alloc ( const char *  name)
static

Definition at line 279 of file res_pjsip_acl.c.

280 {
281  struct ast_sip_acl *sip_acl =
282  ast_sorcery_generic_alloc(sizeof(*sip_acl), acl_destroy);
283 
284  return sip_acl;
285 }
static void acl_destroy(void *obj)
void * ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor)
Allocate a generic sorcery capable object.
Definition: sorcery.c:1728
SIP ACL details and configuration.

References acl_destroy(), and ast_sorcery_generic_alloc().

Referenced by load_module().

◆ acl_change_stasis_cb()

static void acl_change_stasis_cb ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
)
static

Definition at line 287 of file res_pjsip_acl.c.

289 {
291  return;
292  }
293 
295 }
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
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
#define SIP_SORCERY_ACL_TYPE
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...
Definition: sorcery.c:1457
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.

References ast_named_acl_change_type(), ast_sip_get_sorcery(), ast_sorcery_force_reload_object(), SIP_SORCERY_ACL_TYPE, and stasis_message_type().

Referenced by load_module().

◆ acl_destroy()

static void acl_destroy ( void *  obj)
static

Definition at line 272 of file res_pjsip_acl.c.

273 {
274  struct ast_sip_acl *sip_acl = obj;
275  sip_acl->acl = ast_free_acl_list(sip_acl->acl);
276  sip_acl->contact_acl = ast_free_acl_list(sip_acl->contact_acl);
277 }
struct ast_acl_list * ast_free_acl_list(struct ast_acl_list *acl)
Free a list of ACLs.
Definition: acl.c:233
struct ast_acl_list * contact_acl
struct ast_acl_list * acl

References ast_sip_acl::acl, ast_free_acl_list(), and ast_sip_acl::contact_acl.

Referenced by acl_alloc().

◆ acl_handler()

static int acl_handler ( const struct aco_option opt,
struct ast_variable var,
void *  obj 
)
static

Definition at line 237 of file res_pjsip_acl.c.

238 {
239  struct ast_sip_acl *sip_acl = obj;
240  int error = 0;
241  int ignore;
242 
243  if (!strncmp(var->name, "contact_", 8)) {
244  ast_append_acl(var->name + 8, var->value, &sip_acl->contact_acl, &error, &ignore);
245  if (error) {
246  ast_log(LOG_ERROR, "Bad contact ACL '%s' at line '%d' of pjsip.conf\n",
247  var->value, var->lineno);
248  }
249  } else {
250  ast_append_acl(var->name, var->value, &sip_acl->acl, &error, &ignore);
251  if (error) {
252  ast_log(LOG_ERROR, "Bad ACL '%s' at line '%d' of pjsip.conf\n",
253  var->value, var->lineno);
254  }
255  }
256 
257  if (error) {
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);
260  }
261 
262  return error;
263 }
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.
Definition: acl.c:430
#define var
Definition: ast_expr2f.c:614
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
def ignore(key=None, val=None, section=None, pjsip=None, nmapped=None, type='endpoint')
Definition: sip_to_pjsip.py:48
#define NULL
Definition: resample.c:96
int error(const char *format,...)
Definition: utils/frame.c:999

References ast_sip_acl::acl, ast_append_acl(), ast_log, ast_sip_acl::contact_acl, error(), sip_to_pjsip::ignore(), LOG_ERROR, NULL, and var.

Referenced by load_module().

◆ acl_on_rx_msg()

static pj_bool_t acl_on_rx_msg ( pjsip_rx_data *  rdata)
static

Definition at line 215 of file res_pjsip_acl.c.

216 {
220  RAII_VAR(struct ast_sip_acl *, matched_acl, NULL, ao2_cleanup);
221 
222  if (!acls) {
223  ast_log(LOG_ERROR, "Unable to retrieve ACL sorcery data\n");
224  return PJ_FALSE;
225  }
226 
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);
230  }
231  return PJ_TRUE;
232  }
233 
234  return PJ_FALSE;
235 }
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
Definition: astobj2.h:1693
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:513
static int check_acls(void *obj, void *arg, int flags)
@ AST_RETRIEVE_FLAG_MULTIPLE
Return all matching objects.
Definition: sorcery.h:120
@ AST_RETRIEVE_FLAG_ALL
Perform no matching, return all objects.
Definition: sorcery.h:123
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.
Definition: sorcery.c:1897
Generic container type.
#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:936

References ao2_callback, ao2_cleanup, ast_log, AST_RETRIEVE_FLAG_ALL, AST_RETRIEVE_FLAG_MULTIPLE, ast_sip_get_pjsip_endpoint(), ast_sip_get_sorcery(), ast_sorcery_retrieve_by_fields(), check_acls(), LOG_ERROR, NULL, RAII_VAR, and SIP_SORCERY_ACL_TYPE.

◆ apply_acl()

static int apply_acl ( pjsip_rx_data *  rdata,
struct ast_acl_list acl 
)
static

Definition at line 121 of file res_pjsip_acl.c.

122 {
123  struct ast_sockaddr addr;
124 
125  if (ast_acl_list_is_empty(acl)) {
126  return 0;
127  }
128 
129  memset(&addr, 0, sizeof(addr));
130  ast_sockaddr_parse(&addr, rdata->pkt_info.src_name, PARSE_PORT_FORBID);
131  ast_sockaddr_set_port(&addr, rdata->pkt_info.src_port);
132 
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));
135  return 1;
136  }
137  return 0;
138 }
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.
Definition: acl.c:800
@ AST_SENSE_ALLOW
Definition: acl.h:38
int ast_acl_list_is_empty(struct ast_acl_list *acl_list)
Determines if an ACL is empty or if it contains entries.
Definition: acl.c:541
#define LOG_WARNING
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:256
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:532
Definition: test_acl.c:111
Socket address structure.
Definition: netsock2.h:97

References ast_acl_list_is_empty(), ast_apply_acl(), ast_log, AST_SENSE_ALLOW, ast_sockaddr_parse(), ast_sockaddr_set_port, ast_sockaddr_stringify(), LOG_WARNING, and PARSE_PORT_FORBID.

Referenced by check_acls().

◆ apply_contact_acl()

static int apply_contact_acl ( pjsip_rx_data *  rdata,
struct ast_acl_list contact_acl 
)
static

Definition at line 158 of file res_pjsip_acl.c.

159 {
160  int num_contact_addrs;
161  int forbidden = 0;
162  struct ast_sockaddr *contact_addrs;
163  int i;
164  pjsip_contact_hdr *contact = (pjsip_contact_hdr *)&rdata->msg_info.msg->hdr;
165 
166  if (ast_acl_list_is_empty(contact_acl)) {
167  return 0;
168  }
169 
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) {
173  continue;
174  }
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]));
178  forbidden = 1;
179  break;
180  }
181  }
182  ast_free(contact_addrs);
183  if (forbidden) {
184  /* No use checking other contacts if we already have failed ACL check */
185  break;
186  }
187  }
188 
189  return forbidden;
190 }
if(!yyg->yy_init)
Definition: ast_expr2f.c:868
#define ast_free(a)
Definition: astmm.h:180
static int extract_contact_addr(pjsip_contact_hdr *contact, struct ast_sockaddr **addrs)

References ast_acl_list_is_empty(), ast_apply_acl(), ast_free, ast_log, AST_SENSE_ALLOW, ast_sockaddr_stringify(), extract_contact_addr(), if(), and LOG_WARNING.

Referenced by check_acls().

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 343 of file res_pjsip_acl.c.

◆ check_acls()

static int check_acls ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 203 of file res_pjsip_acl.c.

204 {
205  struct ast_sip_acl *sip_acl = obj;
206  pjsip_rx_data *rdata = arg;
207 
208  if (apply_acl(rdata, sip_acl->acl) ||
209  apply_contact_acl(rdata, sip_acl->contact_acl)) {
210  return CMP_MATCH | CMP_STOP;
211  }
212  return 0;
213 }
@ CMP_MATCH
Definition: astobj2.h:1027
@ CMP_STOP
Definition: astobj2.h:1028
static int apply_acl(pjsip_rx_data *rdata, struct ast_acl_list *acl)
static int apply_contact_acl(pjsip_rx_data *rdata, struct ast_acl_list *contact_acl)

References ast_sip_acl::acl, apply_acl(), apply_contact_acl(), CMP_MATCH, CMP_STOP, and ast_sip_acl::contact_acl.

Referenced by acl_on_rx_msg().

◆ extract_contact_addr()

static int extract_contact_addr ( pjsip_contact_hdr *  contact,
struct ast_sockaddr **  addrs 
)
static

Definition at line 140 of file res_pjsip_acl.c.

141 {
142  pjsip_sip_uri *sip_uri;
143  char host[256];
144 
145  if (!contact || contact->star) {
146  *addrs = NULL;
147  return 0;
148  }
149  if (!PJSIP_URI_SCHEME_IS_SIP(contact->uri) && !PJSIP_URI_SCHEME_IS_SIPS(contact->uri)) {
150  *addrs = NULL;
151  return 0;
152  }
153  sip_uri = pjsip_uri_get_uri(contact->uri);
154  ast_copy_pj_str(host, &sip_uri->host, sizeof(host));
156 }
@ AST_AF_UNSPEC
Definition: netsock2.h:54
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.
Definition: netsock2.c:280
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:2035

References AST_AF_UNSPEC, ast_copy_pj_str(), ast_sockaddr_resolve(), NULL, and PARSE_PORT_FORBID.

Referenced by apply_contact_acl().

◆ load_module()

static int load_module ( void  )
static

Definition at line 297 of file res_pjsip_acl.c.

298 {
301  "config", "pjsip.conf,criteria=type=acl");
302 
304  acl_alloc, NULL, NULL)) {
305 
306  ast_log(LOG_ERROR, "Failed to register SIP %s object with sorcery\n",
309  }
310 
318 
320 
324 
326 
328 }
@ OPT_NOOP_T
Type for a default handler that should do nothing.
struct stasis_topic * ast_security_topic(void)
A stasis_topic which publishes messages for security related issues.
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
int ast_sip_register_service(pjsip_module *module)
Register a SIP service in Asterisk.
Definition: res_pjsip.c:110
static int acl_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
static struct stasis_subscription * acl_change_sub
static pjsip_module acl_module
static void * acl_alloc(const char *name)
static void acl_change_stasis_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
#define ast_sorcery_object_register(sorcery, type, alloc, transform, apply)
Register an object type.
Definition: sorcery.h:837
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.
Definition: sorcery.c:1393
#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.
Definition: sorcery.h:1005
#define ast_sorcery_apply_config(sorcery, name)
Definition: sorcery.h:455
#define ast_sorcery_object_field_register(sorcery, type, name, default_val, opt_type, flags,...)
Register a field within an object.
Definition: sorcery.h:955
#define ast_sorcery_apply_default(sorcery, type, name, data)
Definition: sorcery.h:476
@ STASIS_SUBSCRIPTION_FILTER_SELECTIVE
Definition: stasis.h:297
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.
Definition: stasis.c:1025
int stasis_subscription_set_filter(struct stasis_subscription *subscription, enum stasis_subscription_message_filter filter)
Set the message type filtering level on a subscription.
Definition: stasis.c:1079
#define stasis_subscribe(topic, callback, data)
Definition: stasis.h:649

References acl_alloc(), acl_change_stasis_cb(), acl_change_sub, acl_handler(), acl_module, ast_log, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_named_acl_change_type(), ast_security_topic(), ast_sip_get_sorcery(), ast_sip_register_service(), ast_sorcery_apply_config, ast_sorcery_apply_default, ast_sorcery_load_object(), ast_sorcery_object_field_register, ast_sorcery_object_field_register_custom, ast_sorcery_object_register, LOG_ERROR, NULL, OPT_NOOP_T, SIP_SORCERY_ACL_TYPE, stasis_subscribe, stasis_subscription_accept_message_type(), STASIS_SUBSCRIPTION_FILTER_SELECTIVE, and stasis_subscription_set_filter().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 330 of file res_pjsip_acl.c.

331 {
334  return 0;
335 }
void ast_sip_unregister_service(pjsip_module *module)
Definition: res_pjsip.c:126
struct stasis_subscription * stasis_unsubscribe_and_join(struct stasis_subscription *subscription)
Cancel a subscription, blocking until the last message is processed.
Definition: stasis.c:1136

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP ACL Resource" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND, .requires = "res_pjsip", }
static

Definition at line 330 of file res_pjsip_acl.c.

◆ acl_change_sub

struct stasis_subscription* acl_change_sub
static

Definition at line 119 of file res_pjsip_acl.c.

Referenced by load_module().

◆ acl_module

pjsip_module acl_module
static

Definition at line 265 of file res_pjsip_acl.c.

Referenced by load_module().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 343 of file res_pjsip_acl.c.