From a6d9626bd8b7689ec679e0cdedef48be795dfd9e Mon Sep 17 00:00:00 2001 Message-Id: From: Mark Wooding Date: Fri, 6 May 2005 14:25:06 +0000 Subject: [PATCH] noip: set ACLs from environment variables. Organization: Straylight/Edgeware From: mdw --- noip.1 | 46 ++++++++++++++++++++--- noip.c | 113 ++++++++++++++++++++++++++++++++++----------------------- 2 files changed, 108 insertions(+), 51 deletions(-) diff --git a/noip.1 b/noip.1 index fe56efd..36b4cf0 100644 --- a/noip.1 +++ b/noip.1 @@ -81,7 +81,11 @@ in the calling user's home directory, as determined by the .B HOME environment, or, failing that, looking up the .I real -(not effective) user id in the password database. +(not effective) user id in the password database. However, if the +environment variable +.B NOIP_CONFIG +is set, then the file it names is read instead (assuming it exists; if +it doesn't, no configuration is read). .PP The configuration file has a simple line-based format. A line is ignored if it consists only of whitespace, or if its first whitespace @@ -106,7 +110,9 @@ can be used to control this. .BI "socketdir " directory Store the Unix-domain sockets in .IR directory -rather than the default. +rather than the default. The environment variable +.B NOIP_SOCKETDIR +can also be used to control which directory is used for sockets. .TP .BI "realbind " acl-entry Add an entry to the @@ -117,9 +123,23 @@ a socket to an address, the .B realbind ACL is consulted. If the address is matched, then the program is allowed to bind a real Internet socket to that address; otherwise, the -socket is bound to a Unix-domain socket. +socket is bound to a Unix-domain socket. Three environment variables +are consulted too: +.BR NOIP_REALBIND_BEFORE , +.BR NOIP_REALBIND , +and +.BR NOIP_REALBIND_AFTER . +The +.B _BEFORE +rules are inserted at the front of the list; the +.B _AFTER +rules are appended on the end. Currently, the rules in +.B NOIP_REALBIND +are also put at the end (before the +.B _AFTER +rules), though this may change later. .TP -.BI "realbind " acl-entry +.BI "realconnect " acl-entry Add an entry to the .B realconnect access control list (ACL). When a program attempts to @@ -132,7 +152,21 @@ the .B realconnect ACL is consulted. If the destination address is matched, then the program is allowed to contact the real Internet socket; otherwise, the -attempt is made to contact a Unix-domain socket. +attempt is made to contact a Unix-domain socket. Three environment variables +are consulted too: +.BR NOIP_REALCONNET_BEFORE , +.BR NOIP_REALCONNECT , +and +.BR NOIP_REALCONNECT_AFTER . +The +.B _BEFORE +rules are inserted at the front of the list; the +.B _AFTER +rules are appended on the end. Currently, the rules in +.B NOIP_REALCONNECT +are also put at the end (before the +.B _AFTER +rules), though this may change later. .PP (Aside: An attempt to connect to a remote host may not be a hopeless failure, even if a real IP socket is denied: @@ -144,7 +178,7 @@ servers.) .PP An .I acl-entry -has this format: +is a comma-separated list of entries of the form: .IP .BR + | \- .IR address \c diff --git a/noip.c b/noip.c index 735a58a..2f7fd14 100644 --- a/noip.c +++ b/noip.c @@ -533,60 +533,65 @@ static void parse_acl_line(char **pp, aclnode ***tail) char *p = *pp; char *q; - SKIPSPC; - if (*p == '+') act = ALLOW; - else if (*p == '-') act = DENY; - else goto bad; + for (;;) { + SKIPSPC; + if (*p == '+') act = ALLOW; + else if (*p == '-') act = DENY; + else goto bad; - p++; - SKIPSPC; - if (KWMATCHP("any")) { - minaddr = 0; - maxaddr = 0xffffffff; - goto justone; - } else if (KWMATCHP("local")) { - parse_ports(&p, &minport, &maxport); - ACLNODE(*tail, act, 0, 0, minport, maxport); - ACLNODE(*tail, act, 0xffffffff, 0xffffffff, minport, maxport); - for (i = 0; i < n_local_ipaddrs; i++) { - minaddr = ntohl(local_ipaddrs[i].s_addr); - ACLNODE(*tail, act, minaddr, minaddr, minport, maxport); - } - } else { - if (*p == ':') { + p++; + SKIPSPC; + if (KWMATCHP("any")) { minaddr = 0; maxaddr = 0xffffffff; + goto justone; + } else if (KWMATCHP("local")) { + parse_ports(&p, &minport, &maxport); + ACLNODE(*tail, act, 0, 0, minport, maxport); + ACLNODE(*tail, act, 0xffffffff, 0xffffffff, minport, maxport); + for (i = 0; i < n_local_ipaddrs; i++) { + minaddr = ntohl(local_ipaddrs[i].s_addr); + ACLNODE(*tail, act, minaddr, minaddr, minport, maxport); + } } else { - NEXTADDR(q, del); - if (inet_pton(AF_INET, q, &addr) <= 0) goto bad; - minaddr = ntohl(addr.s_addr); - RESCAN(del); - SKIPSPC; - if (*p == '-') { - p++; + if (*p == ':') { + minaddr = 0; + maxaddr = 0xffffffff; + } else { NEXTADDR(q, del); if (inet_pton(AF_INET, q, &addr) <= 0) goto bad; + minaddr = ntohl(addr.s_addr); RESCAN(del); - maxaddr = ntohl(addr.s_addr); - } else if (*p == '/') { - p++; - NEXTADDR(q, del); - if (strchr(q, '.')) { + SKIPSPC; + if (*p == '-') { + p++; + NEXTADDR(q, del); if (inet_pton(AF_INET, q, &addr) <= 0) goto bad; - mask = ntohl(addr.s_addr); - } else { - n = atoi(q); - mask = (~0ul << (32 - n)) & 0xffffffff; - } - RESCAN(del); - minaddr &= mask; - maxaddr = minaddr | (mask ^ 0xffffffff); - } else - maxaddr = minaddr; + RESCAN(del); + maxaddr = ntohl(addr.s_addr); + } else if (*p == '/') { + p++; + NEXTADDR(q, del); + if (strchr(q, '.')) { + if (inet_pton(AF_INET, q, &addr) <= 0) goto bad; + mask = ntohl(addr.s_addr); + } else { + n = atoi(q); + mask = (~0ul << (32 - n)) & 0xffffffff; + } + RESCAN(del); + minaddr &= mask; + maxaddr = minaddr | (mask ^ 0xffffffff); + } else + maxaddr = minaddr; + } + justone: + parse_ports(&p, &minport, &maxport); + ACLNODE(*tail, act, minaddr, maxaddr, minport, maxport); } - justone: - parse_ports(&p, &minport, &maxport); - ACLNODE(*tail, act, minaddr, maxaddr, minport, maxport); + SKIPSPC; + if (*p != ',') break; + p++; } return; @@ -595,6 +600,17 @@ bad: return; } +static void parse_acl_env(const char *var, aclnode ***tail) +{ + char *p; + + if ((p = getenv(var)) != 0) { + p = xstrdup(p); + parse_acl_line(&p, tail); + free(p); + } +} + static void readconfig(void) { FILE *fp; @@ -608,6 +624,8 @@ static void readconfig(void) if ((fp = fopen(p, "r")) == 0) goto done; + parse_acl_env("NOIP_REALBIND_BEFORE", &bind_tail); + parse_acl_env("NOIP_REALCONNECT_BEFORE", &connect_tail); while (fgets(buf, sizeof(buf), fp)) { n = strlen(buf); p = buf; @@ -633,8 +651,13 @@ static void readconfig(void) fclose(fp); done: + parse_acl_env("NOIP_REALBIND", &bind_tail); + parse_acl_env("NOIP_REALCONNECT", &connect_tail); + parse_acl_env("NOIP_REALBIND_AFTER", &bind_tail); + parse_acl_env("NOIP_REALCONNECT_AFTER", &connect_tail); *bind_tail = 0; *connect_tail = 0; + if (!sockdir) sockdir = getenv("NOIP_SOCKETDIR"); if (!sockdir) { snprintf(buf, sizeof(buf), "%s/noip-%s", tmpdir(), user()); sockdir = xstrdup(buf); -- [mdw]