summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlfred E. Heggestad <aeh@db.org>2015-02-14 21:21:42 +0100
committerAlfred E. Heggestad <aeh@db.org>2015-02-14 21:21:42 +0100
commit503c111c88b9a447a64bd84ab7e2d1d57a2e27ef (patch)
tree864e1cd806efedee593530cce1f36d10984bfa0f /src
parent01bff9428954948da5f05098cb70aac971865f72 (diff)
contact: add access-parameter
- basic access-control for incoming calls, originally based on a patch from Doug Blewett (thanks!) - each contact-entry can optionally have a ;access={block,allow} parameter. - add a hash-table for all contacts for fast lookup
Diffstat (limited to 'src')
-rw-r--r--src/contact.c107
-rw-r--r--src/ua.c15
2 files changed, 122 insertions, 0 deletions
diff --git a/src/contact.c b/src/contact.c
index c06c7a1..e8e6df6 100644
--- a/src/contact.c
+++ b/src/contact.c
@@ -7,20 +7,30 @@
#include <baresip.h>
+enum access {
+ ACCESS_UNKNOWN = 0,
+ ACCESS_BLOCK,
+ ACCESS_ALLOW
+};
+
struct contact {
struct le le;
+ struct le he; /* hash-element with key 'auri' */
struct sip_addr addr;
char *buf;
enum presence_status status;
+ enum access access;
};
static struct list cl;
+static struct hash *cht;
static void destructor(void *arg)
{
struct contact *c = arg;
+ hash_unlink(&c->he);
list_unlink(&c->le);
mem_deref(c->buf);
}
@@ -40,6 +50,9 @@ int contact_add(struct contact **contactp, const struct pl *addr)
struct pl pl;
int err;
+ if (!cht)
+ return EINVAL;
+
c = mem_zalloc(sizeof(*c), destructor);
if (!c)
return ENOMEM;
@@ -56,9 +69,28 @@ int contact_add(struct contact **contactp, const struct pl *addr)
goto out;
}
+ if (0 == msg_param_decode(&c->addr.params, "access", &pl)) {
+
+ if (0 == pl_strcasecmp(&pl, "block")) {
+ c->access = ACCESS_BLOCK;
+ }
+ else if (0 == pl_strcasecmp(&pl, "allow")) {
+ c->access = ACCESS_ALLOW;
+ }
+ else {
+ warning("contact: unknown 'access=%r' for '%r'\n",
+ &pl, addr);
+ err = EINVAL;
+ goto out;
+ }
+ }
+ else
+ c->access = ACCESS_UNKNOWN;
+
c->status = PRESENCE_UNKNOWN;
list_append(&cl, &c->le, c);
+ hash_append(cht, hash_joaat_pl(&c->addr.auri), &c->he, c);
out:
if (err)
@@ -159,3 +191,78 @@ int contacts_print(struct re_printf *pf, void *unused)
return err;
}
+
+
+/**
+ * Initialise the contacts sub-system
+ *
+ * @return 0 if success, otherwise errorcode
+ */
+int contact_init(void)
+{
+ int err = 0;
+
+ if (!cht)
+ err = hash_alloc(&cht, 32);
+
+ return err;
+}
+
+
+/**
+ * Close the contacts sub-system
+ */
+void contact_close(void)
+{
+ hash_clear(cht);
+ cht = mem_deref(cht);
+ list_flush(&cl);
+}
+
+
+static bool find_handler(struct le *le, void *arg)
+{
+ struct contact *c = le->data;
+
+ return 0 == pl_strcmp(&c->addr.auri, arg);
+}
+
+
+/**
+ * Lookup a SIP uri in all registered contacts
+ *
+ * @param uri SIP uri to lookup
+ *
+ * @return Matching contact if found, otherwise NULL
+ */
+struct contact *contact_find(const char *uri)
+{
+ return list_ledata(hash_lookup(cht, hash_joaat_str(uri),
+ find_handler, (void *)uri));
+}
+
+
+/**
+ * Check the access parameter of a SIP uri
+ *
+ * - Matching uri has first presedence
+ * - Global <sip:*@*> uri has second presedence
+ *
+ * @param uri SIP uri to check for access
+ *
+ * @return True if blocked, false if allowed
+ */
+bool contact_block_access(const char *uri)
+{
+ struct contact *c;
+
+ c = contact_find(uri);
+ if (c && c->access != ACCESS_UNKNOWN)
+ return c->access == ACCESS_BLOCK;
+
+ c = contact_find("sip:*@*");
+ if (c && c->access != ACCESS_UNKNOWN)
+ return c->access == ACCESS_BLOCK;
+
+ return false;
+}
diff --git a/src/ua.c b/src/ua.c
index 5aeb3bf..b6dab07 100644
--- a/src/ua.c
+++ b/src/ua.c
@@ -266,6 +266,16 @@ static void call_event_handler(struct call *call, enum call_event ev,
switch (ev) {
case CALL_EVENT_INCOMING:
+
+ if (contact_block_access(peeruri)) {
+
+ info("ua: blocked access: \"%s\"\n", peeruri);
+
+ ua_event(ua, UA_EVENT_CALL_CLOSED, call, str);
+ mem_deref(call);
+ break;
+ }
+
switch (ua->acc->answermode) {
case ANSWERMODE_EARLY:
@@ -1157,6 +1167,10 @@ int ua_init(const char *software, bool udp, bool tcp, bool tls,
play_init();
+ err = contact_init();
+ if (err)
+ return err;
+
/* Initialise Network */
err = net_init(&cfg->net, prefer_ipv6 ? AF_INET6 : AF_INET);
if (err) {
@@ -1219,6 +1233,7 @@ void ua_close(void)
net_close();
play_close();
ui_reset();
+ contact_close();
uag.evsock = mem_deref(uag.evsock);
uag.sock = mem_deref(uag.sock);