initial commit
This commit is contained in:
commit
584aad56b8
19 changed files with 390 additions and 0 deletions
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
example.input -text
|
||||||
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
/build/
|
||||||
24
README
Normal file
24
README
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
nobotgate
|
||||||
|
=========
|
||||||
|
|
||||||
|
When you run a private site (that still uses a
|
||||||
|
super-serve), you can use nobotgate to require users to
|
||||||
|
provide an http bearer token. This way, bots won't flood
|
||||||
|
your site with spam.
|
||||||
|
|
||||||
|
usage
|
||||||
|
-----
|
||||||
|
|
||||||
|
use nobotgate(1) together with a super-server such as inetd(8),
|
||||||
|
tcpserver(1) or s6-tcpserver:
|
||||||
|
# tcpserver 0.0.0.0 80 nobotgate /etc/wwwtokens ./on-valid ./on-invalid
|
||||||
|
where /etc/wwwtokens contains:
|
||||||
|
|
||||||
|
and ./on-valid contains:
|
||||||
|
#!/bin/sh
|
||||||
|
exec busybox httpd -i -h /var/www
|
||||||
|
and ./on-invalid contains:
|
||||||
|
#!/bin/sh
|
||||||
|
exec nobotgate-access cat usage
|
||||||
|
and usage contains:
|
||||||
|
No bearer token specified!
|
||||||
39
check_token.c
Normal file
39
check_token.c
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
#include <libowfat/stralloc.h>
|
||||||
|
#include <libowfat/errmsg.h>
|
||||||
|
#include <libowfat/open.h>
|
||||||
|
#include <libowfat/str.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "nobotgate.h"
|
||||||
|
|
||||||
|
int check_token(char *tokenfile, stralloc *token)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
char buf[4096];
|
||||||
|
buffer b;
|
||||||
|
int r,found;
|
||||||
|
stralloc line;
|
||||||
|
fd = open_read(tokenfile);
|
||||||
|
if (fd < 0)
|
||||||
|
diesys(errno == ENOENT ? 100 : 111, "open_read ", tokenfile);
|
||||||
|
buffer_init_read(&b, fd, buf, sizeof(buf));
|
||||||
|
stralloc_init(&line);
|
||||||
|
|
||||||
|
found = 0;
|
||||||
|
for (;;) {
|
||||||
|
r = buffer_getnewline_sa(&b, &line);
|
||||||
|
if (r == 0) break;
|
||||||
|
if (r < 0) diesys(111, "failed reading tokenfile ", tokenfile);
|
||||||
|
stralloc_chomp(&line);
|
||||||
|
stralloc_0(&line);
|
||||||
|
line.s[str_chr(line.s, ' ')] = 0;
|
||||||
|
if (stralloc_equals(token, line.s)) {
|
||||||
|
found = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer_close(&b);
|
||||||
|
stralloc_free(&line);
|
||||||
|
return found;
|
||||||
|
}
|
||||||
2
example.input
Normal file
2
example.input
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
Authorization: Bearer 1234
|
||||||
|
|
||||||
4
example.service/on-invalid
Executable file
4
example.service/on-invalid
Executable file
|
|
@ -0,0 +1,4 @@
|
||||||
|
#!/bin/sh
|
||||||
|
exec \
|
||||||
|
nobotgate-access \
|
||||||
|
cat usage
|
||||||
3
example.service/on-valid
Executable file
3
example.service/on-valid
Executable file
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/sh
|
||||||
|
exec \
|
||||||
|
busybox httpd -i -h .
|
||||||
10
example.service/run
Executable file
10
example.service/run
Executable file
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# service that runs a web server protected with nobotgate.
|
||||||
|
# if the user provided a valid token, it will exec into
|
||||||
|
# ./on-valid, if not, into ./on-invalid.
|
||||||
|
exec \
|
||||||
|
envuidgid www \
|
||||||
|
tcpserver -U 127.0.0.1 80 \
|
||||||
|
../build/nobotgate ./tokens \
|
||||||
|
./on-valid \
|
||||||
|
./on-invalid
|
||||||
2
example.service/tokens
Normal file
2
example.service/tokens
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
1234 a pretty insecure token
|
||||||
|
11aa this token is a lot more secure
|
||||||
91
example.service/trace
Normal file
91
example.service/trace
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
2783 execve("/usr/bin/envuidgid", ["envuidgid", "www", "tcpserver", "-U", "127.0.0.1", "80"], 0x7ffed7055678 /* 11 vars */) = 0
|
||||||
|
2783 brk(NULL) = 0x558000b69000
|
||||||
|
2783 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
|
||||||
|
2783 openat(AT_FDCWD</home/a/src/kento2/nobotgate/example.service>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3</etc/ld.so.cache>
|
||||||
|
2783 fstat(3</etc/ld.so.cache>, {st_mode=S_IFREG|0644, st_size=129031, ...}) = 0
|
||||||
|
2783 mmap(NULL, 129031, PROT_READ, MAP_PRIVATE, 3</etc/ld.so.cache>, 0) = 0x7f13d3dfa000
|
||||||
|
2783 close(3</etc/ld.so.cache>) = 0
|
||||||
|
2783 mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f13d3df8000
|
||||||
|
2783 openat(AT_FDCWD</home/a/src/kento2/nobotgate/example.service>, "/usr/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3</usr/lib/libc.so.6>
|
||||||
|
2783 read(3</usr/lib/libc.so.6>, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\300\255\2\0\0\0\0\0@\0\0\0\0\0\0\08\264\301\0\0\0\0\0\0\0\0\0@\08\0\16\0@\0G\0F\0\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0\20\3\0\0\0\0\0\0\20\3\0\0\0\0\0\0\10\0\0\0\0\0\0\0\3\0\0\0\4\0\0\0\240q\32\0\0\0\0\0\240q\32\0\0\0\0\0\240q\32\0\0\0\0\0 \0\0\0\0\0\0\0 \0\0\0\0\0\0\0 \0\0\0\0\0\0\0\1\0\0\0\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210t\2\0\0\0\0\0\210t\2\0\0\0\0\0\0\20\0\0\0\0\0\0\1\0\0\0\5\0\0\0\0\200\2\0\0\0\0\0\0\200\2\0\0\0\0\0"..., 832) = 832
|
||||||
|
2783 pread64(3</usr/lib/libc.so.6>, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0\20\3\0\0\0\0\0\0\20\3\0\0\0\0\0\0\10\0\0\0\0\0\0\0\3\0\0\0\4\0\0\0\240q\32\0\0\0\0\0\240q\32\0\0\0\0\0\240q\32\0\0\0\0\0 \0\0\0\0\0\0\0 \0\0\0\0\0\0\0 \0\0\0\0\0\0\0\1\0\0\0\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210t\2\0\0\0\0\0\210t\2\0\0\0\0\0\0\20\0\0\0\0\0\0\1\0\0\0\5\0\0\0\0\200\2\0\0\0\0\0\0\200\2\0\0\0\0\0\0\200\2\0\0\0\0\0\235\216\25\0\0\0\0\0\235\216\25\0\0\0\0\0\0\20\0\0\0\0\0\0\1\0\0\0\4\0\0\0\0\20\30\0\0\0\0\0\0\20\30\0\0\0\0\0\0\20\30\0\0\0\0\0"..., 784, 64) = 784
|
||||||
|
2783 fstat(3</usr/lib/libc.so.6>, {st_mode=S_IFREG|0755, st_size=12699128, ...}) = 0
|
||||||
|
2783 pread64(3</usr/lib/libc.so.6>, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0\20\3\0\0\0\0\0\0\20\3\0\0\0\0\0\0\10\0\0\0\0\0\0\0\3\0\0\0\4\0\0\0\240q\32\0\0\0\0\0\240q\32\0\0\0\0\0\240q\32\0\0\0\0\0 \0\0\0\0\0\0\0 \0\0\0\0\0\0\0 \0\0\0\0\0\0\0\1\0\0\0\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210t\2\0\0\0\0\0\210t\2\0\0\0\0\0\0\20\0\0\0\0\0\0\1\0\0\0\5\0\0\0\0\200\2\0\0\0\0\0\0\200\2\0\0\0\0\0\0\200\2\0\0\0\0\0\235\216\25\0\0\0\0\0\235\216\25\0\0\0\0\0\0\20\0\0\0\0\0\0\1\0\0\0\4\0\0\0\0\20\30\0\0\0\0\0\0\20\30\0\0\0\0\0\0\20\30\0\0\0\0\0"..., 784, 64) = 784
|
||||||
|
2783 mmap(NULL, 2006680, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3</usr/lib/libc.so.6>, 0) = 0x7f13d3c0e000
|
||||||
|
2783 mmap(0x7f13d3c36000, 1413120, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3</usr/lib/libc.so.6>, 0x28000) = 0x7f13d3c36000
|
||||||
|
2783 mmap(0x7f13d3d8f000, 352256, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3</usr/lib/libc.so.6>, 0x181000) = 0x7f13d3d8f000
|
||||||
|
2783 mmap(0x7f13d3de5000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3</usr/lib/libc.so.6>, 0x1d6000) = 0x7f13d3de5000
|
||||||
|
2783 mmap(0x7f13d3deb000, 52888, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f13d3deb000
|
||||||
|
2783 close(3</usr/lib/libc.so.6>) = 0
|
||||||
|
2783 mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f13d3c0b000
|
||||||
|
2783 arch_prctl(ARCH_SET_FS, 0x7f13d3c0b740) = 0
|
||||||
|
2783 set_tid_address(0x7f13d3c0ba10) = 2783
|
||||||
|
2783 set_robust_list(0x7f13d3c0ba20, 24) = 0
|
||||||
|
2783 rseq({cpu_id_start=0, cpu_id=RSEQ_CPU_ID_UNINITIALIZED, rseq_cs=NULL, flags=0, node_id=0, mm_cid=0, slice_ctrl={request=0, granted=0, __reserved=0}, __reserved=0}, 32, 0, 0x53053053) = 0
|
||||||
|
2783 mprotect(0x7f13d3de5000, 16384, PROT_READ) = 0
|
||||||
|
2783 mprotect(0x557fcb203000, 4096, PROT_READ) = 0
|
||||||
|
2783 mprotect(0x7f13d3e55000, 8192, PROT_READ) = 0
|
||||||
|
2783 prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
|
||||||
|
2783 munmap(0x7f13d3dfa000, 129031) = 0
|
||||||
|
2783 getrandom("\x50\xa4\x5b\x1a\x33\xa9\x65\xde", 8, GRND_NONBLOCK) = 8
|
||||||
|
2783 brk(NULL) = 0x558000b69000
|
||||||
|
2783 brk(0x558000b8a000) = 0x558000b8a000
|
||||||
|
2783 socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3<UNIX-STREAM:[57002340]>
|
||||||
|
2783 connect(3<UNIX-STREAM:[57002340]>, {sa_family=AF_UNIX, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
|
||||||
|
2783 close(3<UNIX-STREAM:[57002340]>) = 0
|
||||||
|
2783 socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3<UNIX-STREAM:[57002341]>
|
||||||
|
2783 connect(3<UNIX-STREAM:[57002341]>, {sa_family=AF_UNIX, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
|
||||||
|
2783 close(3<UNIX-STREAM:[57002341]>) = 0
|
||||||
|
2783 newfstatat(AT_FDCWD</home/a/src/kento2/nobotgate/example.service>, "/etc/nsswitch.conf", {st_mode=S_IFREG|0644, st_size=216, ...}, 0) = 0
|
||||||
|
2783 newfstatat(AT_FDCWD</home/a/src/kento2/nobotgate/example.service>, "/", {st_mode=S_IFDIR|0755, st_size=4096, ...}, 0) = 0
|
||||||
|
2783 openat(AT_FDCWD</home/a/src/kento2/nobotgate/example.service>, "/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 3</etc/nsswitch.conf>
|
||||||
|
2783 fstat(3</etc/nsswitch.conf>, {st_mode=S_IFREG|0644, st_size=216, ...}) = 0
|
||||||
|
2783 read(3</etc/nsswitch.conf>, "# /etc/nsswitch.conf\n#\n# See nsswitch.conf(5) for information.\n#\npasswd: \tfiles\ngroup: \t\tfiles\nshadow: \tfiles\n\nhosts: \t\tfiles mdns dns\nnetworks: \tfiles\n\nprotocols: \tfiles\nservices: \tfiles\nethers: \tfiles\nrpc: \t\tfiles\n", 4096) = 216
|
||||||
|
2783 read(3</etc/nsswitch.conf>, "", 4096) = 0
|
||||||
|
2783 fstat(3</etc/nsswitch.conf>, {st_mode=S_IFREG|0644, st_size=216, ...}) = 0
|
||||||
|
2783 close(3</etc/nsswitch.conf>) = 0
|
||||||
|
2783 openat(AT_FDCWD</home/a/src/kento2/nobotgate/example.service>, "/etc/passwd", O_RDONLY|O_CLOEXEC) = 3</etc/passwd>
|
||||||
|
2783 fstat(3</etc/passwd>, {st_mode=S_IFREG|0644, st_size=5894, ...}) = 0
|
||||||
|
2783 lseek(3</etc/passwd>, 0, SEEK_SET) = 0
|
||||||
|
2783 read(3</etc/passwd>, "root:x:0:0:root:/root:/bedrock/cross/bin/sh\nnobody:x:99:99:Unprivileged User:/dev/null:/bedrock/cross/bin/false\nchrony:x:999:999:chrony unprivileged user:/var/lib/chrony:/bedrock/cross/bin/nologin\n_dhcpcd:x:998:998:_dhcpcd unprivileged user:/var/db/dhcpcd:"..., 4096) = 4096
|
||||||
|
2783 read(3</etc/passwd>, "6 unprivileged user:/var/empty:/bedrock/cross/bin/nologin\nnixbld7:x:979:952:nixbld7 unprivileged user:/var/empty:/bedrock/cross/bin/nologin\nnixbld8:x:978:952:nixbld8 unprivileged user:/var/empty:/bedrock/cross/bin/nologin\nnixbld9:x:977:952:nixbld9 unprivil"..., 4096) = 1798
|
||||||
|
2783 close(3</etc/passwd>) = 0
|
||||||
|
2783 execve("/home/a/.local/bin/tcpserver", ["tcpserver", "-U", "127.0.0.1", "80"], 0x557fcb2047f0 /* 13 vars */) = -1 ENOENT (No such file or directory)
|
||||||
|
2783 execve("/bedrock/cross/pin/bin/tcpserver", ["tcpserver", "-U", "127.0.0.1", "80"], 0x557fcb2047f0 /* 13 vars */) = -1 ENOENT (No such file or directory)
|
||||||
|
2783 execve("/bedrock/bin/tcpserver", ["tcpserver", "-U", "127.0.0.1", "80"], 0x557fcb2047f0 /* 13 vars */) = -1 ENOENT (No such file or directory)
|
||||||
|
2783 execve("/home/a/.nix-profile/bin/tcpserver", ["tcpserver", "-U", "127.0.0.1", "80"], 0x557fcb2047f0 /* 13 vars */) = -1 ENOENT (No such file or directory)
|
||||||
|
2783 execve("/nix/var/nix/profiles/default/bin/tcpserver", ["tcpserver", "-U", "127.0.0.1", "80"], 0x557fcb2047f0 /* 13 vars */) = -1 ENOENT (No such file or directory)
|
||||||
|
2783 execve("/usr/local/bin/tcpserver", ["tcpserver", "-U", "127.0.0.1", "80"], 0x557fcb2047f0 /* 13 vars */) = -1 ENOENT (No such file or directory)
|
||||||
|
2783 execve("/usr/local/sbin/tcpserver", ["tcpserver", "-U", "127.0.0.1", "80"], 0x557fcb2047f0 /* 13 vars */) = -1 ENOENT (No such file or directory)
|
||||||
|
2783 execve("/usr/bin/tcpserver", ["tcpserver", "-U", "127.0.0.1", "80"], 0x557fcb2047f0 /* 13 vars */) = 0
|
||||||
|
2783 brk(NULL) = 0x5605f057b000
|
||||||
|
2783 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
|
||||||
|
2783 openat(AT_FDCWD</home/a/src/kento2/nobotgate/example.service>, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3</etc/ld.so.cache>
|
||||||
|
2783 fstat(3</etc/ld.so.cache>, {st_mode=S_IFREG|0644, st_size=129031, ...}) = 0
|
||||||
|
2783 mmap(NULL, 129031, PROT_READ, MAP_PRIVATE, 3</etc/ld.so.cache>, 0) = 0x7f9752158000
|
||||||
|
2783 close(3</etc/ld.so.cache>) = 0
|
||||||
|
2783 mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9752156000
|
||||||
|
2783 openat(AT_FDCWD</home/a/src/kento2/nobotgate/example.service>, "/usr/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3</usr/lib/libc.so.6>
|
||||||
|
2783 read(3</usr/lib/libc.so.6>, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\300\255\2\0\0\0\0\0@\0\0\0\0\0\0\08\264\301\0\0\0\0\0\0\0\0\0@\08\0\16\0@\0G\0F\0\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0\20\3\0\0\0\0\0\0\20\3\0\0\0\0\0\0\10\0\0\0\0\0\0\0\3\0\0\0\4\0\0\0\240q\32\0\0\0\0\0\240q\32\0\0\0\0\0\240q\32\0\0\0\0\0 \0\0\0\0\0\0\0 \0\0\0\0\0\0\0 \0\0\0\0\0\0\0\1\0\0\0\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210t\2\0\0\0\0\0\210t\2\0\0\0\0\0\0\20\0\0\0\0\0\0\1\0\0\0\5\0\0\0\0\200\2\0\0\0\0\0\0\200\2\0\0\0\0\0"..., 832) = 832
|
||||||
|
2783 pread64(3</usr/lib/libc.so.6>, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0\20\3\0\0\0\0\0\0\20\3\0\0\0\0\0\0\10\0\0\0\0\0\0\0\3\0\0\0\4\0\0\0\240q\32\0\0\0\0\0\240q\32\0\0\0\0\0\240q\32\0\0\0\0\0 \0\0\0\0\0\0\0 \0\0\0\0\0\0\0 \0\0\0\0\0\0\0\1\0\0\0\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210t\2\0\0\0\0\0\210t\2\0\0\0\0\0\0\20\0\0\0\0\0\0\1\0\0\0\5\0\0\0\0\200\2\0\0\0\0\0\0\200\2\0\0\0\0\0\0\200\2\0\0\0\0\0\235\216\25\0\0\0\0\0\235\216\25\0\0\0\0\0\0\20\0\0\0\0\0\0\1\0\0\0\4\0\0\0\0\20\30\0\0\0\0\0\0\20\30\0\0\0\0\0\0\20\30\0\0\0\0\0"..., 784, 64) = 784
|
||||||
|
2783 fstat(3</usr/lib/libc.so.6>, {st_mode=S_IFREG|0755, st_size=12699128, ...}) = 0
|
||||||
|
2783 pread64(3</usr/lib/libc.so.6>, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0\20\3\0\0\0\0\0\0\20\3\0\0\0\0\0\0\10\0\0\0\0\0\0\0\3\0\0\0\4\0\0\0\240q\32\0\0\0\0\0\240q\32\0\0\0\0\0\240q\32\0\0\0\0\0 \0\0\0\0\0\0\0 \0\0\0\0\0\0\0 \0\0\0\0\0\0\0\1\0\0\0\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210t\2\0\0\0\0\0\210t\2\0\0\0\0\0\0\20\0\0\0\0\0\0\1\0\0\0\5\0\0\0\0\200\2\0\0\0\0\0\0\200\2\0\0\0\0\0\0\200\2\0\0\0\0\0\235\216\25\0\0\0\0\0\235\216\25\0\0\0\0\0\0\20\0\0\0\0\0\0\1\0\0\0\4\0\0\0\0\20\30\0\0\0\0\0\0\20\30\0\0\0\0\0\0\20\30\0\0\0\0\0"..., 784, 64) = 784
|
||||||
|
2783 mmap(NULL, 2006680, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3</usr/lib/libc.so.6>, 0) = 0x7f9751f6c000
|
||||||
|
2783 mmap(0x7f9751f94000, 1413120, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3</usr/lib/libc.so.6>, 0x28000) = 0x7f9751f94000
|
||||||
|
2783 mmap(0x7f97520ed000, 352256, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3</usr/lib/libc.so.6>, 0x181000) = 0x7f97520ed000
|
||||||
|
2783 mmap(0x7f9752143000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3</usr/lib/libc.so.6>, 0x1d6000) = 0x7f9752143000
|
||||||
|
2783 mmap(0x7f9752149000, 52888, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f9752149000
|
||||||
|
2783 close(3</usr/lib/libc.so.6>) = 0
|
||||||
|
2783 mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9751f69000
|
||||||
|
2783 arch_prctl(ARCH_SET_FS, 0x7f9751f69740) = 0
|
||||||
|
2783 set_tid_address(0x7f9751f69a10) = 2783
|
||||||
|
2783 set_robust_list(0x7f9751f69a20, 24) = 0
|
||||||
|
2783 rseq({cpu_id_start=0, cpu_id=RSEQ_CPU_ID_UNINITIALIZED, rseq_cs=NULL, flags=0, node_id=0, mm_cid=0, slice_ctrl={request=0, granted=0, __reserved=0}, __reserved=0}, 32, 0, 0x53053053) = 0
|
||||||
|
2783 mprotect(0x7f9752143000, 16384, PROT_READ) = 0
|
||||||
|
2783 mprotect(0x5605de88f000, 4096, PROT_READ) = 0
|
||||||
|
2783 mprotect(0x7f97521b3000, 8192, PROT_READ) = 0
|
||||||
|
2783 prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
|
||||||
|
2783 munmap(0x7f9752158000, 129031) = 0
|
||||||
|
2783 write(2</dev/pts/1<char 136:1>>, "tcpserver: usage: tcpserver [ -461UXpPhHrRoOdDqQv ] [ -c limit ] [ -x rules.cdb ] [ -B banner ] [ -g gid ] [ -u uid ] [ -b backlog ] [ -l localname ] [ -t timeout ] [ -I interface ] host port program\n", 200) = 200
|
||||||
|
2783 exit_group(100) = ?
|
||||||
|
2783 +++ exited with 100 +++
|
||||||
1
example.service/usage
Normal file
1
example.service/usage
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
curl -H 'Authorization: Bearer <your token>' http://localhost:80
|
||||||
28
meson.build
Normal file
28
meson.build
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
project(
|
||||||
|
'nobotgate', 'c',
|
||||||
|
default_options: [
|
||||||
|
'c_std=c99',
|
||||||
|
'warning_level=2',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc = meson.get_compiler('c')
|
||||||
|
deps = [
|
||||||
|
cc.find_library('libowfat'),
|
||||||
|
]
|
||||||
|
|
||||||
|
add_project_arguments(
|
||||||
|
'-DPATH_TMP="'+get_option('path_tmp')+'"',
|
||||||
|
language: 'c',
|
||||||
|
)
|
||||||
|
|
||||||
|
executable('nobotgate', files(
|
||||||
|
'./nobotgate.c',
|
||||||
|
'./parse_token.c',
|
||||||
|
'./check_token.c',
|
||||||
|
'./send_headers.c',
|
||||||
|
), dependencies:deps, install:true)
|
||||||
|
|
||||||
|
executable('nobotgate-access', files(
|
||||||
|
'./nobotgate-access.c',
|
||||||
|
), dependencies:deps, install:true)
|
||||||
6
meson.options
Normal file
6
meson.options
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
option(
|
||||||
|
'path_tmp',
|
||||||
|
type : 'string',
|
||||||
|
value : '/tmp',
|
||||||
|
description : 'path to tmpfs',
|
||||||
|
)
|
||||||
36
nobotgate-access.c
Normal file
36
nobotgate-access.c
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
#include <libowfat/buffer.h>
|
||||||
|
#include <libowfat/errmsg.h>
|
||||||
|
#include <libowfat/str.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#define dieusage() die(100, argv0, " PROG ARGS");
|
||||||
|
|
||||||
|
static void consume_headers(void) {
|
||||||
|
char buf[2048];
|
||||||
|
int r;
|
||||||
|
for (;;) {
|
||||||
|
r=buffer_getline(buffer_0, buf, sizeof buf);
|
||||||
|
if (r==0) die(100,"EOF before header end");
|
||||||
|
if (buf[0]=='\r')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char *header;
|
||||||
|
(void)argc;
|
||||||
|
errmsg_iam(*argv);
|
||||||
|
|
||||||
|
if (argc<2) dieusage();
|
||||||
|
|
||||||
|
consume_headers();
|
||||||
|
|
||||||
|
header = "HTTP/1.0 200 OK\r\n"
|
||||||
|
"Connection: close\r\n"
|
||||||
|
"\r\n";
|
||||||
|
if (write(1, header, str_len(header)) < 0)
|
||||||
|
diesys(111, "write to stdout");
|
||||||
|
execvp(argv[1], argv+1);
|
||||||
|
diesys(111, "exec ", argv[1]);
|
||||||
|
}
|
||||||
57
nobotgate.c
Normal file
57
nobotgate.c
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
#define _XOPEN_SOURCE 700
|
||||||
|
#include <libowfat/buffer.h>
|
||||||
|
#include <libowfat/errmsg.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "nobotgate.h"
|
||||||
|
|
||||||
|
#define dieusage() die(100,"usage: ",argv0," tokenfile allowed-handler denied-handler")
|
||||||
|
|
||||||
|
static stralloc token;
|
||||||
|
static char *tokenfile, *cmd_valid, *cmd_invalid;
|
||||||
|
|
||||||
|
static void run(void) {
|
||||||
|
char tmp[] = PATH_TMP"/nobotgate.XXXXXX";
|
||||||
|
int tmpfd;
|
||||||
|
char buf[8192];
|
||||||
|
buffer b;
|
||||||
|
char *cmd;
|
||||||
|
tmpfd = mkstemp(tmp);
|
||||||
|
|
||||||
|
buffer_init_write(&b,tmpfd,buf,sizeof buf);
|
||||||
|
if (!send_headers(buffer_0, &b))
|
||||||
|
die(111,"copy stdin to temporary file");
|
||||||
|
|
||||||
|
lseek(tmpfd,0,SEEK_SET);
|
||||||
|
buffer_init_read(&b,tmpfd,buf,sizeof buf);
|
||||||
|
if (!parse_token(&b,&token)) {
|
||||||
|
carp("failed to parse token");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd=check_token(tokenfile,&token)
|
||||||
|
? cmd_valid
|
||||||
|
: cmd_invalid;
|
||||||
|
lseek(tmpfd,0,SEEK_SET);
|
||||||
|
dup2(tmpfd,0);
|
||||||
|
unlink(tmp);
|
||||||
|
buffer_close(&b);
|
||||||
|
stralloc_free(&token);
|
||||||
|
carp("execing ",cmd);
|
||||||
|
execlp(cmd,cmd,NULL);
|
||||||
|
err:
|
||||||
|
unlink(tmp);
|
||||||
|
exit(111);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc,char **argv)
|
||||||
|
{
|
||||||
|
errmsg_iam(*argv);
|
||||||
|
argv++; argc--;
|
||||||
|
if (argc != 3) dieusage();
|
||||||
|
tokenfile=argv[0];
|
||||||
|
cmd_valid=argv[1];
|
||||||
|
cmd_invalid=argv[2];
|
||||||
|
run();
|
||||||
|
}
|
||||||
19
nobotgate.h
Normal file
19
nobotgate.h
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef NOBOTGATE
|
||||||
|
#define NOBOTGATE
|
||||||
|
|
||||||
|
#include <libowfat/buffer.h>
|
||||||
|
#include <libowfat/stralloc.h>
|
||||||
|
|
||||||
|
/* buffer shall stream an http request.
|
||||||
|
* it stores the found bearer token to result or
|
||||||
|
* returns 0 if none is found.
|
||||||
|
* always succeeds. */
|
||||||
|
int parse_token(buffer *b, stralloc *result);
|
||||||
|
|
||||||
|
/* return: 1 if the token is valid(i.e. in tokenfile),
|
||||||
|
* 0 else */
|
||||||
|
int check_token(char *tokenfile, stralloc *token);
|
||||||
|
|
||||||
|
int send_headers(buffer *from, buffer *to);
|
||||||
|
|
||||||
|
#endif
|
||||||
34
parse_token.c
Normal file
34
parse_token.c
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
#include <libowfat/stralloc.h>
|
||||||
|
#include <libowfat/buffer.h>
|
||||||
|
#include <libowfat/errmsg.h>
|
||||||
|
#include <libowfat/str.h>
|
||||||
|
|
||||||
|
#define AUTH_HEADER "Authorization: Bearer "
|
||||||
|
#define AUTH_HEADER_LEN str_len(AUTH_HEADER)
|
||||||
|
|
||||||
|
// TODO make case insensitive according to https://www.rfc-editor.org/info/rfc7230/#section-3.2
|
||||||
|
int parse_token(buffer *b, stralloc *result)
|
||||||
|
{
|
||||||
|
stralloc line;
|
||||||
|
int r;
|
||||||
|
stralloc_init(result);
|
||||||
|
for (;;) {
|
||||||
|
r=buffer_getnewline_sa(b,&line);
|
||||||
|
if (r==0) break;
|
||||||
|
if (r<0) { carpsys("read line"); goto err; }
|
||||||
|
|
||||||
|
if (stralloc_starts(&line,AUTH_HEADER)) {
|
||||||
|
stralloc_chomp(&line);
|
||||||
|
if (!stralloc_copyb(result, line.s+AUTH_HEADER_LEN,
|
||||||
|
line.len-AUTH_HEADER_LEN)
|
||||||
|
) { carpsys("out of memory"); goto err; }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stralloc_free(&line);
|
||||||
|
return 1;
|
||||||
|
err:
|
||||||
|
stralloc_free(&line);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
27
send_headers.c
Normal file
27
send_headers.c
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <libowfat/errmsg.h>
|
||||||
|
|
||||||
|
#include "nobotgate.h"
|
||||||
|
|
||||||
|
int send_headers(buffer *from, buffer *to)
|
||||||
|
{
|
||||||
|
char buf[8192];
|
||||||
|
int nread;
|
||||||
|
for (;;) {
|
||||||
|
nread=buffer_getline(from,buf,sizeof buf);
|
||||||
|
if (nread==0) { carp("EOF before header end"); return 0; }
|
||||||
|
if (nread<0) { carpsys("failed reading"); return 0; }
|
||||||
|
/* include \n */
|
||||||
|
nread++;
|
||||||
|
|
||||||
|
if (buffer_put(to,buf,nread)<0) return 0;
|
||||||
|
if (buf[0]=='\r')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer_flush(to)<0) {
|
||||||
|
carpsys("buffer flush");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
5
tool/debug
Executable file
5
tool/debug
Executable file
|
|
@ -0,0 +1,5 @@
|
||||||
|
#!/bin/sh
|
||||||
|
set -eux
|
||||||
|
gdb \
|
||||||
|
-ex 'set args ./example.service/tokens ./example.service/on-valid ./example.service/on-invalid < ./example.input' \
|
||||||
|
./build/nobotgate
|
||||||
Loading…
Add table
Add a link
Reference in a new issue