Asterisk - The Open Source Telephony Project  18.5.0
acl.h
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2012, Digium, Inc.
5  *
6  * Mark Spencer <[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 /*! \file
20  * \brief Access Control of various sorts
21  */
22 
23 #ifndef _ASTERISK_ACL_H
24 #define _ASTERISK_ACL_H
25 
26 
27 #if defined(__cplusplus) || defined(c_plusplus)
28 extern "C" {
29 #endif
30 
31 #include "asterisk/network.h"
32 #include "asterisk/linkedlists.h"
33 #include "asterisk/netsock2.h"
34 #include "asterisk/io.h"
35 
39 };
40 
41 /* Host based access control */
42 
43 /*! \brief internal representation of ACL entries
44  * In principle user applications would have no need for this,
45  * but there is sometimes a need to extract individual items,
46  * e.g. to print them, and rather than defining iterators to
47  * navigate the list, and an externally visible 'struct ast_ha_entry',
48  * at least in the short term it is more convenient to make the whole
49  * thing public and let users play with them.
50  */
51 struct ast_ha {
52  /* Host access rule */
56  struct ast_ha *next;
57 };
58 
59 #define ACL_NAME_LENGTH 80
60 
61 /*!
62  * \brief an ast_acl is a linked list node of ast_ha structs which may have names.
63  *
64  * \note These shouldn't be used directly by ACL consumers. Consumers should handle
65  * ACLs via ast_acl_list structs.
66  */
67 struct ast_acl {
68  struct ast_ha *acl; /*!< Rules contained by the ACL */
69  int is_realtime; /*!< If raised, this named ACL was retrieved from realtime storage */
70  int is_invalid; /*!< If raised, this is an invalid ACL which will automatically reject everything. */
71  char name[ACL_NAME_LENGTH]; /*!< If this was retrieved from the named ACL subsystem, this is the name of the ACL. */
73 };
74 
75 /*! \brief Wrapper for an ast_acl linked list. */
77 
78 /*!
79  * \brief Free a list of HAs
80  *
81  * \details
82  * Given the head of a list of HAs, it and all appended
83  * HAs are freed
84  *
85  * \param ha The head of the list of HAs to free
86  * \retval void
87  */
88 void ast_free_ha(struct ast_ha *ha);
89 
90 /*!
91  * \brief Free a list of ACLs
92  *
93  * \details
94  * Given the head of a list of ast_acl structs, it and all appended
95  * acl structs will be freed. This includes the ast_ha structs within
96  * the individual nodes.
97  * \param acl The list of ACLs to free
98  * \retval NULL
99  */
101 
102 /*!
103  * \brief Copy the contents of one HA to another
104  *
105  * \details
106  * This copies the internals of the 'from' HA to the 'to'
107  * HA. It is important that the 'to' HA has been allocated
108  * prior to calling this function
109  *
110  * \param from Source HA to copy
111  * \param to Destination HA to copy to
112  * \retval void
113  */
114 void ast_copy_ha(const struct ast_ha *from, struct ast_ha *to);
115 
116 /*!
117  * \brief Add a new rule to a list of HAs
118  *
119  * \details
120  * This adds the new host access rule to the end of the list
121  * whose head is specified by the path parameter. Rules are
122  * evaluated in a way such that if multiple rules apply to
123  * a single IP address/subnet mask, then the rule latest
124  * in the list will be used.
125  *
126  * \param sense Either "permit" or "deny" (Actually any 'p' word will result
127  * in permission, and any other word will result in denial)
128  * \param stuff The IP address and subnet mask, separated with a '/'. The subnet
129  * mask can either be in dotted-decimal format or in CIDR notation (i.e. 0-32).
130  * \param path The head of the HA list to which we wish to append our new rule. If
131  * NULL is passed, then the new rule will become the head of the list
132  * \param[out] error The integer error points to will be set non-zero if an error occurs
133  * \return The head of the HA list
134  */
135 struct ast_ha *ast_append_ha(const char *sense, const char *stuff, struct ast_ha *path, int *error);
136 
137 /*!
138  * \brief Add a new rule with optional port to a list of HAs
139  * \since 13.31.0, 16.8.0, 17.2.0
140  *
141  * \details
142  * This adds the new host access rule to the end of the list
143  * whose head is specified by the path parameter. Rules are
144  * evaluated in a way such that if multiple rules apply to
145  * a single IP address/subnet mask, then the rule latest
146  * in the list will be used.
147  *
148  * \param sense Either "permit" or "deny" (Actually any 'p' word will result
149  * in permission, and any other word will result in denial)
150  * \param stuff The IP address and subnet mask, separated with a '/'. The subnet
151  * mask can either be in dotted-decimal format or in CIDR notation (i.e. 0-32). A
152  * port can be provided by placing it after the IP address, separated with a ':'.
153  * \param path The head of the HA list to which we wish to append our new rule. If
154  * NULL is passed, then the new rule will become the head of the list
155  * \param[out] error The integer error points to will be set non-zero if an error occurs
156  * \return The head of the HA list
157  */
158 struct ast_ha *ast_append_ha_with_port(const char *sense, const char *stuff, struct ast_ha *path, int *error);
159 
160 /*!
161  * \brief Convert HAs to a comma separated string value
162  * \param ha the starting ha head
163  * \param buf string buffer to convert data to
164  */
165 void ast_ha_join(const struct ast_ha *ha, struct ast_str **buf);
166 
167 /*!
168  * \brief Convert HAs to a comma separated string value using CIDR notation
169  * \param ha the starting ha head
170  * \param buf string buffer to convert data to
171  */
172 void ast_ha_join_cidr(const struct ast_ha *ha, struct ast_str **buf);
173 
174 /*!
175  * \brief Add a rule to an ACL struct
176  *
177  * \details
178  * This adds a named ACL or an ACL rule to an ast_acl container.
179  * It works in a similar way to ast_append_ha.
180  *
181  * \param sense Can be any among "permit", "deny", or "acl"
182  * this controls whether the rule being added will simply modify the unnamed ACL at the head of the list
183  * or if a new named ACL will be added to that ast_acl.
184  * \param stuff If sense is 'permit'/'deny', this is the ip address and subnet mask separated with a '/' like in ast_append ha.
185  * If it sense is 'acl', then this will be the name of the ACL being appended to the container.
186  * \param path Address of the ACL list being appended
187  * \param[out] error The int that error points to will be set to 1 if an error occurs.
188  * \param[out] named_acl_flag This will raise a flag under certain conditions to indicate that a named ACL has been added by this
189  * operation. This may be used to indicate that an event subscription should be made against the named ACL subsystem.
190  * Note: This flag may be raised by this function, but it will never be lowered by it.
191  */
192 void ast_append_acl(const char *sense, const char *stuff, struct ast_acl_list **path, int *error, int *named_acl_flag);
193 
194 /*!
195  * \brief Determines if an ACL is empty or if it contains entries
196  *
197  * \param acl_list The ACL list being checked
198  * \retval 0 - the list is not empty
199  * \retval 1 - the list is empty
200  */
201 int ast_acl_list_is_empty(struct ast_acl_list *acl_list);
202 
203 /*!
204  * \brief Apply a set of rules to a given IP address
205  *
206  * \details
207  * The list of host access rules is traversed, beginning with the
208  * input rule. If the IP address given matches a rule, the "sense"
209  * of that rule is used as the return value. Note that if an IP
210  * address matches multiple rules that the last one matched will be
211  * the one whose sense will be returned.
212  *
213  * \param ha The head of the list of host access rules to follow
214  * \param addr An ast_sockaddr whose address is considered when matching rules
215  * \retval AST_SENSE_ALLOW The IP address passes our ACL
216  * \retval AST_SENSE_DENY The IP address fails our ACL
217  */
218 enum ast_acl_sense ast_apply_ha(const struct ast_ha *ha, const struct ast_sockaddr *addr);
219 
220 /*!
221  * \brief Apply a set of rules to a given IP address
222  *
223  * \details
224  * Similar to the above, only uses an acl container, which is a whole slew
225  * of ast_ha lists. It runs ast_apply_ha on each of the ast_ha structs
226  * contained in the acl container. It will deny if any of the ast_ha lists
227  * fail, and it will pass only if all of the rules pass.
228  *
229  * \param acl_list The head of the list of ACLs to evaluate
230  * \param addr An ast_sockaddr whose address is considered when matching rules
231  * \param purpose Context for which the ACL is being applied - Establishes purpose of a notice when rejected
232  *
233  * \retval AST_SENSE_ALLOW The IP address passes our ACLs
234  * \retval AST_SENSE_DENY The IP address fails our ACLs
235  */
236 enum ast_acl_sense ast_apply_acl(struct ast_acl_list *acl_list, const struct ast_sockaddr *addr, const char *purpose);
237 
238 /*!
239  * \brief Apply a set of rules to a given IP address, don't log failure.
240  *
241  * \details
242  * Exactly like ast_apply_acl, except that it will never log anything.
243  *
244  * \param acl_list The head of the list of ACLs to evaluate
245  * \param addr An ast_sockaddr whose address is considered when matching rules
246  *
247  * \retval AST_SENSE_ALLOW The IP address passes our ACLs
248  * \retval AST_SENSE_DENY The IP address fails our ACLs
249  */
250 enum ast_acl_sense ast_apply_acl_nolog(struct ast_acl_list *acl_list, const struct ast_sockaddr *addr);
251 
252 /*!
253  * \brief Get the IP address given a hostname
254  *
255  * \details
256  * Similar in nature to ast_gethostbyname, except that instead
257  * of getting an entire hostent structure, you instead are given
258  * only the IP address inserted into a ast_sockaddr structure.
259  *
260  * \param addr The IP address found. The address family is used
261  * as an input parameter to filter the returned addresses. If
262  * it is AST_AF_UNSPEC, both IPv4 and IPv6 addresses can be returned.
263  * \param hostname The hostname to look up
264  *
265  * \retval 0 Success
266  * \retval -1 Failure
267  */
268 int ast_get_ip(struct ast_sockaddr *addr, const char *hostname);
269 
270 /*!
271  * \brief Get the IP address given a hostname and optional service
272  *
273  * \details
274  * If the service parameter is non-NULL, then an SRV lookup will be made by
275  * prepending the service to the hostname parameter, separated by a '.'
276  * For example, if hostname is "example.com" and service is "_sip._udp" then
277  * an SRV lookup will be done for "_sip._udp.example.com". If service is NULL,
278  * then this function acts exactly like a call to ast_get_ip.
279  *
280  * \param addr The IP address found. The address family is used
281  * as an input parameter to filter the returned addresses. If
282  * it is 0, both IPv4 and IPv6 addresses can be returned.
283  *
284  * \param hostname The hostname to look up
285  * \param service A specific service provided by the host. A NULL service results
286  * in an A-record lookup instead of an SRV lookup
287  * \retval 0 Success
288  * \retval -1 Failure
289  */
290 int ast_get_ip_or_srv(struct ast_sockaddr *addr, const char *hostname, const char *service);
291 
292 /*!
293  * \brief Get our local IP address when contacting a remote host
294  *
295  * \details
296  * This function will attempt to connect(2) to them over UDP using a source
297  * port of 5060. If the connect(2) call is successful, then we inspect the
298  * sockaddr_in output parameter of connect(2) to determine the IP address
299  * used to connect to them. This IP address is then copied into us.
300  *
301  * \param them The IP address to which we wish to attempt to connect
302  * \param[out] us The source IP address used to connect to them
303  * \retval -1 Failure
304  * \retval 0 Success
305  */
306 int ast_ouraddrfor(const struct ast_sockaddr *them, struct ast_sockaddr *us);
307 
308 /*!
309  * \brief Find an IP address associated with a specific interface
310  *
311  * \details
312  * Given an interface such as "eth0" we find the primary IP address
313  * associated with it using the SIOCGIFADDR ioctl. If the ioctl call
314  * should fail, we populate address with 0s.
315  *
316  * \note
317  * This function is not actually used anywhere
318  *
319  * \param iface The interface name whose IP address we wish to find
320  * \param[out] address The interface's IP address is placed into this param
321  * \retval -1 Failure. address is filled with 0s
322  * \retval 0 Success
323  */
324 int ast_lookup_iface(char *iface, struct ast_sockaddr *address);
325 
326 /*!
327  * \brief Duplicate the contents of a list of host access rules
328  *
329  * \details
330  * A deep copy of all ast_has in the list is made. The returned
331  * value is allocated on the heap and must be freed independently
332  * of the input parameter when finished.
333  *
334  * \param original The ast_ha to copy
335  * \retval The head of the list of duplicated ast_has
336  */
337 struct ast_ha *ast_duplicate_ha_list(struct ast_ha *original);
338 
339 /*!
340  * \brief Duplicates the contests of a list of lists of host access rules.
341  *
342  * \details
343  * A deep copy of an ast_acl list is made (which in turn means a deep copy of
344  * each of the ast_ha structs contained within). The returned value is allocated
345  * on the heap and must be freed independently of the input paramater when
346  * finished.
347  *
348  * \param original The ast_acl_list to copy
349  * \retval The new duplicated ast_acl_list
350  */
351 struct ast_acl_list *ast_duplicate_acl_list(struct ast_acl_list *original);
352 
353 /*!
354  * \brief Find our IP address
355  *
356  * \details
357  * This function goes through many iterations in an attempt to find
358  * our IP address. If any step along the way should fail, we move to the
359  * next item in the list. Here are the steps taken:
360  * - If bindaddr has a non-zero IP address, that is copied into ourip
361  * - We use a combination of gethostname and ast_gethostbyname to find our
362  * IP address.
363  * - We use ast_ouraddrfor with 198.41.0.4 as the destination IP address
364  * - We try some platform-specific socket operations to find the IP address
365  *
366  * \param[out] ourip Our IP address is written here when it is found
367  * \param bindaddr A hint used for finding our IP. See the steps above for
368  * more details
369  * \param family Only addresses of the given family will be returned. Use 0
370  * or AST_SOCKADDR_UNSPEC to get addresses of all families.
371  * \retval 0 Success
372  * \retval -1 Failure
373  */
374 int ast_find_ourip(struct ast_sockaddr *ourip, const struct ast_sockaddr *bindaddr, int family);
375 
376 /*!
377  * \brief Convert a string to the appropriate COS value
378  *
379  * \param value The COS string to convert
380  * \param[out] cos The integer representation of that COS value
381  * \retval -1 Failure
382  * \retval 0 Success
383  */
384 int ast_str2cos(const char *value, unsigned int *cos);
385 
386 /*!
387  * \brief Convert a string to the appropriate TOS value
388  *
389  * \param value The TOS string to convert
390  * \param[out] tos The integer representation of that TOS value
391  * \retval -1 Failure
392  * \retval 0 Success
393  */
394 int ast_str2tos(const char *value, unsigned int *tos);
395 
396 /*!
397  * \brief Convert a TOS value into its string representation
398  *
399  * \param tos The TOS value to look up
400  * \return The string equivalent of the TOS value
401  */
402 const char *ast_tos2str(unsigned int tos);
403 
404 /*!
405  * \brief Retrieve a named ACL
406  *
407  * \details
408  * This function attempts to find a named ACL. If found, a copy
409  * of the requested ACL will be made which must be freed by
410  * the caller.
411  *
412  * \param name Name of the ACL sought
413  * \param[out] is_realtime will be true if the ACL being returned is from realtime
414  * \param[out] is_undefined will be true if no ACL profile can be found for the requested name
415  *
416  * \retval A copy of the named ACL as an ast_ha
417  * \retval NULL if no ACL could be found.
418  */
419 struct ast_ha *ast_named_acl_find(const char *name, int *is_realtime, int *is_undefined);
420 
421 /*!
422  * \brief a \ref stasis_message_type for changes against a named ACL or the set of all named ACLs
423  * \since 12
424  *
425  * \retval NULL on error
426  * \retval \ref stasis_message_type for named ACL changes
427  *
428  * \note Messages of this type should always be issued on and expected from the
429  * \ref ast_security_topic \ref stasis_topic
430  */
432 
433 /*!
434  * \brief output an HA to the provided fd
435  *
436  * \details
437  * This function can be used centrally to output HAs as used in ACLs from other
438  * modules. It follows the format as originally used for named ACLs in
439  * named_acl.c.
440  *
441  * \param fd The file-descriptor to which to output the HA.
442  * \param ha The HA to output.
443  * \param prefix If you need a specific prefix output on each line, give it here, may be NULL.
444  *
445  * \since 13.33.0, 16.10.0, 17.4.0
446  */
447 void ast_ha_output(int fd, const struct ast_ha *ha, const char *prefix);
448 
449 /*!
450  * \brief output an ACL to the provided fd
451  *
452  * \details
453  * This function can be used centrally to output HAs as used in ACLs from other
454  * modules. It follows the format as originally used for named ACLs in
455  * named_acl.c.
456  *
457  * \param fd The file-descriptor to which to output the ACL.
458  * \param acl The ACL to output.
459  * \param prefix If you need a specific prefix output on each line, give it here, may be NULL.
460  *
461  * \since 13.33.0, 16.10.0, 17.4.0
462  */
463 void ast_acl_output(int fd, struct ast_acl_list *acl, const char *prefix);
464 
465 #if defined(__cplusplus) || defined(c_plusplus)
466 }
467 #endif
468 
469 #endif /* _ASTERISK_ACL_H */
struct ast_ha * next
Definition: acl.h:56
struct ast_ha * ast_duplicate_ha_list(struct ast_ha *original)
Duplicate the contents of a list of host access rules.
Definition: acl.c:277
unsigned int cos
Definition: chan_iax2.c:352
#define AST_LIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
Definition: linkedlists.h:172
int ast_find_ourip(struct ast_sockaddr *ourip, const struct ast_sockaddr *bindaddr, int family)
Find our IP address.
Definition: acl.c:1052
struct ast_sockaddr addr
Definition: acl.h:53
char * address
Definition: f2c.h:59
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
void ast_acl_output(int fd, struct ast_acl_list *acl, const char *prefix)
output an ACL to the provided fd
Definition: acl.c:1099
enum ast_cc_service_type service
Definition: chan_sip.c:949
enum ast_acl_sense ast_apply_ha(const struct ast_ha *ha, const struct ast_sockaddr *addr)
Apply a set of rules to a given IP address.
Definition: acl.c:808
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 ...
enum ast_acl_sense sense
Definition: acl.h:55
void ast_ha_join_cidr(const struct ast_ha *ha, struct ast_str **buf)
Convert HAs to a comma separated string value using CIDR notation.
Definition: acl.c:745
Wrapper for an ast_acl linked list.
Definition: acl.h:76
int ast_str2tos(const char *value, unsigned int *tos)
Convert a string to the appropriate TOS value.
Definition: acl.c:967
I/O Management (derived from Cheops-NG)
int value
Definition: syslog.c:37
enum ast_acl_sense ast_apply_acl_nolog(struct ast_acl_list *acl_list, const struct ast_sockaddr *addr)
Apply a set of rules to a given IP address, don&#39;t log failure.
Definition: acl.c:804
Socket address structure.
Definition: netsock2.h:97
void ast_ha_join(const struct ast_ha *ha, struct ast_str **buf)
Convert HAs to a comma separated string value.
Definition: acl.c:723
unsigned int tos
Definition: chan_iax2.c:351
internal representation of ACL entries In principle user applications would have no need for this...
Definition: acl.h:51
int is_realtime
Definition: acl.h:69
int ast_ouraddrfor(const struct ast_sockaddr *them, struct ast_sockaddr *us)
Get our local IP address when contacting a remote host.
Definition: acl.c:1005
struct ast_acl_list * ast_duplicate_acl_list(struct ast_acl_list *original)
Duplicates the contests of a list of lists of host access rules.
Definition: acl.c:316
struct ast_sockaddr netmask
Definition: acl.h:54
ast_acl_sense
Definition: acl.h:36
int is_invalid
Definition: acl.h:70
struct ast_ha * acl
Definition: acl.h:68
A set of macros to manage forward-linked lists.
an ast_acl is a linked list node of ast_ha structs which may have names.
Definition: acl.h:67
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
Network socket handling.
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
Wrapper for network related headers, masking differences between various operating systems...
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
struct ast_acl_list * ast_free_acl_list(struct ast_acl_list *acl)
Free a list of ACLs.
Definition: acl.c:233
#define ACL_NAME_LENGTH
Definition: acl.h:59
int ast_get_ip(struct ast_sockaddr *addr, const char *hostname)
Get the IP address given a hostname.
Definition: acl.c:1000
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
Definition: linkedlists.h:409
Definition: test_acl.c:111
static const char name[]
Definition: cdr_mysql.c:74
int ast_str2cos(const char *value, unsigned int *cos)
Convert a string to the appropriate COS value.
Definition: acl.c:953
int ast_lookup_iface(char *iface, struct ast_sockaddr *address)
Find an IP address associated with a specific interface.
int ast_get_ip_or_srv(struct ast_sockaddr *addr, const char *hostname, const char *service)
Get the IP address given a hostname and optional service.
Definition: acl.c:897
void ast_free_ha(struct ast_ha *ha)
Free a list of HAs.
Definition: acl.c:222
struct ast_ha * ast_named_acl_find(const char *name, int *is_realtime, int *is_undefined)
Retrieve a named ACL.
Definition: named_acl.c:293
struct ast_ha * ast_append_ha_with_port(const char *sense, const char *stuff, struct ast_ha *path, int *error)
Add a new rule with optional port to a list of HAs.
Definition: acl.c:718
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
void ast_ha_output(int fd, const struct ast_ha *ha, const char *prefix)
output an HA to the provided fd
Definition: acl.c:1087
static struct ast_str * hostname
Definition: cdr_mysql.c:77
struct ast_ha * ast_append_ha(const char *sense, const char *stuff, struct ast_ha *path, int *error)
Add a new rule to a list of HAs.
Definition: acl.c:713
int error(const char *format,...)
Definition: utils/frame.c:999
const char * ast_tos2str(unsigned int tos)
Convert a TOS value into its string representation.
Definition: acl.c:987
struct ast_sockaddr bindaddr
Definition: chan_ooh323.c:353
void ast_copy_ha(const struct ast_ha *from, struct ast_ha *to)
Copy the contents of one HA to another.
Definition: acl.c:255
static char prefix[MAX_PREFIX]
Definition: http.c:141