[asterisk-commits] oej: branch oej/deluxepine-trunk r237248 - in /team/oej/deluxepine-trunk: inc...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Sun Jan 3 04:40:54 CST 2010


Author: oej
Date: Sun Jan  3 04:40:51 2010
New Revision: 237248

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=237248
Log:
Just adding the files, doesn't compile cleanly yet

Added:
    team/oej/deluxepine-trunk/include/asterisk/nacl.h   (with props)
    team/oej/deluxepine-trunk/main/nacl.c   (with props)

Added: team/oej/deluxepine-trunk/include/asterisk/nacl.h
URL: http://svnview.digium.com/svn/asterisk/team/oej/deluxepine-trunk/include/asterisk/nacl.h?view=auto&rev=237248
==============================================================================
--- team/oej/deluxepine-trunk/include/asterisk/nacl.h (added)
+++ team/oej/deluxepine-trunk/include/asterisk/nacl.h Sun Jan  3 04:40:51 2010
@@ -1,0 +1,75 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2009-2010, Edvina AB
+ *
+ * Olle E. Johansson <oej at edvina.net>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+#ifndef ASTERISK_NACL_H
+#define ASTERISK_NACL_H
+
+
+/*! \file
+ *
+ * \brief Named Access Control Lists (nacl)
+ *
+ * \author Olle E. Johansson <oej at edvina.net>
+ */
+
+/*! \brief Structure for named ACL */
+/*! \brief Structure for named ACL */
+struct ast_nacl {
+	char name[MAXHOSTNAMELEN];		/*!< Name of this ACL */
+	struct ast_ha *acl;			/*!< The actual ACL */
+	int rules;				/*!< Number of ACL rules */
+	int delete;				/*!< Mark this object for deletion */
+	int manipulated;			/*!< Manipulated by CLI or manager */
+	char owner[20];				/*!< Owner (module) */
+	char desc[80];				/*!< Description */
+};
+
+/*! \brief Add named ACL to list (done from configuration file or module) */
+struct ast_nacl *ast_nacl_add(const char *name, const char *owner);
+
+/*! \brief Find a named ACL 
+	if deleted is true, we will find deleted items too
+	if owner is NULL, we'll find all otherwise owner is used for selection too
+*/
+struct ast_nacl *ast_nacl_find_all(const char *name, const int deleted, const char *owner);
+
+/*! \brief Find a named ACL (that is not marked with the delete flag) 
+ */
+struct ast_nacl *ast_nacl_find(const char *name);
+
+/*! \brief Mark all the owned NACLs
+*/
+int ast_nacl_mark_all_owned(const char *owner);
+
+/*! \brief Attach to a named ACL. You need to detach later 
+	This is to avoid Named ACLs to disappear from runtime. Even if they are deleted from the
+	configuration, they will still be around thanks to ASTOBJs
+ */
+struct ast_nacl *ast_nacl_attach(const char *name);
+
+/*! \brief Detach from a named ACL. 
+	If it's marked for deletion and refcount is zero, then it's deleted
+ */
+void ast_nacl_detach(struct ast_nacl *nacl);
+
+/*! \brief Initialize NACL subsystem */
+int ast_nacl_load(void);
+
+/*! \brief re-nitialize NACL subsystem */
+int ast_nacl_reload(void);
+
+#endif /* ASTERISK_NACL_H */

Propchange: team/oej/deluxepine-trunk/include/asterisk/nacl.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/oej/deluxepine-trunk/include/asterisk/nacl.h
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Propchange: team/oej/deluxepine-trunk/include/asterisk/nacl.h
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: team/oej/deluxepine-trunk/main/nacl.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/deluxepine-trunk/main/nacl.c?view=auto&rev=237248
==============================================================================
--- team/oej/deluxepine-trunk/main/nacl.c (added)
+++ team/oej/deluxepine-trunk/main/nacl.c Sun Jan  3 04:40:51 2010
@@ -1,0 +1,731 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2009-2010, Edvina AB
+ *
+ * Olle E. Johansson <oej at edvina.net>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Named Access Control Lists (nacl)
+ *
+ * \author Olle E. Johansson <oej at edvina.net>
+ */
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 237134 $")
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "asterisk/acl.h"
+#include "asterisk/astobj2.h"
+#include "asterisk/config.h"
+#include "asterisk/manager.h"
+#include "asterisk/logger.h"
+#include "asterisk/cli.h"
+#include "asterisk/options.h"
+#include "asterisk/utils.h"
+#include "asterisk/lock.h"
+#include "asterisk/nacl.h"
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define NACL_LOAD	1
+#define NACL_RELOAD	2
+
+
+enum nacl_ops {
+	NACL_ADD,
+	NACL_DEL,
+	NACL_UNKNOWN = 0,
+};
+
+enum rule_ops {
+	HA_PERMIT,
+	HA_DENY,
+	HA_UNKNOWN = 0,
+};
+
+static struct nacloptext_def {
+	enum nacl_ops op;
+	const char *text;
+}  nops[] = {
+	{ NACL_ADD, "add" },	
+	{ NACL_DEL, "del" },	
+};
+
+static struct naclrule_def {
+	enum rule_ops op;
+	const char *text;
+} rops[] = {
+	{ HA_PERMIT, "permit" },
+	{ HA_DENY, "deny" },
+};
+
+
+
+
+/*! \brief the list of NACLs */
+struct ao2_container *nacl_list;
+
+static enum nacl_ops find_naclop(const char *op)
+{
+	int i;
+
+	for (i = 0; (i < (sizeof(nops) / sizeof(nops[0]))); i++) {
+		if (!strcasecmp(nops[i].text, op)) {
+			return nops[i].op;
+		}
+	}
+	return NACL_UNKNOWN;
+}
+
+static enum rule_ops find_naclrule(const char *rule)
+{
+	int i;
+
+	for (i = 0; (i < (sizeof(rops) / sizeof(rops[0]))); i++) {
+		if (!strcasecmp(rops[i].text, rule)) {
+			return rops[i].op;
+		}
+	}
+	return HA_UNKNOWN;
+}
+
+static const char *find_naclruletext(enum rule_ops op)
+{
+	int i;
+
+	for (i = 0; (i < (sizeof(rops) / sizeof(rops[0]))); i++) {
+		if (op == rops[i].op) {
+			return rops[i].text;
+		}
+	}
+	return NULL;
+}
+
+/*! \brief destroy a NACL 
+*/
+static void nacl_destroy(void *obj)
+{
+	struct ast_nacl *nacl = obj;
+	if (option_debug > 2)
+		ast_log(LOG_DEBUG, "--- Destruction of NACL %s is NOW. Please have a safe distance.\n", nacl->name);
+	if (nacl->acl)
+		ast_free_ha(nacl->acl);
+}
+
+
+/*! \brief Add named ACL to list (done from configuration file or module) 
+	Internal ACLs, created by Asterisk modules, should use a name that
+	begins with "ast_". These are prevented from configuration in nacl.conf
+ */
+struct ast_nacl *ast_nacl_add(const char *name, const char *owner)
+{
+	struct ast_nacl *nacl;
+	
+	if (ast_strlen_zero(name)) {
+		ast_log(LOG_WARNING, "Zero length name.\n");
+		return NULL;
+	}
+
+	nacl = ao2_alloc(sizeof(struct ast_nacl), nacl_destroy);
+
+	ast_copy_string(nacl->name, name, sizeof(nacl->name));
+	ast_copy_string(nacl->owner, owner, sizeof(nacl->owner));
+
+	ao2_link(nacl_list,nacl);
+
+ 	if (option_debug > 2) {
+		ast_log(LOG_DEBUG, "Added named ACL '%s'\n", name);
+	}
+
+	return nacl;
+}
+
+/* Copied from app_queue.c */
+static int compress_char(const char c)
+{
+	if (c < 32)
+		return 0;
+	else if (c > 96)
+		return c - 64;
+	else
+		return c - 32;
+}
+
+/*! \brief ao2 function to create unique hash of object */
+static int nacl_hash_fn(const void *obj, const int flags)
+{
+	const struct ast_nacl *nacl = obj;
+	int ret = 0, i;
+
+	for (i = 0; i < strlen(nacl->name) && nacl->name[i]; i++)
+		ret += compress_char(nacl->name[i]) << (i * 6);
+	return ret;
+}
+
+/*! \brief ao2 function to compare objects */
+static int nacl_cmp_fn(void *obj1, void *obj2, int flags)
+{
+	struct ast_nacl *nacl1 = obj1, *nacl2 = obj2;
+	return strcmp(nacl1->name, nacl2->name) ? 0 : CMP_MATCH | CMP_STOP;
+}
+
+
+/*! \brief Find a named ACL 
+	if deleted is true, we will find deleted items too
+	if owner is NULL, we'll find all otherwise owner is used for selection too
+	We raise the refcount on the result, which the calling function need to deref.
+*/
+struct ast_nacl *ast_nacl_find_all(const char *name, const int deleted, const char *owner)
+{
+	struct ast_nacl *found = NULL;
+	struct ao2_iterator i;
+	struct ast_nacl *nacl = NULL;
+
+	i = ao2_iterator_init(nacl_list, 0);
+
+	ao2_lock(nacl_list);
+	while ((nacl = ao2_iterator_next(&i))) {
+		ao2_lock(nacl);
+
+		if (!strcasecmp(nacl->name, name) && (owner == NULL || !strcasecmp(nacl->owner,owner))) {
+			if(nacl->delete) {
+				if (deleted) {
+					found = nacl;
+					ao2_unlock(nacl);
+					continue;
+				}
+			} else {
+				found = nacl;
+				ao2_unlock(nacl);
+				continue;
+			}
+		}
+		ao2_unlock(nacl);
+                ao2_ref(nacl, -1);
+	};
+	ao2_unlock(nacl_list);
+	ao2_iterator_destroy(&i);
+
+	return found;
+}
+
+/*! \brief Find a named ACL 
+*/
+struct ast_nacl *ast_nacl_find(const char *name)
+{
+	return ast_nacl_find_all(name, 0, NULL);
+}
+
+/*! \brief MarkClear all named ACLs owned by us 
+	Mark the others as deletion ready.
+*/
+int ast_nacl_mark_all_owned(const char *owner)
+{
+	int pruned = 0;
+	struct ao2_iterator i;
+	struct ast_nacl *nacl = NULL;
+
+	i = ao2_iterator_init(nacl_list, 0);
+
+	ao2_lock(nacl_list);
+	while ((nacl = ao2_iterator_next(&i))) {
+		ao2_lock(nacl);
+		if (owner == NULL || !strcasecmp(nacl->owner, owner)) {
+			nacl->delete = TRUE;
+			pruned++;
+		}
+		ao2_unlock(nacl);
+	}; 
+	ao2_unlock(nacl_list);
+	return pruned;
+}
+
+
+/*! \brief Attach to a named ACL. You need to detach later 
+	This is to avoid Named ACLs to disappear from runtime. Even if they are deleted from the
+	configuration, they will still be around
+	\note Deleted NACLs won't be found any more with this function, to avoid adding to the use
+		of these ACLs
+ */
+struct ast_nacl *ast_nacl_attach(const char *name)
+{
+	struct ast_nacl *nacl;
+	if (!name) {
+		return NULL;
+	}
+	nacl = ast_nacl_find(name);
+	if (!nacl) {
+		return NULL;
+	}
+	return nacl;
+}
+
+/*! \brief Detach from a named ACL. 
+	If it's marked for deletion and refcount is zero, then it's deleted
+ */
+void ast_nacl_detach(struct ast_nacl *nacl)
+{
+	if (!nacl) {
+		return; /* What's up, doc? */
+	}
+	ao2_ref(nacl, -1);
+}
+
+/*! Unref all objects with delete=1 */
+static int nacl_delete_marked(void)
+{
+	int pruned = 0;
+	struct ao2_iterator i;
+	struct ast_nacl *nacl = NULL;
+
+	i = ao2_iterator_init(nacl_list, 0);
+
+	ao2_lock(nacl_list);
+	while ((nacl = ao2_iterator_next(&i))) {
+		if (nacl->delete) {
+			ao2_ref(nacl, -1);
+			pruned++;
+		}
+	}; 
+	ao2_unlock(nacl_list);
+	return pruned;
+}
+
+/*! \brief Update a HA list by inserting or deleting a row at a specific position 
+	if inser is false, it means delete
+*/
+static struct ast_ha *ha_update(struct ast_ha *ha, int line, int insert, struct ast_ha *new)
+{
+	struct ast_ha *next = ha;
+	struct ast_ha *temp = NULL;
+	int rule = 0;
+
+	/* IF we have nothing to insert, just give up */
+	if (insert && !new) {
+		return ha;
+	}
+
+	ast_log(LOG_DEBUG, "--- Operation %s requested line %d\n", insert?"insert":"delete", line);
+
+	/* If there's no existing ha we have nothing to delete */
+	if (!ha) {
+		if (!insert) {
+			return NULL;
+		} else {
+			return new;
+		}
+	}
+
+	/* Insert or delete at top */
+	if (line <= 1) {
+		if (insert) {
+			if (next == NULL) {
+				return new;
+			}
+			ast_log(LOG_DEBUG, "---  inserting at start\n");
+			new->next = next;
+			return new;
+		} else {	/* Delete first rule */
+			temp = next->next;
+			ast_log(LOG_DEBUG, "---  deleting first line\n");
+			free(next);
+			return temp;
+		}
+	}
+
+	for (rule=1; (rule <= line && next != NULL); rule++) {
+		ast_log(LOG_DEBUG, "\n---  Rule %d ", rule);
+		if (rule == line) {
+			/* Ok, we are here */
+			if (insert) {
+				ast_log(LOG_DEBUG, "---  inserting\n");
+				/* Insert */
+				new->next = temp->next;
+				temp->next = new;
+			} else {
+				ast_log(LOG_DEBUG, "---  deleting\n");
+				/* Delete */
+				temp->next = next->next;	/* The one to delete */
+				free(next);
+			}
+			return ha;
+		}
+		temp = next;	/* The previous NACL */
+		next = next->next;
+	}
+	/* If we are here, the line number was greater than the number of lines available */
+	if (insert) {
+		ast_log(LOG_DEBUG, "---  inserting\n");
+		temp->next = new;
+	}
+	return ha;
+	
+}
+
+/*! \brief Print ha list to CLI */
+static void ha_list(int fd, struct ast_ha *ha, const int rules)
+{
+	char iabuf[INET_ADDRSTRLEN];
+	char iabuf2[INET_ADDRSTRLEN];
+	int rulesfound = 0;
+
+	while (ha) {
+		rulesfound++;
+		ast_copy_string(iabuf2, ast_inet_ntoa(ha->netaddr), sizeof(iabuf2));
+		ast_copy_string(iabuf, ast_inet_ntoa(ha->netmask), sizeof(iabuf));
+		ast_cli(fd,"     %-3.3d: %s: %s mask %s\n", rulesfound, (ha->sense == AST_SENSE_ALLOW) ? "permit" : "deny  ", iabuf2, iabuf);
+		ha = ha->next;
+	}
+	/* Rules is only used for configuration based nacls */
+	if (rules != 0 && rulesfound != rules) {
+		ast_cli(fd, "     NOTE: Number of rules doesn't match configuration. Please check.\n");
+	}
+}
+
+/*! \brief CLI command to list named ACLs */
+static int cli_show_nacls(int fd, int argc, char *argv[])
+{
+#define FORMAT "%-40.40s %-20.20s %5d %5d %7s\n"
+#define FORMAT2 "%-40.40s %-20.20s %-5.5s %-5.5s %7s\n"
+
+	struct ao2_iterator i;
+	struct ast_nacl *nacl;
+
+	i = ao2_iterator_init(nacl_list, 0);
+
+	ast_cli(fd, FORMAT2, "ACL name:", "Set by", "#rules", "Usage", "Flags");
+	while ((nacl = ao2_iterator_next(&i))) {
+		ast_cli(fd, FORMAT, nacl->name, 
+			S_OR(nacl->owner, "-"),
+			nacl->rules,
+			(ao2_ref(nacl, 0) -1),
+			nacl->manipulated ? "M" : "");
+		ha_list(fd, nacl->acl, nacl->rules);
+                ao2_ref(nacl, -1);
+	};
+	ao2_iterator_destroy(&i);
+	ast_cli(fd, "\nFlag M = Modified by AMI or CLI\n");
+	return RESULT_SUCCESS;
+}
+#undef FORMAT
+#undef FORMAT2
+
+/*! \brief Update NACL (or create it if it doesn't exist) */
+static int nacl_update(int fd, const char *command, const char *name, int rule, char *operation, const char *target, const char *owner)
+{
+	struct ast_nacl *nacl;
+	struct ast_ha *newha = NULL;
+	int insert = !strcasecmp(command, "add");
+	int err = 0;
+
+	nacl = ast_nacl_find(name);
+	if (!nacl) {
+		if (!insert) {
+			ast_cli(fd, "No such NACL: %s\n", name);
+			return RESULT_SUCCESS;
+		}
+		nacl = ast_nacl_add(name, owner);
+		/* Add a ref so that both existing and new NACLs has an extra ref after nacl_find or nacl_add */
+		ast_cli(fd, "Successfully added new NACL %s\n", name);
+		ao2_ref(nacl, +1);
+	}
+	if (!insert && !nacl->acl) {
+		ast_cli(fd, "No rules to delete for NACL: %s\n", name);
+		ao2_ref(nacl, -1);
+		return RESULT_SUCCESS;
+	}
+	ao2_lock(nacl);
+	if (insert) {
+		newha = ast_append_ha(operation, target, NULL, &err);
+		if (err) {
+			ast_cli(fd, "Syntax error in new rule forNACL: %s\n", name);
+			ao2_ref(nacl, -1);
+			ao2_unlock(nacl);
+			return RESULT_SUCCESS;
+		}
+	}
+	nacl->acl = ha_update(nacl->acl, rule, insert, newha);
+	if (insert) {
+		nacl->rules++;
+	} else if (nacl->rules) {
+		nacl->rules--;
+	}
+	nacl->manipulated = TRUE;
+	ao2_ref(nacl, -1);
+	ao2_unlock(nacl);
+	return RESULT_SUCCESS;
+}
+
+static char show_nacls_usage[] = 
+"Usage: nacl show\n"
+"       Lists all configured named ACLs.\n"
+"       Named ACLs can be used in many configuration files as well as internally\n"
+"       by Asterisk.\n";
+
+static struct ast_cli_entry cli_nacl = { 
+	{ "nacl", "show", NULL },
+	cli_show_nacls, "List configured named ACLs.",
+	show_nacls_usage };
+
+/*! \brief CLI command to add named ACLs */
+static int cli_nacl_add(int fd, int argc, char *argv[])
+{
+
+	if (argc != 6) {
+		return RESULT_SHOWUSAGE;
+	}
+	if (option_debug >= 2) {
+		ast_cli(fd, "--- Command: %s %s\n", argv[0], argv[1]);
+		ast_cli(fd, "--- NACL Name: %s Operation %s\n", argv[2], argv[4]);
+		ast_cli(fd, "--- NACL line: %s Address %s\n", argv[3], argv[5]);
+	}
+	if (strcasecmp(argv[4], "permit") && strcasecmp(argv[4], "deny")) {
+		ast_cli(fd, "Error: Illegal operand %s\n", argv[4]);
+		return RESULT_SHOWUSAGE;
+	}
+	return nacl_update(fd, argv[1], argv[2], atoi(argv[3]), argv[4], argv[5], "cli");
+}
+
+/*! \brief CLI command to delete rules in named ACLs */
+static int cli_nacl_delete(int fd, int argc, char *argv[])
+{
+	if (argc != 4) {
+		return RESULT_SHOWUSAGE;
+	}
+	ast_cli(fd, "--- Command: %s %s\n", argv[0], argv[1]);
+	ast_cli(fd, "--- NACL Name: %s Line %s\n", argv[2], argv[3]);
+	return nacl_update(fd, argv[1], argv[2], atoi(argv[3]), NULL, NULL, "cli");
+}
+
+static char nacl_delete_usage[] = 
+"Usage: nacl delete <name> <number>\n"
+"       Delete a rule from a NACL.\n"
+"	The NACL will still remain in memory, even if there are no active rules\n"
+"	Please note that changes to ACLs are not stored in configuration, thuse are not\n"
+"	persistant between Asterisk restarts.\n"
+"\n";
+
+static char nacl_add_usage[] = 
+"Usage: nacl add <name> <number> [permit|deny] <address>\n"
+"       Add a rule to a specific NACL.\n"
+"	If the NACL doesn't exist, it's created. If there is an existing rule with the given\n"
+"       number, the new rule is inserted before.\n"
+"       Address is given as <ipaddress>/<netmask> or <ipaddress>/<maskbytes> (CIDR notation)\n"
+"	Please note that changes to ACLs are not stored in configuration, thuse are not\n"
+"	persistant between Asterisk restarts.\n"
+"\n";
+
+static struct ast_cli_entry clidef_nacl_add = { 
+	{ "nacl", "add", NULL },
+	cli_nacl_add, "Add a new rule to a NACL.",
+	nacl_add_usage };
+
+static struct ast_cli_entry clidef_nacl_delete = { 
+	{ "nacl", "delete", NULL },
+	cli_nacl_delete, "Delete a rule from an NACL.",
+	nacl_delete_usage };
+
+static char mandescr_naclupdate[] =
+"Description: A 'NaclUpdate' action will modify or create\n"
+"named ACLs for dynamic IP based filters.\n"
+"Variables:\n"
+"   NaclName:   Name of the NACL. If it doesn't exist, it's created on an add operation\n"
+"   NaclOp:     Operation - Add or Delete\n"
+"   RuleId:     Line number of rule to add or delete. If there is an existing rule on this\n"
+"               position on an add operation, the line is inserted at that position, before\n"
+"               the existing line. If the line number is higher than the number of lines,\n"
+"               the new line is added at the end.\n"
+"For 'add' operations, the RuleOp and RuleTarget variables are required:\n"
+"   RuleOp:     Permit or Deny\n"
+"   RuleTarget: IP address and netmask for filter, separated by slash.\n"
+"   ActionId:   Optional ID for this transaction\n"
+"\n";
+
+static int manager_naclupdate(struct mansession *s, const struct message *m)
+{
+        const char *naclname = astman_get_header(m, "NaclName");
+        const char *naclop = astman_get_header(m, "NaclOp");
+        const char *ruleid = astman_get_header(m, "RuleId");
+        const char *ruleop = astman_get_header(m, "RuleOp");
+        const char *ruletarget = astman_get_header(m, "RuleTarget");
+        const char *id = astman_get_header(m,"ActionID");
+	enum nacl_ops n_op;
+	enum rule_ops r_op = HA_UNKNOWN;
+	struct ast_nacl *nacl;
+	struct ast_ha *newha = NULL;
+	int err = 0;
+
+        char idText[256] = "";
+
+	if (ast_strlen_zero(naclname)) {
+		astman_send_error(s, m, "NaclName not specified");
+		return 0;
+	}
+	if (ast_strlen_zero(naclop)) {
+		astman_send_error(s, m, "NaclOp not specified");
+		return 0;
+	}
+	if (ast_strlen_zero(ruleid)) {
+		astman_send_error(s, m, "RuleID not specified");
+		return 0;
+	}
+	if ((n_op = find_naclop(naclop)) == NACL_UNKNOWN) {
+		astman_send_error(s, m, "Unknown NaclOP - 'add' or 'del' implemented");
+		return 0;
+	}
+	if (n_op == NACL_ADD) {
+		r_op = find_naclrule(ruleop);
+		if  (r_op  == HA_UNKNOWN) {
+			astman_send_error(s, m, "Unknown RuleOp");
+			return 0;
+		}
+		if (ast_strlen_zero(ruletarget)) {
+			astman_send_error(s, m, "RuleTarget not specified");
+			return 0;
+		}
+	}
+
+        if (!ast_strlen_zero(id)) {
+                snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
+        }
+	nacl = ast_nacl_find(naclname);
+	if (!nacl) {
+		if (n_op == NACL_DEL) {
+			astman_send_error(s, m, "Unknown NACL name");
+			return 0;
+		}
+		/* Assume ADD */
+		nacl = ast_nacl_add(naclname, "AMI");
+		/* Add a ref so that both existing and new NACLs has an extra ref after nacl_find or nacl_add */
+		ao2_ref(nacl, +1);
+	}
+	if (n_op == NACL_DEL && !nacl->acl) {
+		ao2_ref(nacl, -1);
+		astman_send_error(s, m, "No rules to delete in given NACL");
+		return 0;
+	}
+	if (n_op == NACL_ADD) {
+		newha = ast_append_ha(ruleop, ruletarget, NULL, &err);
+		if (err) {
+			astman_send_error(s,m, "Syntax error in rule.");
+			ao2_ref(nacl, -1);
+			return RESULT_SUCCESS;
+		}
+	}
+	ao2_lock(nacl);
+	nacl->acl = ha_update(nacl->acl, atoi(ruleid), (n_op == NACL_ADD), newha);
+	if (n_op == NACL_ADD) {
+		nacl->rules++;
+	} else if (nacl->rules) {
+		nacl->rules--;
+	}
+	nacl->manipulated = TRUE;
+	ao2_ref(nacl, -1);
+	ao2_unlock(nacl);
+	return 0;
+}
+ 
+
+
+/* Initialize named ACLs 
+	This function is used both at load and reload time.
+ */
+static int nacl_init(int reload_reason)
+{
+	struct ast_config *cfg;
+	struct ast_variable *v;
+	char *cat = NULL;
+	struct ast_nacl *nacl = NULL;
+	int marked = 0;
+
+
+	/* Clear all existing NACLs - or mark them for deletion */
+	marked = ast_nacl_mark_all_owned("config");
+
+	cfg = ast_config_load("nacl.conf");
+	if (cfg) {
+		while ((cat = ast_category_browse(cfg, cat))) {
+			if (!strncasecmp(cat, "ast_", 4)) {
+				ast_log(LOG_ERROR, "NACL names prefixed with ast_ are reserved for internal use. NACL not actived:  %s\n", cat);
+				continue;
+			}
+		
+			nacl = ast_nacl_find_all(cat, 1, "config");	/* Find deleted items */
+			if (nacl) {
+				nacl->delete = FALSE;
+				ast_free_ha(nacl->acl);	/* Delete existing ACL (locking needed indeed) */
+				ao2_ref(nacl, -1);	/* The find operation adds a ref */
+			} else {
+				nacl = ast_nacl_add(cat, "config");
+			}
+			v = ast_variable_browse(cfg, cat);
+			while(v) {
+				if (!strcasecmp(v->name, "permit") || !strcasecmp(v->name, "deny")) {
+					int err;
+					nacl->acl = ast_append_ha(v->name, v->value, nacl->acl, &err);
+					if (err) {
+						ast_log(LOG_ERROR, "Syntax error in ACL \"%s = %s\", line %d\n", v->name, v->value, v->lineno);
+					} else {
+						nacl->rules++;
+					}
+				} else {
+					ast_log(LOG_WARNING, "Unknown configuration option: %s\n", v->name);
+				}
+				v = v->next;
+			}
+		}
+		ast_config_destroy(cfg);
+	} 
+
+	if (marked) {
+		ao2_lock(nacl_list);
+		nacl_delete_marked();
+		ao2_unlock(nacl_list);
+	}
+
+	if (reload_reason == NACL_LOAD) {
+		ast_cli_register(&cli_nacl);
+		ast_cli_register(&clidef_nacl_add);
+		ast_cli_register(&clidef_nacl_delete);
+		ast_manager_register2("NaclUpdate", EVENT_FLAG_CONFIG, manager_naclupdate, "Update Named ACL", mandescr_naclupdate);
+	}
+	return 0;
+}
+
+/*! \brief Initialize NACL subsystem */
+int ast_nacl_load(void)
+{
+	nacl_list = ao2_container_alloc(42, nacl_hash_fn, nacl_cmp_fn);
+	return nacl_init(NACL_LOAD);
+}
+
+/*! \brief re-nitialize NACL subsystem */
+int ast_nacl_reload(void)
+{
+	return nacl_init(NACL_RELOAD);
+}

Propchange: team/oej/deluxepine-trunk/main/nacl.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/oej/deluxepine-trunk/main/nacl.c
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Propchange: team/oej/deluxepine-trunk/main/nacl.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain




More information about the asterisk-commits mailing list