From fb9e808db02ad954fa06d33f2a1988313cd3965d Mon Sep 17 00:00:00 2001 From: Thomas Bruederli Date: Sun, 17 Sep 2017 15:31:53 +0200 Subject: [PATCH 1/4] Do not attempt to resolve hosts if imapHost given --- bin/apiendpoint.pl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bin/apiendpoint.pl b/bin/apiendpoint.pl index 52346c8..f6d5ad7 100755 --- a/bin/apiendpoint.pl +++ b/bin/apiendpoint.pl @@ -422,8 +422,9 @@ sub handle_signup { $force = 1; } - else { + elsif (not $detail->{imapHost}) { my $Resolver = Net::DNS::Resolver->new; + $Resolver->tcp_timeout(2); my $domain = $detail->{username}; $domain =~ s/.*\@//; my $reply; @@ -526,7 +527,8 @@ sub handle_signup { UseSSL => ($detail->{imapSSL} > 1), UseBlocking => ($detail->{imapSSL} > 1), ); - die "UNABLE TO CONNECT for $detail->{username}\n" unless $imap; + die "UNABLE TO CONNECT for $detail->{username} @ $detail->{imapHost}\n" unless $imap; + # $imap->set_tracing(1); my $ok = $imap->login($detail->{username}, $detail->{password}); die "LOGIN FAILED FOR $detail->{username}" unless $ok; From 9b88e918b4fa508cedb2ca64b17e21327372c95d Mon Sep 17 00:00:00 2001 From: Thomas Bruederli Date: Sun, 17 Sep 2017 17:20:48 +0200 Subject: [PATCH 2/4] Add libnet-libidn-perl to install packages --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 5140ea7..e2bcd89 100644 --- a/Makefile +++ b/Makefile @@ -24,6 +24,7 @@ PACKAGES= \ libjson-xs-perl \ liblocale-gettext-perl \ libswitch-perl \ + libnet-libidn-perl \ nginx \ PERLPACKAGES= \ From 02d64c9a7a16bfbbaad50d5153dc20429efebadd Mon Sep 17 00:00:00 2001 From: Thomas Bruederli Date: Sun, 17 Sep 2017 18:17:41 +0200 Subject: [PATCH 3/4] Dockerize this project - Dockerfile to build an image as instructed in the Makefile - Specific nginx.conf file to be used in Docker (no SSL) - entrypoint.sh for the Docker container starting the proxy --- Dockerfile | 61 ++++++++++++++++++++ docker/entrypoint.sh | 14 +++++ docker/nginx.conf | 131 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 206 insertions(+) create mode 100644 Dockerfile create mode 100644 docker/entrypoint.sh create mode 100644 docker/nginx.conf diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..1849be9 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,61 @@ +FROM debian:jessie-slim + +WORKDIR /root + +RUN apt-get update +RUN apt-get -y install build-essential \ + libanyevent-httpd-perl \ + libdata-uuid-libuuid-perl \ + libdatetime-perl \ + libdbd-sqlite3-perl \ + libdbi-perl \ + libemail-address-perl \ + libemail-mime-perl \ + libhtml-parser-perl \ + libhtml-strip-perl \ + libhttp-date-perl \ + libhttp-tiny-perl \ + libimage-size-perl \ + libio-socket-ssl-perl \ + libencode-imaputf7-perl \ + libjson-perl \ + libjson-xs-perl \ + liblocale-gettext-perl \ + libswitch-perl \ + libexpat1-dev \ + libnet-libidn-perl \ + curl \ + git \ + nginx + +RUN cpan; true + +RUN perl -MCPAN -e 'my $c = "CPAN::HandleConfig"; $c->load(doit => 1, autoconfig => 1); $c->edit(prerequisites_policy => "follow"); $c->edit(build_requires_install_policy => "yes"); $c->commit' + +RUN curl -L -O http://www.cpan.org/authors/id/C/CI/CINDY/AnyEvent-HTTPD-SendMultiHeaderPatch-0.001003.tar.gz && \ + tar xf AnyEvent-HTTPD-SendMultiHeaderPatch-0.001003.tar.gz && \ + cd AnyEvent-HTTPD-SendMultiHeaderPatch-0.001003 && \ + perl Makefile.PL && \ + make install + +ENV PERLPACKAGES "Test::Requires Mouse AnyEvent::HTTP AnyEvent::HTTPD::CookiePatch AnyEvent::IMAP Cookie::Baker Date::Parse Email::Sender::Simple Email::Sender::Transport::SMTPS HTML::GenerateUtil IO::LockedFile Mail::IMAPTalk Moose Net::CalDAVTalk Net::CardDAVTalk Net::DNS Net::Server::Fork Template" + +RUN for PACKAGE in $PERLPACKAGES; do cpan $PACKAGE; done + +RUN adduser --quiet --disabled-login --gecos "JMAP" jmap || true +RUN install -o jmap -g jmap -m 755 -d /home/jmap/data +RUN mkdir -p /home/jmap/data + +COPY . /home/jmap/jmap-perl + +WORKDIR /home/jmap/jmap-perl + +RUN rm /etc/nginx/sites-enabled/default + +COPY docker/nginx.conf /etc/nginx/sites-enabled/ + +COPY docker/entrypoint.sh /root/ + +EXPOSE 80 + +CMD ["sh", "/root/entrypoint.sh"] diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh new file mode 100644 index 0000000..9c5b52a --- /dev/null +++ b/docker/entrypoint.sh @@ -0,0 +1,14 @@ +#! /bin/sh + +# Find the docker IP +IP=`ip addr | awk '/inet 172/ { print $2 }' | cut -d'/' -f1` +# Replace all occurrence of "proxy.jmap.io" by the docker IP +sed -i "s?https://proxy.jmap.io?http://$IP?g" ./bin/server.pl ./htdocs/landing.html ./JMAP/API.pm ./JMAP/DB.pm +# Or can be occurrence of previous docker IP +sed -i "s?http://172[^/]*?http://$IP?g" ./bin/server.pl ./htdocs/landing.html ./JMAP/API.pm ./JMAP/DB.pm + +export jmaphost=$IP + +service nginx start +perl ./bin/server.pl & +perl ./bin/apiendpoint.pl diff --git a/docker/nginx.conf b/docker/nginx.conf new file mode 100644 index 0000000..0b9b6f8 --- /dev/null +++ b/docker/nginx.conf @@ -0,0 +1,131 @@ +server { + listen 80; + + root /home/jmap/jmap-perl/htdocs/; + index index.html index.htm; + server_name proxy.jmap.io; + + location / { + # First attempt to serve request as file, then + # as directory, then fall back to displaying a 404. + try_files $uri $uri/ /index.html; + } + + location = / { + if ( $request_method = 'OPTIONS' ) { + add_header 'Access-Control-Allow-Origin' '*'; + + # -D GAPING_SECURITY_HOLE + add_header 'Access-Control-Allow-Headers' $http_access_control_request_headers; + add_header 'Access-Control-Allow-Methods' 'POST, GET, OPTIONS'; + add_header 'Access-Control-Max-Age' 600; + add_header 'Content-Type' 'text/plain; charset=UTF-8'; + add_header 'Content-Length' 0; + + return 204; + } + + # First attempt to serve request as file, then + # as directory, then fall back to displaying a 404. + proxy_pass http://127.0.0.1:9000/home; + } + + location /events/ { + if ( $request_method = 'OPTIONS' ) { + add_header 'Access-Control-Allow-Origin' '*'; + + # -D GAPING_SECURITY_HOLE + add_header 'Access-Control-Allow-Headers' $http_access_control_request_headers; + add_header 'Access-Control-Allow-Methods' 'POST, GET, OPTIONS'; + add_header 'Access-Control-Max-Age' 600; + add_header 'Content-Type' 'text/plain; charset=UTF-8'; + add_header 'Content-Length' 0; + + return 204; + } + + # Immediately send backend responses back to client + proxy_buffering off; + + # Disable keepalive to browser + keepalive_timeout 0; + + # It's a long lived backend connection with potentially a long time between + # push events, make sure proxy doesn't timeout + proxy_read_timeout 7200; + + proxy_pass http://127.0.0.1:9001/events/; + } + + location /files/ { + proxy_pass http://127.0.0.1:9000/files/; + } + + location /jmap/ { + if ( $request_method = 'OPTIONS' ) { + add_header 'Access-Control-Allow-Origin' '*'; + + # -D GAPING_SECURITY_HOLE + add_header 'Access-Control-Allow-Headers' $http_access_control_request_headers; + add_header 'Access-Control-Allow-Methods' 'POST, GET, OPTIONS'; + add_header 'Access-Control-Max-Age' 600; + add_header 'Content-Type' 'text/plain; charset=UTF-8'; + add_header 'Content-Length' 0; + + return 204; + } + + proxy_pass http://127.0.0.1:9000/jmap/; + } + + location /upload/ { + if ( $request_method = 'OPTIONS' ) { + add_header 'Access-Control-Allow-Origin' '*'; + + # -D GAPING_SECURITY_HOLE + add_header 'Access-Control-Allow-Headers' $http_access_control_request_headers; + add_header 'Access-Control-Allow-Methods' 'POST, GET, OPTIONS'; + add_header 'Access-Control-Max-Age' 600; + add_header 'Content-Length' 0; + add_header 'Content-Type' 'text/plain; charset=UTF-8'; + + return 204; + } + + add_header 'Access-Control-Allow-Origin' '*'; + + proxy_pass http://127.0.0.1:9000/upload/; + } + + location /raw/ { + proxy_pass http://127.0.0.1:9000/raw/; + } + + location /A { + proxy_pass http://127.0.0.1:9000/A; + } + + location /J { + proxy_pass http://127.0.0.1:9000/J; + } + + location /U { + proxy_pass http://127.0.0.1:9000/U; + } + + location /register { + proxy_pass http://127.0.0.1:9000/register; + } + + location /signup { + proxy_pass http://127.0.0.1:9000/signup; + } + + location /delete { + proxy_pass http://127.0.0.1:9000/delete; + } + + location /cb { + proxy_pass http://127.0.0.1:9000/cb; + } +} From 7078eff51ab5fe4c9f0e707f5399ebf9206ac6ad Mon Sep 17 00:00:00 2001 From: Thomas Bruederli Date: Tue, 19 Sep 2017 21:30:37 +0200 Subject: [PATCH 4/4] Pimp readme with markdown formatting and add instructions for Docker --- README => README.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) rename README => README.md (57%) diff --git a/README b/README.md similarity index 57% rename from README rename to README.md index 35a7a51..f8b6977 100644 --- a/README +++ b/README.md @@ -12,3 +12,27 @@ support the CONDSTORE extension, (RFC4551/RFC7162). A separate backend for Gmail is provided, because Gmail has native server-side thread support, meaning that threading does not need to be calculated locally. + + +Installation +------------ + +See the [INSTALL](./INSTALL) instructions in this repository. + + +Run in Docker +------------- + +Build a Docker image from this repository using the included [Dockerfile](./Dockerfile): + +``` +docker build -t local/jmap-perl . +``` + +Run the JMAP Proxy Docker container: + +``` +docker run -p 8088:80 --name=jmap-proxy -d local/jmap-perl +``` + +Now connect to the running proxy via http://localhost:8088