Asterisk - The Open Source Telephony Project  18.5.0
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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .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.

Referenced by acl_change_stasis_cb(), acl_on_rx_msg(), and load_module().

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.

References acl_destroy(), and ast_sorcery_generic_alloc().

Referenced by load_module().

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.

◆ 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.

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().

289 {
291  return;
292  }
293 
295 }
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.
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 ...
#define SIP_SORCERY_ACL_TYPE
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.

◆ acl_destroy()

static void acl_destroy ( void *  obj)
static

Definition at line 272 of file res_pjsip_acl.c.

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

Referenced by acl_alloc().

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
SIP ACL details and configuration.

◆ 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.

References ast_sip_acl::acl, ast_append_acl(), ast_log, ast_sip_acl::contact_acl, error(), sip_to_pjsip::ignore(), ast_variable::lineno, LOG_ERROR, ast_variable::name, NULL, and ast_variable::value.

Referenced by load_module().

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 }
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
def ignore(key=None, val=None, section=None, pjsip=None, nmapped=None, type='endpoint')
Definition: sip_to_pjsip.py:48
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
struct ast_acl_list * contact_acl
struct ast_acl_list * acl
int error(const char *format,...)
Definition: utils/frame.c:999
SIP ACL details and configuration.

◆ 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.

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.

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)
Definition: astobj2.h:1716
Perform no matching, return all objects.
Definition: sorcery.h:123
Return all matching objects.
Definition: sorcery.h:120
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
#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
static int check_acls(void *obj, void *arg, int flags)
#define LOG_ERROR
Definition: logger.h:285
#define SIP_SORCERY_ACL_TYPE
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
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:3718
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
Generic container type.
SIP ACL details and configuration.

◆ 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.

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().

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 }
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 LOG_WARNING
Definition: logger.h:274
Socket address structure.
Definition: netsock2.h:97
#define ast_log
Definition: astobj2.c:42
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
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 ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:537
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260

◆ 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.

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().

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 }
#define LOG_WARNING
Definition: logger.h:274
if(!yyg->yy_init)
Definition: ast_expr2f.c:868
Socket address structure.
Definition: netsock2.h:97
#define ast_log
Definition: astobj2.c:42
static int extract_contact_addr(pjsip_contact_hdr *contact, struct ast_sockaddr **addrs)
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
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
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260
#define ast_free(a)
Definition: astmm.h:182

◆ 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.

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().

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 }
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_acl_list * contact_acl
struct ast_acl_list * acl
SIP ACL details and configuration.

◆ 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.

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

Referenced by apply_contact_acl().

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 }
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
static char host[256]
Definition: muted.c:77
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

◆ load_module()

static int load_module ( void  )
static

Definition at line 297 of file res_pjsip_acl.c.

References acl_alloc(), acl_change_stasis_cb(), 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().

Referenced by unload_module().

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 }
struct stasis_topic * ast_security_topic(void)
A stasis_topic which publishes messages for security related issues.
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.
Definition: stasis.c:1079
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 ...
#define ast_sorcery_apply_config(sorcery, name)
Definition: sorcery.h:456
#define NULL
Definition: resample.c:96
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
static pjsip_module acl_module
#define ast_log
Definition: astobj2.c:42
#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
static struct stasis_subscription * acl_change_sub
#define ast_sorcery_object_register(sorcery, type, alloc, transform, apply)
Register an object type.
Definition: sorcery.h:838
int ast_sip_register_service(pjsip_module *module)
Register a SIP service in Asterisk.
Definition: res_pjsip.c:3315
#define stasis_subscribe(topic, callback, data)
Definition: stasis.h:652
#define LOG_ERROR
Definition: logger.h:285
#define ast_sorcery_apply_default(sorcery, type, name, data)
Definition: sorcery.h:477
#define SIP_SORCERY_ACL_TYPE
static void acl_change_stasis_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void * acl_alloc(const char *name)
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
#define ast_sorcery_object_field_register(sorcery, type, name, default_val, opt_type, flags,...)
Register a field within an object.
Definition: sorcery.h:955
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
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
static int acl_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 330 of file res_pjsip_acl.c.

References acl_module, AST_MODFLAG_LOAD_ORDER, AST_MODPRI_APP_DEPEND, AST_MODULE_INFO(), AST_MODULE_SUPPORT_CORE, ast_sip_unregister_service(), ASTERISK_GPL_KEY, load_module(), and stasis_unsubscribe_and_join().

331 {
334  return 0;
335 }
static pjsip_module acl_module
static struct stasis_subscription * acl_change_sub
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
void ast_sip_unregister_service(pjsip_module *module)
Definition: res_pjsip.c:3331

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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .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 343 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.

◆ acl_module

pjsip_module acl_module
static

Definition at line 265 of file res_pjsip_acl.c.

Referenced by load_module(), and unload_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.