Named ACLs: Introduces a system for creating and sharing ACLs
[asterisk/asterisk.git] / include / asterisk / acl.h
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2012, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
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
36 enum ast_acl_sense {
37         AST_SENSE_DENY,
38         AST_SENSE_ALLOW
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 */
53         struct ast_sockaddr addr;
54         struct ast_sockaddr netmask;
55         enum ast_acl_sense sense;
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. */
72         AST_LIST_ENTRY(ast_acl) list;
73 };
74
75 /*! \brief Wrapper for an ast_acl linked list. */
76 AST_LIST_HEAD(ast_acl_list, ast_acl);
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  */
100 struct ast_acl_list *ast_free_acl_list(struct ast_acl_list *acl);
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 rule to an ACL struct
139  *
140  * \details
141  * This adds a named ACL or an ACL rule to an ast_acl container.
142  * It works in a similar way to ast_append_ha.
143  *
144  * \param sense Can be any among "permit", "deny", or "acl"
145  *        this controls whether the rule being added will simply modify the unnamed ACL at the head of the list
146  *        or if a new named ACL will be added to that ast_acl.
147  * \param stuff If sense is 'permit'/'deny', this is the ip address and subnet mask separated with a '/' like in ast_append ha.
148  *        If it sense is 'acl', then this will be the name of the ACL being appended to the container.
149  * \param path Address of the ACL list being appended
150  * \param[out] error The int that error points to will be set to 1 if an error occurs.
151  * \param[out] named_acl_flag This will raise a flag under certain conditions to indicate that a named ACL has been added by this
152  *        operation. This may be used to indicate that an event subscription should be made against the named ACL subsystem.
153  *        Note: This flag may be raised by this function, but it will never be lowered by it.
154  */
155 void ast_append_acl(const char *sense, const char *stuff, struct ast_acl_list **path, int *error, int *named_acl_flag);
156
157 /*!
158  * \brief Determines if an ACL is empty or if it contains entries
159  *
160  * \param acl_list The ACL list being checked
161  * \retval 0 - the list is not empty
162  * \retval 1 - the list is empty
163  */
164 int ast_acl_list_is_empty(struct ast_acl_list *acl_list);
165
166 /*!
167  * \brief Apply a set of rules to a given IP address
168  *
169  * \details
170  * The list of host access rules is traversed, beginning with the
171  * input rule. If the IP address given matches a rule, the "sense"
172  * of that rule is used as the return value. Note that if an IP
173  * address matches multiple rules that the last one matched will be
174  * the one whose sense will be returned.
175  *
176  * \param ha The head of the list of host access rules to follow
177  * \param addr An ast_sockaddr whose address is considered when matching rules
178  * \retval AST_SENSE_ALLOW The IP address passes our ACL
179  * \retval AST_SENSE_DENY The IP address fails our ACL
180  */
181 enum ast_acl_sense ast_apply_ha(const struct ast_ha *ha, const struct ast_sockaddr *addr);
182
183 /*!
184  * \brief Apply a set of rules to a given IP address
185  *
186  * \details
187  * Similar to the above, only uses an acl container, which is a whole slew
188  * of ast_ha lists. It runs ast_apply_ha on each of the ast_ha structs
189  * contained in the acl container. It will deny if any of the ast_ha lists
190  * fail, and it will pass only if all of the rules pass.
191  *
192  * \param acl The head of the list of ACLs to evaluate
193  * \param addr An ast_sockaddr whose address is considered when matching rules
194  * \param purpose Context for which the ACL is being applied - Establishes purpose of a notice when rejected
195  *
196  * \retval AST_SENSE_ALLOW The IP address passes our ACLs
197  * \retval AST_SENSE_DENY The IP address fails our ACLs
198  */
199 enum ast_acl_sense ast_apply_acl(struct ast_acl_list *acl_list, const struct ast_sockaddr *addr, const char *purpose);
200
201 /*!
202  * \brief Get the IP address given a hostname
203  *
204  * \details
205  * Similar in nature to ast_gethostbyname, except that instead
206  * of getting an entire hostent structure, you instead are given
207  * only the IP address inserted into a ast_sockaddr structure.
208  *
209  * \param addr The IP address found.  The address family is used
210  * as an input parameter to filter the returned addresses.  If
211  * it is 0, both IPv4 and IPv6 addresses can be returned.
212  * \param hostname The hostname to look up
213  *
214  * \retval 0 Success
215  * \retval -1 Failure
216  */
217 int ast_get_ip(struct ast_sockaddr *addr, const char *hostname);
218
219 /*!
220  * \brief Get the IP address given a hostname and optional service
221  *
222  * \details
223  * If the service parameter is non-NULL, then an SRV lookup will be made by
224  * prepending the service to the hostname parameter, separated by a '.'
225  * For example, if hostname is "example.com" and service is "_sip._udp" then
226  * an SRV lookup will be done for "_sip._udp.example.com". If service is NULL,
227  * then this function acts exactly like a call to ast_get_ip.
228  *
229  * \param addr The IP address found.  The address family is used
230  * as an input parameter to filter the returned addresses.  If
231  * it is 0, both IPv4 and IPv6 addresses can be returned.
232  *
233  * \param hostname The hostname to look up
234  * \param service A specific service provided by the host. A NULL service results
235  * in an A-record lookup instead of an SRV lookup
236  * \retval 0 Success
237  * \retval -1 Failure
238  */
239 int ast_get_ip_or_srv(struct ast_sockaddr *addr, const char *hostname, const char *service);
240
241 /*!
242  * \brief Get our local IP address when contacting a remote host
243  *
244  * \details
245  * This function will attempt to connect(2) to them over UDP using a source
246  * port of 5060. If the connect(2) call is successful, then we inspect the
247  * sockaddr_in output parameter of connect(2) to determine the IP address
248  * used to connect to them. This IP address is then copied into us.
249  *
250  * \param them The IP address to which we wish to attempt to connect
251  * \param[out] us The source IP address used to connect to them
252  * \retval -1 Failure
253  * \retval 0 Success
254  */
255 int ast_ouraddrfor(const struct ast_sockaddr *them, struct ast_sockaddr *us);
256
257 /*!
258  * \brief Find an IP address associated with a specific interface
259  *
260  * \details
261  * Given an interface such as "eth0" we find the primary IP address
262  * associated with it using the SIOCGIFADDR ioctl. If the ioctl call
263  * should fail, we populate address with 0s.
264  *
265  * \note
266  * This function is not actually used anywhere
267  *
268  * \param iface The interface name whose IP address we wish to find
269  * \param[out] address The interface's IP address is placed into this param
270  * \retval -1 Failure. address is filled with 0s
271  * \retval 0 Success
272  */
273 int ast_lookup_iface(char *iface, struct ast_sockaddr *address);
274
275 /*!
276  * \brief Duplicate the contents of a list of host access rules
277  *
278  * \details
279  * A deep copy of all ast_has in the list is made. The returned
280  * value is allocated on the heap and must be freed independently
281  * of the input parameter when finished.
282  *
283  * \param original The ast_ha to copy
284  * \retval The head of the list of duplicated ast_has
285  */
286 struct ast_ha *ast_duplicate_ha_list(struct ast_ha *original);
287
288 /*!
289  * \brief Duplicates the contests of a list of lists of host access rules.
290  *
291  * \details
292  * A deep copy of an ast_acl list is made (which in turn means a deep copy of
293  * each of the ast_ha structs contained within). The returned value is allocated
294  * on the heap and must be freed independently of the input paramater when
295  * finished.
296  *
297  * \param original The ast_acl_list to copy
298  * \retval The new duplicated ast_acl_list
299  */
300 struct ast_acl_list *ast_duplicate_acl_list(struct ast_acl_list *original);
301
302 /*!
303  * \brief Find our IP address
304  *
305  * \details
306  * This function goes through many iterations in an attempt to find
307  * our IP address. If any step along the way should fail, we move to the
308  * next item in the list. Here are the steps taken:
309  * - If bindaddr has a non-zero IP address, that is copied into ourip
310  * - We use a combination of gethostname and ast_gethostbyname to find our
311  *   IP address.
312  * - We use ast_ouraddrfor with 198.41.0.4 as the destination IP address
313  * - We try some platform-specific socket operations to find the IP address
314  *
315  * \param[out] ourip Our IP address is written here when it is found
316  * \param bindaddr A hint used for finding our IP. See the steps above for
317  * more details
318  * \param family Only addresses of the given family will be returned. Use 0
319  * or AST_SOCKADDR_UNSPEC to get addresses of all families.
320  * \retval 0 Success
321  * \retval -1 Failure
322  */
323 int ast_find_ourip(struct ast_sockaddr *ourip, const struct ast_sockaddr *bindaddr, int family);
324
325 /*!
326  * \brief Convert a string to the appropriate COS value
327  *
328  * \param value The COS string to convert
329  * \param[out] cos The integer representation of that COS value
330  * \retval -1 Failure
331  * \retval 0 Success
332  */
333 int ast_str2cos(const char *value, unsigned int *cos);
334
335 /*!
336  * \brief Convert a string to the appropriate TOS value
337  *
338  * \param value The TOS string to convert
339  * \param[out] tos The integer representation of that TOS value
340  * \retval -1 Failure
341  * \retval 0 Success
342  */
343 int ast_str2tos(const char *value, unsigned int *tos);
344
345 /*!
346  * \brief Convert a TOS value into its string representation
347  *
348  * \param tos The TOS value to look up
349  * \return The string equivalent of the TOS value
350  */
351 const char *ast_tos2str(unsigned int tos);
352
353 /*!
354  * \brief Retrieve a named ACL
355  *
356  * \details
357  * This function attempts to find a named ACL. If found, a copy
358  * of the requested ACL will be made which must be freed by
359  * the caller.
360  *
361  * \param name Name of the ACL sought
362  * \param[out] is_realtime will be true if the ACL being returned is from realtime
363  * \param[out] is_undefined will be true if no ACL profile can be found for the requested name
364  *
365  * \retval A copy of the named ACL as an ast_ha
366  * \retval NULL if no ACL could be found.
367  */
368 struct ast_ha *ast_named_acl_find(const char *name, int *is_realtime, int *is_undefined);
369
370 /*!
371  * \brief Initialize and configure the named ACL system.
372  *
373  * \details
374  * This function will prepare the named ACL system for use.
375  * For this reason, it needs to be called before other things that use ACLs are initialized.
376  */
377 int ast_named_acl_init(void);
378
379 /*!
380  * \brief reload/reconfigure the named ACL system.
381  *
382  * \details
383  * This function is designed to trigger an event upon a successful reload that may update
384  * ACL consumers.
385  */
386 int ast_named_acl_reload(void);
387
388 #if defined(__cplusplus) || defined(c_plusplus)
389 }
390 #endif
391
392 #endif /* _ASTERISK_ACL_H */