diff options
author | Laurent Bercot <ska-skaware@skarnet.org> | 2014-12-15 23:08:59 +0000 |
---|---|---|
committer | Laurent Bercot <ska-skaware@skarnet.org> | 2014-12-15 23:08:59 +0000 |
commit | e0fc82203d677a6f1e808e9a1a46176c109d89be (patch) | |
tree | e9609209b755e3f7a8480aea86601ffe9d4ca540 /src/libs6net | |
download | s6-networking-e0fc82203d677a6f1e808e9a1a46176c109d89be.tar.xz |
Initial commit
Diffstat (limited to 'src/libs6net')
-rw-r--r-- | src/libs6net/deps-lib/s6net | 12 | ||||
-rw-r--r-- | src/libs6net/s6net_accessrules_backend_cdb.c | 38 | ||||
-rw-r--r-- | src/libs6net/s6net_accessrules_backend_fs.c | 58 | ||||
-rw-r--r-- | src/libs6net/s6net_accessrules_keycheck_ip4.c | 24 | ||||
-rw-r--r-- | src/libs6net/s6net_accessrules_keycheck_ip6.c | 27 | ||||
-rw-r--r-- | src/libs6net/s6net_accessrules_keycheck_reversedns.c | 27 | ||||
-rw-r--r-- | src/libs6net/s6net_accessrules_keycheck_uidgid.c | 16 | ||||
-rw-r--r-- | src/libs6net/s6net_accessrules_uidgid_cdb.c | 11 | ||||
-rw-r--r-- | src/libs6net/s6net_accessrules_uidgid_fs.c | 10 | ||||
-rw-r--r-- | src/libs6net/s6net_ident_client.c | 22 | ||||
-rw-r--r-- | src/libs6net/s6net_ident_error.c | 33 | ||||
-rw-r--r-- | src/libs6net/s6net_ident_reply_get.c | 46 | ||||
-rw-r--r-- | src/libs6net/s6net_ident_reply_parse.c | 58 |
13 files changed, 382 insertions, 0 deletions
diff --git a/src/libs6net/deps-lib/s6net b/src/libs6net/deps-lib/s6net new file mode 100644 index 0000000..7b497ac --- /dev/null +++ b/src/libs6net/deps-lib/s6net @@ -0,0 +1,12 @@ +s6net_accessrules_backend_cdb.o +s6net_accessrules_backend_fs.o +s6net_accessrules_keycheck_ip4.o +s6net_accessrules_keycheck_ip6.o +s6net_accessrules_keycheck_reversedns.o +s6net_accessrules_keycheck_uidgid.o +s6net_accessrules_uidgid_cdb.o +s6net_accessrules_uidgid_fs.o +s6net_ident_client.o +s6net_ident_reply_get.o +s6net_ident_reply_parse.o +s6net_ident_error.o diff --git a/src/libs6net/s6net_accessrules_backend_cdb.c b/src/libs6net/s6net_accessrules_backend_cdb.c new file mode 100644 index 0000000..e75f755 --- /dev/null +++ b/src/libs6net/s6net_accessrules_backend_cdb.c @@ -0,0 +1,38 @@ +/* ISC license. */ + +#include <unistd.h> +#include <errno.h> +#include <skalibs/bytestr.h> +#include <skalibs/uint16.h> +#include <skalibs/cdb.h> +#include <skalibs/stralloc.h> +#include <s6-networking/accessrules.h> + +s6net_accessrules_result_t s6net_accessrules_backend_cdb (char const *key, unsigned int keylen, void *data, s6net_accessrules_params_t *params) +{ + struct cdb *c = data ; + unsigned int execbase, n ; + uint16 envlen, execlen ; + register int r = cdb_find(c, key, keylen) ; + if (r < 0) return S6NET_ACCESSRULES_ERROR ; + else if (!r) return S6NET_ACCESSRULES_NOTFOUND ; + n = cdb_datalen(c) ; + if ((n < 5U) || (n > 8197U)) return (errno = EINVAL, S6NET_ACCESSRULES_ERROR) ; + if (!stralloc_readyplus(¶ms->exec, n)) return S6NET_ACCESSRULES_ERROR ; + execbase = params->exec.len ; + if (cdb_read(c, params->exec.s + execbase, n, cdb_datapos(c)) < 0) return S6NET_ACCESSRULES_ERROR ; + if (params->exec.s[execbase] == 'D') return S6NET_ACCESSRULES_DENY ; + else if (params->exec.s[execbase] != 'A') return S6NET_ACCESSRULES_NOTFOUND ; + uint16_unpack_big(params->exec.s + execbase + 1U, &envlen) ; + if ((envlen > 4096U) || (envlen+5U > n)) return (errno = EINVAL, S6NET_ACCESSRULES_ERROR) ; + uint16_unpack_big(params->exec.s + execbase + 3 + envlen, &execlen) ; + if ((execlen > 4096U) || (5U + envlen + execlen != n)) return (errno = EINVAL, S6NET_ACCESSRULES_ERROR) ; + if (!stralloc_catb(¶ms->env, params->exec.s + execbase + 3U, envlen)) return S6NET_ACCESSRULES_ERROR ; + byte_copy(params->exec.s + execbase, execlen, params->exec.s + execbase + 5U + envlen) ; + if (execlen) + { + params->exec.len += execlen ; + params->exec.s[params->exec.len++] = 0 ; + } + return S6NET_ACCESSRULES_ALLOW ; +} diff --git a/src/libs6net/s6net_accessrules_backend_fs.c b/src/libs6net/s6net_accessrules_backend_fs.c new file mode 100644 index 0000000..d609285 --- /dev/null +++ b/src/libs6net/s6net_accessrules_backend_fs.c @@ -0,0 +1,58 @@ +/* ISC license. */ + +#include <unistd.h> +#include <errno.h> +#include <skalibs/bytestr.h> +#include <skalibs/fmtscan.h> +#include <skalibs/stralloc.h> +#include <skalibs/djbunix.h> +#include <s6-networking/accessrules.h> + +s6net_accessrules_result_t s6net_accessrules_backend_fs (char const *key, unsigned int keylen, void *data, s6net_accessrules_params_t *params) +{ + char *dir = data ; + unsigned int dirlen = str_len(dir) ; + unsigned int envbase = params->env.len ; + int wasnull = !params->env.s ; + { + char tmp[dirlen + keylen + 10] ; + byte_copy(tmp, dirlen, dir) ; + tmp[dirlen] = '/' ; + byte_copy(tmp + dirlen + 1, keylen, key) ; + byte_copy(tmp + dirlen + keylen + 1, 7, "/allow") ; + if (access(tmp, R_OK) < 0) + { + if ((errno != EACCES) && (errno != ENOENT)) + return S6NET_ACCESSRULES_ERROR ; + byte_copy(tmp + dirlen + keylen + 2, 5, "deny") ; + return (access(tmp, R_OK) == 0) ? S6NET_ACCESSRULES_DENY : + (errno != EACCES) && (errno != ENOENT) ? S6NET_ACCESSRULES_ERROR : + S6NET_ACCESSRULES_NOTFOUND ; + } + byte_copy(tmp + dirlen + keylen + 2, 4, "env") ; + if ((envdir(tmp, ¶ms->env) < 0) && (errno != ENOENT)) + return S6NET_ACCESSRULES_ERROR ; + if (!stralloc_readyplus(¶ms->exec, 4097)) + { + if (wasnull) stralloc_free(¶ms->env) ; + else params->env.len = envbase ; + return S6NET_ACCESSRULES_ERROR ; + } + byte_copy(tmp + dirlen + keylen + 2, 5, "exec") ; + { + register int r = openreadnclose(tmp, params->exec.s + params->exec.len, 4096) ; + if ((r < 0) && (errno != EACCES) && (errno != ENOENT)) + { + if (wasnull) stralloc_free(¶ms->env) ; + else params->env.len = envbase ; + return S6NET_ACCESSRULES_ERROR ; + } + if (r > 0) + { + params->exec.len += r ; + params->exec.s[params->exec.len++] = 0 ; + } + } + } + return S6NET_ACCESSRULES_ALLOW ; +} diff --git a/src/libs6net/s6net_accessrules_keycheck_ip4.c b/src/libs6net/s6net_accessrules_keycheck_ip4.c new file mode 100644 index 0000000..1f96bd8 --- /dev/null +++ b/src/libs6net/s6net_accessrules_keycheck_ip4.c @@ -0,0 +1,24 @@ +/* ISC license. */ + +#include <skalibs/uint32.h> +#include <skalibs/uint.h> +#include <skalibs/fmtscan.h> +#include <s6-networking/accessrules.h> + +s6net_accessrules_result_t s6net_accessrules_keycheck_ip4 (void const *key, void *data, s6net_accessrules_params_t *params, s6net_accessrules_backend_func_t_ref check1) +{ + char fmt[IP4_FMT + UINT_FMT + 6] = "ip4/" ; + uint32 ip ; + unsigned int i = 0 ; + uint32_unpack_big((char const *)key, &ip) ; + for (; i <= 32 ; i++) + { + register s6net_accessrules_result_t r ; + register unsigned int len = 4 + ip4_fmtu32(fmt+4, (i == 32) ? 0 : ip & ~((1U << i) - 1)) ; + fmt[len++] = '_' ; + len += uint_fmt(fmt + len, 32 - i) ; + r = (*check1)(fmt, len, data, params) ; + if (r != S6NET_ACCESSRULES_NOTFOUND) return r ; + } + return S6NET_ACCESSRULES_NOTFOUND ; +} diff --git a/src/libs6net/s6net_accessrules_keycheck_ip6.c b/src/libs6net/s6net_accessrules_keycheck_ip6.c new file mode 100644 index 0000000..c2ee5ae --- /dev/null +++ b/src/libs6net/s6net_accessrules_keycheck_ip6.c @@ -0,0 +1,27 @@ +/* ISC license. */ + +#include <skalibs/uint.h> +#include <skalibs/bytestr.h> +#include <skalibs/bitarray.h> +#include <skalibs/fmtscan.h> +#include <s6-networking/accessrules.h> + +s6net_accessrules_result_t s6net_accessrules_keycheck_ip6 (void const *key, void *data, s6net_accessrules_params_t *params, s6net_accessrules_backend_func_t_ref check1) +{ + char fmt[IP6_FMT + UINT_FMT + 6] = "ip6/" ; + char ip6[16] ; + unsigned int i = 0 ; + byte_copy(ip6, 16, (char const *)key) ; + for (; i <= 128 ; i++) + { + unsigned int len ; + register s6net_accessrules_result_t r ; + if (i) bitarray_clear(ip6, 128 - i) ; + len = 4 + ip6_fmt(fmt+4, ip6) ; + fmt[len++] = '_' ; + len += uint_fmt(fmt + len, 128 - i) ; + r = (*check1)(fmt, len, data, params) ; + if (r != S6NET_ACCESSRULES_NOTFOUND) return r ; + } + return S6NET_ACCESSRULES_NOTFOUND ; +} diff --git a/src/libs6net/s6net_accessrules_keycheck_reversedns.c b/src/libs6net/s6net_accessrules_keycheck_reversedns.c new file mode 100644 index 0000000..f4c0213 --- /dev/null +++ b/src/libs6net/s6net_accessrules_keycheck_reversedns.c @@ -0,0 +1,27 @@ +/* ISC license. */ + +#include <errno.h> +#include <skalibs/bytestr.h> +#include <s6-networking/accessrules.h> + +s6net_accessrules_result_t s6net_accessrules_keycheck_reversedns (void const *key, void *data, s6net_accessrules_params_t *params, s6net_accessrules_backend_func_t_ref check1) +{ + char const *name = key ; + unsigned int len = str_len(name) ; + if (!len) return (errno = EINVAL, S6NET_ACCESSRULES_ERROR) ; + if (name[len-1] == '.') len-- ; + { + unsigned int i = 0 ; + char tmp[len + 11] ; + byte_copy(tmp, 11, "reversedns/") ; + while (i < len) + { + register s6net_accessrules_result_t r ; + byte_copy(tmp+11, len-i, name+i) ; + r = (*check1)(tmp, 11+len-i, data, params) ; + if (r != S6NET_ACCESSRULES_NOTFOUND) return r ; + i += byte_chr(name+i, len-i, '.') + 1 ; + } + } + return (*check1)("reversedns/@", 12, data, params) ; +} diff --git a/src/libs6net/s6net_accessrules_keycheck_uidgid.c b/src/libs6net/s6net_accessrules_keycheck_uidgid.c new file mode 100644 index 0000000..a7e2200 --- /dev/null +++ b/src/libs6net/s6net_accessrules_keycheck_uidgid.c @@ -0,0 +1,16 @@ +/* ISC license. */ + +#include <skalibs/uint.h> +#include <skalibs/diuint.h> +#include <s6-networking/accessrules.h> + +s6net_accessrules_result_t s6net_accessrules_keycheck_uidgid (void const *key, void *data, s6net_accessrules_params_t *params, s6net_accessrules_backend_func_t_ref check1) +{ + char fmt[4 + UINT_FMT] = "uid/" ; + register s6net_accessrules_result_t r = (*check1)(fmt, 4 + uint_fmt(fmt+4, ((diuint const *)key)->left), data, params) ; + if (r != S6NET_ACCESSRULES_NOTFOUND) return r ; + fmt[0] = 'g' ; + r = (*check1)(fmt, 4 + uint_fmt(fmt+4, ((diuint const *)key)->right), data, params) ; + return (r != S6NET_ACCESSRULES_NOTFOUND) ? r : + (*check1)("uid/default", 11, data, params) ; +} diff --git a/src/libs6net/s6net_accessrules_uidgid_cdb.c b/src/libs6net/s6net_accessrules_uidgid_cdb.c new file mode 100644 index 0000000..1836389 --- /dev/null +++ b/src/libs6net/s6net_accessrules_uidgid_cdb.c @@ -0,0 +1,11 @@ +/* ISC license. */ + +#include <skalibs/diuint.h> +#include <skalibs/cdb.h> +#include <s6-networking/accessrules.h> + +s6net_accessrules_result_t s6net_accessrules_uidgid_cdb (unsigned int uid, unsigned int gid, struct cdb *c, s6net_accessrules_params_t *params) +{ + diuint uidgid = { uid, gid } ; + return s6net_accessrules_keycheck_uidgid(&uidgid, c, params, &s6net_accessrules_backend_cdb) ; +} diff --git a/src/libs6net/s6net_accessrules_uidgid_fs.c b/src/libs6net/s6net_accessrules_uidgid_fs.c new file mode 100644 index 0000000..db2e909 --- /dev/null +++ b/src/libs6net/s6net_accessrules_uidgid_fs.c @@ -0,0 +1,10 @@ +/* ISC license. */ + +#include <skalibs/diuint.h> +#include <s6-networking/accessrules.h> + +s6net_accessrules_result_t s6net_accessrules_uidgid_fs (unsigned int uid, unsigned int gid, char const *rulesdir, s6net_accessrules_params_t *params) +{ + diuint uidgid = { uid, gid } ; + return s6net_accessrules_keycheck_uidgid(&uidgid, (void *)rulesdir, params, &s6net_accessrules_backend_fs) ; +} diff --git a/src/libs6net/s6net_ident_client.c b/src/libs6net/s6net_ident_client.c new file mode 100644 index 0000000..c6b9ac0 --- /dev/null +++ b/src/libs6net/s6net_ident_client.c @@ -0,0 +1,22 @@ +/* ISC license. */ + +#include <errno.h> +#include <skalibs/uint16.h> +#include <skalibs/bytestr.h> +#include <skalibs/tai.h> +#include <skalibs/ip46.h> +#include <s6-networking/ident.h> + +int s6net_ident_client (char *s, unsigned int max, ip46_t const *remoteip, uint16 remoteport, ip46_t const *localip, uint16 localport, tain_t const *deadline, tain_t *stamp) +{ + char buf[S6NET_IDENT_REPLY_SIZE] ; + unsigned int len ; + register int r = s6net_ident_reply_get(buf, remoteip, remoteport, localip, localport, deadline, stamp) ; + if (r < 0) return errno == EPIPE ? (errno = EIO, 0) : -1 ; /* the RFC says so */ + len = r ; + r = s6net_ident_reply_parse(buf, remoteport, localport) ; + if (r <= 0) return r ; + if (max + r < len + 1) return (errno = ENAMETOOLONG, -1) ; + byte_copy(s, len - r + 1, buf + r) ; + return len - r + 1 ; +} diff --git a/src/libs6net/s6net_ident_error.c b/src/libs6net/s6net_ident_error.c new file mode 100644 index 0000000..de01714 --- /dev/null +++ b/src/libs6net/s6net_ident_error.c @@ -0,0 +1,33 @@ +/* ISC license */ + +#include <errno.h> +#include <skalibs/error.h> +#include <s6-networking/ident.h> + +#define N 5 + +static char const *s6net_ident_error_strings[N+1] = +{ + "invalid port", + "no such user", + "identification denied", + "unknown error", + "X-error-token", + "(invalid error code)" +} ; + +static int const s6net_ident_error_codes[N] = +{ + EINVAL, + ESRCH, + EPERM, + EIO, + EEXIST +} ; + +char const *s6net_ident_error_str (int e) +{ + register unsigned int i = 0 ; + for (; i < N ; i++) if (e == s6net_ident_error_codes[i]) break ; + return s6net_ident_error_strings[i] ; +} diff --git a/src/libs6net/s6net_ident_reply_get.c b/src/libs6net/s6net_ident_reply_get.c new file mode 100644 index 0000000..3e11121 --- /dev/null +++ b/src/libs6net/s6net_ident_reply_get.c @@ -0,0 +1,46 @@ +/* ISC license. */ + +#include <errno.h> +#include <skalibs/uint16.h> +#include <skalibs/allreadwrite.h> +#include <skalibs/buffer.h> +#include <skalibs/error.h> +#include <skalibs/tai.h> +#include <skalibs/djbunix.h> +#include <skalibs/ip46.h> +#include <skalibs/unix-timed.h> +#include <s6-networking/ident.h> + +int s6net_ident_reply_get (char *s, ip46_t const *remoteip, uint16 remoteport, ip46_t const *localip, uint16 localport, tain_t const *deadline, tain_t *stamp) +{ + unsigned int len ; + int fd ; + if (ip46_is6(remoteip) != ip46_is6(localip)) return (errno = EAFNOSUPPORT, -1) ; + fd = socket_tcp46(ip46_is6(remoteip)) ; + if (fd < 0) return -1 ; + if (socket_bind46(fd, localip, 0) < 0) goto err ; + if (socket_deadlineconnstamp46(fd, remoteip, 113, deadline, stamp) <= 0) goto err ; + { + char buf[S6NET_IDENT_REPLY_SIZE + 1] ; + char fmt[UINT16_FMT] ; + buffer b = BUFFER_INIT(&buffer_write, fd, buf, 256) ; + unsigned int n = uint16_fmt(fmt, remoteport) ; + buffer_putnoflush(&b, fmt, n) ; + buffer_putnoflush(&b, " , ", 3) ; + n = uint16_fmt(fmt, localport) ; + buffer_putnoflush(&b, fmt, n) ; + buffer_putnoflush(&b, "\r\n", 2) ; + if (!buffer_timed_flush(&b, deadline, stamp)) goto err ; + buffer_init(&b, &buffer_read, fd, buf, S6NET_IDENT_REPLY_SIZE + 1) ; + if (sanitize_read(timed_getlnmax(&b, s, S6NET_IDENT_REPLY_SIZE, &len, '\n', deadline, stamp)) <= 0) goto err ; + } + fd_close(fd) ; + if (len < 2) return (errno = EPROTO, -1) ; + len -= 2 ; + s[len] = 0 ; + return (int)len ; + +err: + fd_close(fd) ; + return -1 ; +} diff --git a/src/libs6net/s6net_ident_reply_parse.c b/src/libs6net/s6net_ident_reply_parse.c new file mode 100644 index 0000000..a895d60 --- /dev/null +++ b/src/libs6net/s6net_ident_reply_parse.c @@ -0,0 +1,58 @@ +/* ISC license. */ + +#include <errno.h> +#include <skalibs/uint16.h> +#include <skalibs/bytestr.h> +#include <skalibs/error.h> +#include <s6-networking/ident.h> + +static unsigned int skipspace (char const *s) +{ + register unsigned int n = 0 ; + while ((s[n] == ' ') || (s[n] == '\t')) n++ ; + return n ; +} + +int s6net_ident_reply_parse (char const *s, uint16 rp, uint16 lp) +{ + unsigned int n = 0 ; + n += skipspace(s+n) ; if (!s[n]) goto err ; + { + unsigned int i ; + uint16 u ; + i = uint16_scan(s+n, &u) ; if (!i) goto err ; n += i ; + if (u != rp) goto err ; + n += skipspace(s+n) ; if (!s[n]) goto err ; + if (s[n++] != ',') goto err ; + n += skipspace(s+n) ; if (!s[n]) goto err ; + i = uint16_scan(s+n, &u) ; if (!i) goto err ; n += i ; + if (u != lp) goto err ; + } + n += skipspace(s+n) ; if (!s[n]) goto err ; + if (s[n++] != ':') goto err ; + n += skipspace(s+n) ; if (!s[n]) goto err ; + if (!str_diffn(s+n, "ERROR", 5)) goto ERROR ; + if (!str_diffn(s+n, "USERID", 6)) goto USERID ; + err: + return (errno = EPROTO, -1) ; + + ERROR: + n += 5 ; + n += skipspace(s+n) ; if (!s[n]) goto err ; + if (s[n++] != ':') goto err ; + n += skipspace(s+n) ; if (!s[n]) goto err ; + if (!str_diffn(s+n, "INVALID-PORT", 12)) return (errno = EINVAL, 0) ; + if (!str_diffn(s+n, "NO-USER", 7)) return (errno = ESRCH, 0) ; + if (!str_diffn(s+n, "HIDDEN-USER", 11)) return (errno = EPERM, 0) ; + if (!str_diffn(s+n, "UNKNOWN-ERROR", 13)) return (errno = EIO, 0) ; + if (s[n] == 'X') return (errno = EEXIST, 0) ; + goto err ; + + USERID: + n += 6 ; + n += skipspace(s+n) ; if (!s[n]) goto err ; + if (s[n++] != ':') goto err ; + n += str_chr(s+n, ':') ; if (!s[n]) goto err ; + n++ ; if ((s[n] == ' ') || (s[n] == '\t')) n++ ; + return n ; +} |