Asterisk - The Open Source Telephony Project GIT-master-27fb039
Loading...
Searching...
No Matches
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 = ASTERISK_GPL_KEY , .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 216 of file res_pjsip_acl.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 367 of file res_pjsip_acl.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 367 of file res_pjsip_acl.c.

◆ acl_alloc()

static void * acl_alloc ( const char *  name)
static

Definition at line 303 of file res_pjsip_acl.c.

304{
305 struct ast_sip_acl *sip_acl =
306 ast_sorcery_generic_alloc(sizeof(*sip_acl), acl_destroy);
307
308 return sip_acl;
309}
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:1792
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 311 of file res_pjsip_acl.c.

313{
315 return;
316 }
317
319}
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:1521

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

Referenced by load_module().

◆ acl_destroy()

static void acl_destroy ( void *  obj)
static

Definition at line 296 of file res_pjsip_acl.c.

297{
298 struct ast_sip_acl *sip_acl = obj;
299 sip_acl->acl = ast_free_acl_list(sip_acl->acl);
300 sip_acl->contact_acl = ast_free_acl_list(sip_acl->contact_acl);
301}
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 261 of file res_pjsip_acl.c.

262{
263 struct ast_sip_acl *sip_acl = obj;
264 int error = 0;
265 int ignore;
266
267 if (!strncmp(var->name, "contact_", 8)) {
268 ast_append_acl(var->name + 8, var->value, &sip_acl->contact_acl, &error, &ignore);
269 if (error) {
270 ast_log(LOG_ERROR, "Bad contact ACL '%s' at line '%d' of pjsip.conf\n",
271 var->value, var->lineno);
272 }
273 } else {
274 ast_append_acl(var->name, var->value, &sip_acl->acl, &error, &ignore);
275 if (error) {
276 ast_log(LOG_ERROR, "Bad ACL '%s' at line '%d' of pjsip.conf\n",
277 var->value, var->lineno);
278 }
279 }
280
281 if (error) {
282 ast_log(LOG_ERROR, "There is an error in ACL configuration. Blocking ALL SIP traffic.\n");
283 ast_append_acl("deny", "0.0.0.0/0.0.0.0", &sip_acl->acl, NULL, &ignore);
284 }
285
286 return error;
287}
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:429
#define var
Definition ast_expr2f.c:605
#define ast_log
Definition astobj2.c:42
#define LOG_ERROR
ignore(key=None, val=None, section=None, pjsip=None, nmapped=None, type='endpoint')
#define NULL
Definition resample.c:96
int error(const char *format,...)

References ast_sip_acl::acl, ast_append_acl(), ast_log, ast_sip_acl::contact_acl, error(), 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 239 of file res_pjsip_acl.c.

240{
244 RAII_VAR(struct ast_sip_acl *, matched_acl, NULL, ao2_cleanup);
245
246 if (!acls) {
247 ast_log(LOG_ERROR, "Unable to retrieve ACL sorcery data\n");
248 return PJ_FALSE;
249 }
250
251 if ((matched_acl = ao2_callback(acls, 0, check_acls, rdata))) {
252 if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) {
253 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 403, NULL, NULL, NULL);
254 }
255 return PJ_TRUE;
256 }
257
258 return PJ_FALSE;
259}
#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:520
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:1961
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:981

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 145 of file res_pjsip_acl.c.

146{
147 struct ast_sockaddr addr;
148
150 return 0;
151 }
152
153 memset(&addr, 0, sizeof(addr));
154 ast_sockaddr_parse(&addr, rdata->pkt_info.src_name, PARSE_PORT_FORBID);
155 ast_sockaddr_set_port(&addr, rdata->pkt_info.src_port);
156
157 if (ast_apply_acl(acl, &addr, "SIP ACL: ") != AST_SENSE_ALLOW) {
158 ast_log(LOG_WARNING, "Incoming SIP message from %s did not pass ACL test\n", ast_sockaddr_stringify(&addr));
159 return 1;
160 }
161 return 0;
162}
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:799
@ 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:540
#define LOG_WARNING
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition netsock2.h:256
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_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition netsock2.h:532
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 182 of file res_pjsip_acl.c.

183{
184 int num_contact_addrs;
185 int forbidden = 0;
186 struct ast_sockaddr *contact_addrs;
187 int i;
188 pjsip_contact_hdr *contact = (pjsip_contact_hdr *)&rdata->msg_info.msg->hdr;
189
190 if (ast_acl_list_is_empty(contact_acl)) {
191 return 0;
192 }
193
194 while ((contact = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, contact->next))) {
195 num_contact_addrs = extract_contact_addr(contact, &contact_addrs);
196 if (num_contact_addrs <= 0) {
197 continue;
198 }
199 for (i = 0; i < num_contact_addrs; ++i) {
200 if (ast_apply_acl(contact_acl, &contact_addrs[i], "SIP Contact ACL: ") != AST_SENSE_ALLOW) {
201 ast_log(LOG_WARNING, "Incoming SIP message from %s did not pass ACL test\n", ast_sockaddr_stringify(&contact_addrs[i]));
202 forbidden = 1;
203 break;
204 }
205 }
206 ast_free(contact_addrs);
207 if (forbidden) {
208 /* No use checking other contacts if we already have failed ACL check */
209 break;
210 }
211 }
212
213 return forbidden;
214}
#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(), and LOG_WARNING.

Referenced by check_acls().

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 367 of file res_pjsip_acl.c.

◆ check_acls()

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

Definition at line 227 of file res_pjsip_acl.c.

228{
229 struct ast_sip_acl *sip_acl = obj;
230 pjsip_rx_data *rdata = arg;
231
232 if (apply_acl(rdata, sip_acl->acl) ||
233 apply_contact_acl(rdata, sip_acl->contact_acl)) {
234 return CMP_MATCH | CMP_STOP;
235 }
236 return 0;
237}
@ 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 164 of file res_pjsip_acl.c.

165{
166 pjsip_sip_uri *sip_uri;
167 char host[256];
168
169 if (!contact || contact->star) {
170 *addrs = NULL;
171 return 0;
172 }
173 if (!PJSIP_URI_SCHEME_IS_SIP(contact->uri) && !PJSIP_URI_SCHEME_IS_SIPS(contact->uri)) {
174 *addrs = NULL;
175 return 0;
176 }
177 sip_uri = pjsip_uri_get_uri(contact->uri);
178 ast_copy_pj_str(host, &sip_uri->host, sizeof(host));
180}
@ 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:2201

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 321 of file res_pjsip_acl.c.

322{
325 "config", "pjsip.conf,criteria=type=acl");
326
328 acl_alloc, NULL, NULL)) {
329
330 ast_log(LOG_ERROR, "Failed to register SIP %s object with sorcery\n",
333 }
334
342
344
348
350
352}
@ OPT_NOOP_T
Type for a default handler that should do nothing.
@ 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:117
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)
struct stasis_topic * ast_security_topic(void)
A stasis_topic which publishes messages for security related issues.
#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:1457
#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:1090
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:1144
#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 354 of file res_pjsip_acl.c.

355{
358 return 0;
359}
void ast_sip_unregister_service(pjsip_module *module)
Definition res_pjsip.c:133
struct stasis_subscription * stasis_unsubscribe_and_join(struct stasis_subscription *subscription)
Cancel a subscription, blocking until the last message is processed.
Definition stasis.c:1201

References acl_change_sub, acl_module, ast_sip_unregister_service(), and stasis_unsubscribe_and_join().

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP ACL Resource" , .key = ASTERISK_GPL_KEY , .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 367 of file res_pjsip_acl.c.

◆ acl_change_sub

struct stasis_subscription* acl_change_sub
static

Definition at line 143 of file res_pjsip_acl.c.

Referenced by load_module(), and unload_module().

◆ acl_module

pjsip_module acl_module
static

Definition at line 289 of file res_pjsip_acl.c.

289 {
290 .name = { "ACL Module", 14 },
291 /* This should run after a logger but before anything else */
292 .priority = 1,
293 .on_rx_request = acl_on_rx_msg,
294};
static pj_bool_t acl_on_rx_msg(pjsip_rx_data *rdata)

Referenced by load_module(), and unload_module().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 367 of file res_pjsip_acl.c.