aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile89
-rw-r--r--README.md8
-rw-r--r--config.def.mk11
-rw-r--r--favicon.icobin9278 -> 26790 bytes
-rwxr-xr-xgenpass.pl84
-rwxr-xr-xgpigeon-template.cgi117
-rw-r--r--index.html29
-rw-r--r--link-tmpl-template.cgi24
-rw-r--r--nginx-example.conf6
-rw-r--r--styles.css163
10 files changed, 390 insertions, 141 deletions
diff --git a/Makefile b/Makefile
index 24b9489..000e898 100644
--- a/Makefile
+++ b/Makefile
@@ -6,10 +6,35 @@
BOLD=\033[01m
RED=\033[31m
STOP=\033[0m
-RANDOM_ARGON2 := $(shell perl genpass.pl > genpass.txt && tail -1 genpass.txt)
include config.mk
+RANDOM_ARGON2 := $(shell perl genpass.pl > genpass.txt && tail -1 genpass.txt)
+_GPGID := $(shell gpg --with-colons -k $(MYMAIL_ADDR) | grep "pub:u" | cut -d':' -f5)
gpigeon: gpigeon-template.cgi link-tmpl-template.cgi
+ @if test -n '$(MYMAIL_ADDR)'; then \
+ printf "Your mail address is ${BOLD}$(MYMAIL_ADDR)${STOP}\n"; \
+ sed -e 's|your_addr_goes_here|$(MYMAIL_ADDR)|g' link-tmpl-template.cgi > link-tmpl.cgi; \
+ else \
+ printf "${RED}There's no mail adress configured for gpigeon in your config.mk !${STOP}\n" ; \
+ $(MAKE) clean ; \
+ exit 1; \
+ fi
+
+ @if test -n '$(MAILSENDER)'; then \
+ printf "Encrypted mails will be sent from ${BOLD}$(MAILSENDER)${STOP}\n"; \
+ sed -e 's|sender_addr_goes_here|$(MAILSENDER)|g' -i link-tmpl.cgi; \
+ else \
+ printf "\t${RED}No mail sender adress configured in your config.mk. Fix this.${STOP}\n" ; \
+ $(MAKE) clean ; \
+ exit 1; \
+ fi
+ @if test -n '$(_GPGID)'; then \
+ printf "Your GPG 0xlong id is ${BOLD}$(_GPGID)${STOP}\n";\
+ sed -e 's|gpgid_goes_here|0x$(_GPGID)|g' -i link-tmpl.cgi;\
+ else \
+ printf "${RED}It seems that no public GPG key is tied to ${BOLD}$(MYMAIL_ADDR)${STOP}\n";\
+ exit 1; \
+ fi
@if test -z '$(PREFIX)'; then \
printf "\n$(RED)No \u0024PREFIX variable defined in config.mk.\n";\
printf "Look into config.def.mk for the defaults and fix that.$(STOP)\n";\
@@ -41,70 +66,40 @@ gpigeon: gpigeon-template.cgi link-tmpl-template.cgi
fi
@if test -n '$(LINK_TEMPLATE_PATH)'; then \
printf "\nLink template is at ${BOLD}$(LINK_TEMPLATE_PATH)${STOP}"; \
- sed -e 's|link_template_path_goes_here|$(LINK_TEMPLATE_PATH)|g' gpigeon-template.cgi > gpigeon.cgi; \
+ sed -e 's|link_template_path_goes_here|$(LINK_TEMPLATE_PATH)|g' -i gpigeon.cgi; \
else \
printf "\n${RED}The path for the link template wasn't set in your config.mk. Fix that.${STOP}" ;\
exit 1;\
fi
@if test -n '$(ARGON2ID_HASH)'; then\
- printf "\nThe argon2id hash is ${BOLD}$(ARGON2ID_HASH)${STOP}"; \
- sed -e 's|argon2id_hash_goes_here|$(ARGON2ID_HASH)|g' gpigeon-template.cgi > gpigeon.cgi; \
+ printf "\nThe argon2id hash is ${BOLD}${ARGON2ID_HASH}${STOP}\n"; \
+ sed -e 's|argon2id_hash_goes_here|$(ARGON2ID_HASH)|g' -i gpigeon.cgi; \
else \
- sed -e 's|argon2id_hash_goes_here|$(RANDOM_ARGON2)|g' gpigeon-template.cgi > gpigeon.cgi; \
+ sed -e 's|argon2id_hash_goes_here|$(RANDOM_ARGON2)|g' -i gpigeon.cgi; \
printf "\nThe variable ARGON2ID_HASH wasn't declared in your config.mk thus a password \nand its argon2id hash as been generated (look into `pwd`/genpass.txt)."; \
printf "\nYour password is:\n${BOLD}`head -1 genpass.txt`${STOP}"; \
printf "\nAnd the hash is:\n${BOLD}%s${STOP}\n\n" '${RANDOM_ARGON2}'; \
rm -f genpass.txt; \
fi
-
-
-
- @if test -n '$(MYGPG_ID_0XLONG)'; then \
- printf "Mails will be encrypted to you with the ${BOLD}$(MYGPG_ID_0XLONG)${STOP} GPG key\n"; \
- sed -e 's|gpgid_goes_here|$(MYGPG_ID_0XLONG)|g' link-tmpl-template.cgi > link-tmpl.cgi; \
- gpg --armor --export $(MYGPG_ID_0XLONG) > gpg.txt; \
- else \
- printf "${RED}No GPG key found because the 0xlong fingerprint format wasn't set in config.mk. Fix this.${STOP}\n";\
- $(MAKE) clean;\
- exit 1 ;\
- fi
-
@if test -n '$(MSG_FORM_CHAR_LIMIT)'; then \
printf "Message form will have a message limit of ${BOLD}$(MSG_FORM_CHAR_LIMIT) characters${STOP}\n"; \
- sed -e "s|msg_char_limit_goes_here|$(MSG_FORM_CHAR_LIMIT)|g" link-tmpl-template.cgi > link-tmpl.cgi;\
+ sed -e "s|msg_char_limit_goes_here|$(MSG_FORM_CHAR_LIMIT)|g" -i link-tmpl.cgi;\
else \
printf "${RED}No character limits were defined in your config.mk. Fix that.${STOP}\n" ;\
$(MAKE) clean ;\
exit 1;\
fi
- @if test -n '$(MYMAIL_ADDR)'; then \
- printf "Your mail address is ${BOLD}$(MYMAIL_ADDR)${STOP}\n"; \
- sed -e 's|your_addr_goes_here|$(MYMAIL_ADDR)|g' link-tmpl-template.cgi > link-tmpl.cgi; \
- else \
- printf "There's no mail adress configured for gpigeon in your config.mk !\n" ; \
- $(MAKE) clean ; \
- exit 1; \
- fi
-
@if [ '${HAS_MAILSERVER}' == '1' ]; then \
printf "Local mail server setup. ${BOLD}Mail::Sendmail module will be used to send the mails${STOP}.\n"; \
else \
printf "External mail server setup. ${BOLD}Net::SMTPS module will be used to send the mails${STOP}.\n"; \
- if test -n '$(MAILSENDER)'; then \
- printf "\tEncrypted mails will be sent from ${BOLD}$(MAILSENDER)${STOP}\n"; \
- sed -e 's|sender_addr_goes_here|$(MAILSENDER)|g' link-tmpl-template.cgi > link-tmpl.cgi; \
- else \
- printf "\t${RED}No mail sender adress configured in your config.mk. Fix this.${STOP}\n" ; \
- $(MAKE) clean ; \
- exit 1; \
- fi; \
if test -n '$(MAILSENDER_PW)'; then \
printf "\tPassword for ${BOLD}${MAILSENDER}${STOP} is %s.\n" '${MAILSENDER_PW}'; \
- sed -e 's|sender_pw_goes_here|$(MAILSENDER_PW)|g' link-tmpl-template.cgi > link-tmpl.cgi; \
+ sed -e 's|sender_pw_goes_here|$(MAILSENDER_PW)|g' -i link-tmpl.cgi; \
else\
printf "\t${RED}Password for the sender address wasn't set in your config.mk. Fix this${STOP}.\n";\
$(MAKE) clean ; \
@@ -112,7 +107,7 @@ gpigeon: gpigeon-template.cgi link-tmpl-template.cgi
fi; \
if test -n '$(SMTP_DOMAIN)'; then \
printf "\tSMTP server: ${BOLD}$(SMTP_DOMAIN)${STOP}\n"; \
- sed -e 's|smtp_domain_goes_here|$(SMTP_DOMAIN)|g' link-tmpl-template.cgi > link-tmpl.cgi; \
+ sed -e 's|smtp_domain_goes_here|$(SMTP_DOMAIN)|g' -i link-tmpl.cgi; \
else\
printf "\t${RED}No SMTP server was configured in your config.mk. Fix this.${STOP}\n";\
$(MAKE) clean ; \
@@ -120,19 +115,16 @@ gpigeon: gpigeon-template.cgi link-tmpl-template.cgi
fi; \
if test -n '$(SMTP_PORT)'; then \
printf "\tSMTP port: ${BOLD}$(SMTP_PORT)${STOP}\n"; \
- sed -e 's|smtp_port_goes_here|$(SMTP_PORT)|g' link-tmpl-template.cgi > link-tmpl.cgi; \
+ sed -e 's|smtp_port_goes_here|$(SMTP_PORT)|g' -i link-tmpl.cgi; \
else \
printf "\t${RED}No SMTP port configured in your config.mk. Fix this${STOP}.\n"; \
$(MAKE) clean ; \
exit 1; \
fi; \
fi
- @sed -e 's|has_mailserver_goes_here|$(HAS_MAILSERVER)|g' link-tmpl-template.cgi > link-tmpl.cgi
- @sed -e 's|gpg_homedir_goes_here|$(_GPG_HOMEDIR)|g' link-tmpl-template.cgi > link-tmpl.cgi
- @if test -n '$(WWWDOMAIN)' && test -n '$(WWWPREFIX)'; then\
- $(MAKE) nginxconf;\
- printf "Done generating $(WWWDOMAIN).conf for nginx.";\
- fi
+ @sed -e 's|has_mailserver_goes_here|$(HAS_MAILSERVER)|g' -i link-tmpl.cgi
+ @sed -e 's|gpg_homedir_goes_here|$(_GPG_HOMEDIR)|g' -i link-tmpl.cgi
+ $(MAKE) nginxconf
@printf "\nDone preparing files. You can now type\nsudo make install\nin your terminal.\n"
install:
@@ -146,13 +138,16 @@ install:
install -Dm644 index.html favicon.ico styles.css -t $(DESTDIR)$(WWWPREFIX)/gpigeon/
install -Dm755 merci/* -t $(DESTDIR)$(PREFIX)/merci/
@if test -e '$(WWWDOMAIN).conf'; then\
- printf "\nInstalling $(WWWDOMAIN).conf into $(NGINXCONFDIR)\n";\
- install -Dm644 $(WWWDOMAIN).conf -t $(DESTDIR)$(NGINXCONFDIR);\
+ printf "\nInstalling $(WWWDOMAIN).conf into $(SITESENABLED)\n";\
+ install -Dm644 $(WWWDOMAIN).conf -t $(DESTDIR)$(SITESENABLED);\
fi
chown $(WWWUSER):$(WWWUSER) -R $(DESTDIR)$(PREFIX)/gpigeon || exit 1;
chown $(WWWUSER):$(WWWUSER) -R $(DESTDIR)$(WWWPREFIX)/gpigeon || exit 1;
nginxconf: nginx-example.conf
+ @if test -n '$(WWWDOMAIN)' && test -n '$(WWWPREFIX)'; then\
+ printf "Done generating $(WWWDOMAIN).conf for nginx.";\
+ fi
@sed -e 's|wwwpath_goes_here|$(WWWPREFIX)|g;s|domain_goes_here|$(WWWDOMAIN)|g' nginx-example.conf > $(WWWDOMAIN).conf ;\
diff --git a/README.md b/README.md
index 9a27592..8be7b9a 100644
--- a/README.md
+++ b/README.md
@@ -18,7 +18,7 @@ Features
- A table of the links generated is visible when you connect so you can
keep track of what has been created. You can also delete link
individually, or all at once.
-- No javascript used for the moment.
+- No javascript used at the moment.
Dependencies
============
@@ -94,6 +94,12 @@ server {
fastcgi_pass unix:/run/fcgiwrap.sock;
include /etc/nginx/fastcgi_params;
}
+
+ add_header Strict-Transport-Security "max-age=63072000; preload";
+ add_header Content-Security-Policy "default-src 'self'";
+ add_header X-Frame-Options DENY;
+ add_header Access-Control-Allow-Origin https://$server_name;
+ add_header Vary Origin; # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin#cors_and_caching
}
```
You can also tune the `WWWDOMAIN` and `NGINXCONFDIR` variable in your `config.mk` to have it generated for you when running `make`.
diff --git a/config.def.mk b/config.def.mk
index b02f14f..28c435c 100644
--- a/config.def.mk
+++ b/config.def.mk
@@ -2,27 +2,26 @@
# paths
PREFIX = /usr/share/gpigeon
+WWWPREFIX = /var/www
COOKIES_DIR = $(PREFIX)/cookies
_GPG_HOMEDIR = $(PREFIX)/gnupg
LINK_TEMPLATE_PATH = $(PREFIX)/link-tmpl.cgi
-WWWPREFIX = /var/www
GPIGEON_PATH = $(WWWPREFIX)/cgi-bin/gpigeon.cgi
# system stuff
WEBUSER=www-data #it must match up with your nginx user. For ex. on arch it's 'http'
-# CGI tuning stuff
+# form customization stuff
MSG_FORM_CHAR_LIMIT = 3000
# argon2id hash. generated by genpass.pl if empty when running make
ARGON2ID_HASH =
-# gpg and email vars
+# email related
HAS_MAILSERVER = 0# choose 0 if you'll use an external mail server, 1 if local mail server installed.
-# you don't need to set the 3 last variables if you got a local mailserver.
-MYGPG_ID_0XLONG =# the 0xlong format of your gpg key. - required
MYMAIL_ADDR =# your mail address - required
MAILSENDER =# the mailer address that'll send you the encrypted mails - required
+# you don't need to set the 3 last variables if you got a local mailserver.
MAILSENDER_PW =# password for the mailer address
SMTP_DOMAIN =# smtp domain pour the mailer
SMTP_PORT =# smtp port for the mailer
@@ -30,4 +29,4 @@ SMTP_PORT =# smtp port for the mailer
#optional, domain to generate nginx config for
#and where to put the config
WWWDOMAIN=
-NGINXCONFDIR=/etc/nginx/sites-enabled
+SITESENABLED=/etc/nginx/sites-enabled
diff --git a/favicon.ico b/favicon.ico
index 83bbd77..0db8263 100644
--- a/favicon.ico
+++ b/favicon.ico
Binary files differ
diff --git a/genpass.pl b/genpass.pl
index 44b0f53..a57d98b 100755
--- a/genpass.pl
+++ b/genpass.pl
@@ -1,9 +1,85 @@
#! /usr/bin/perl
+# genpass.pl: generate argon2id hash from a random password. Can be used
+# interactively.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+# Copyright (c) 2021, Miquel Lionel <lionel@les-miquelots.net>
+
use warnings;
use strict;
+use File::Copy qw(move);
use Crypt::Argon2 qw/argon2id_pass/;
-my $pass = `openssl rand -base64 32`;
+use Term::ReadKey;
+use Term::ANSIColor qw(:constants);
my $salt = `openssl rand 16`;
-chomp $pass;
-print $pass,"\n";
-print argon2id_pass($pass, $salt, 3, '32M', 1, 32);
+my $opt = $ARGV[0];
+
+sub FillConfigMk {
+ my $hash = shift;
+ $hash =~ s/\$/\\044/g;
+ my $mkconfig = 'config.mk';
+ if (-e $mkconfig){
+ open my $in, '<', $mkconfig or die "$!";
+ open my $out, '>', "$mkconfig.tmp" or die "$!";
+ while (<$in>){
+ s/ARGON2ID_HASH =.*/ARGON2ID_HASH = `printf "$hash"`/gi;
+ print $out $_;
+ }
+ close $out;
+ close $in;
+ move("$mkconfig.tmp", $mkconfig) or die "Uh oh, move failed: $!";
+ print "Done modifying $mkconfig\n";
+ }
+}
+
+
+if (defined $opt){
+ if ($opt eq '-i'){ # interactive
+ print "Password: ";
+ ReadMode 2;
+ my $pass = <STDIN>;
+ chomp $pass;
+ while (length($pass) < 10){
+ print "\nYour password is below 10 characters. Fix this: ";
+ $pass = <STDIN>;
+ chomp $pass;
+ }
+ print "\nRetype password: ";
+ my $confirm = <STDIN>;
+ chomp $confirm;
+ my $same = $pass cmp $confirm;
+ if (not $same == 0){
+ ReadMode 1;
+ die "\nPasswords don't match.";
+ }
+ ReadMode 1;
+
+ print "\n\nWant to see your typed password ? [y/n] : ";
+ my $ynchoice = <STDIN>;
+ chomp $ynchoice;
+ if ($ynchoice eq 'y' or $ynchoice eq 'o'){
+ print "\nYour password is ", BOLD, "$pass", RESET;
+ }
+ my $hash = argon2id_pass($pass, $salt, 3, '32M', 1, 32);
+ print "\nThe resulting argon2id hash is: ", BOLD, $hash, RESET, "\n";
+ FillConfigMk($hash);
+ }
+}
+else {
+ my $pass = `openssl rand -base64 32`;
+ chomp $pass;
+ print $pass,"\n";
+ print argon2id_pass($pass, $salt, 3, '32M', 1, 32);
+}
diff --git a/gpigeon-template.cgi b/gpigeon-template.cgi
index 6ee79d9..e8c5036 100755
--- a/gpigeon-template.cgi
+++ b/gpigeon-template.cgi
@@ -1,7 +1,24 @@
#! /usr/bin/perl -T
+# gpigeon.cgi: generate links for someone to send you GPG encrypted messages via a one time form.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+# Copyright (c) 2020-2021, Miquel Lionel <lionel@les-miquelots.net>
use warnings;
use strict;
+use File::Path qw(mkpath rmtree);
use Crypt::Argon2 qw(argon2id_verify);
use Email::Valid;
use String::Random;
@@ -9,60 +26,76 @@ use CGI qw(param);
use CGI::Cookie;
use CGI::Carp qw(fatalsToBrowser);
+my $uagent = $ENV{HTTP_USER_AGENT};
+my $rIP = $ENV{REMOTE_ADDR};
+my $hostname = $ENV{'SERVER_NAME'};
+
sub ValidCookie {
my $client_login_cookie = shift;
my $dir = shift;
+ my $filename = $client_login_cookie->value;
+ my $login_cookiefile = "$dir/$filename.txt";
+
if (not defined $client_login_cookie){
return;
}
- my $cookie_line = undef;
- my $filename = $client_login_cookie->value;
if ($filename =~ /^([\w]+)$/){
$filename = $1;
}
else{
return;
}
- my $login_cookiefile = "$dir/$filename.txt";
+
if (-e $login_cookiefile){
open my $in, '<', $login_cookiefile or die "can't read file: $!";
- my $cookie_line = readline $in;
+ $rip_line = readline $in;
+ $ua_line = readline $in;
+ $cookie_line = readline $in;
close $in;
+ chomp ($rip_line, $ua_line);
if (not defined $cookie_line){
return;
}
+ my %magic_cookie = CGI::Cookie->parse($cookie_line) or die "$!";
+ my $magic_cookie_val = $magic_cookie{'id'}->value;
+
+ my $rip_match = $rip_line cmp $rIP;
+ my $ua_match = $ua_line cmp $uagent;
+ my $magic_match = $magic_cookie_val cmp $client_login_cookie->value;
+
+ if ($rip_match == 0 and $ua_match == 0 and $magic_match == 0){
+ return 1;
+ }
}
else{
return;
}
-
- if ($client_login_cookie == $cookie_line){
- return 1;
- }
return;
-
}
sub LoginCookieGen {
my $id_cookie = shift;
my $dir = shift;
- my $str_rand_obj = String::Random->new;
- my $val = $str_rand_obj->randregex('\w{64}');
- my $cookiefile = "$dir/$val.txt";
- my $new_login_cookie = CGI::Cookie->new(
- -name => 'id',
- -value => $val,
- -expires => '+1y',
- '-max-age' => '+1y',
- -domain => ".$ENV{'SERVER_NAME'}",
- -path => '/',
- -secure => 1,
- -httponly => 1,
- -samesite => 'Strict',
- ) or die "Can't create cookie: $!";
if (not defined $id_cookie){
+ if (not -d "$dir"){
+ mkpath("$dir") or die "$!";
+ }
+ my $str_rand_obj = String::Random->new;
+ my $val = $str_rand_obj->randregex('\w{64}');
+ my $cookiefile = "$dir/$val.txt";
+ my $new_login_cookie = CGI::Cookie->new(
+ -name => 'id',
+ -value => $val,
+ -expires => '+1y',
+ '-max-age' => '+1y',
+ -domain => ".$hostname",
+ -path => '/',
+ -secure => 1,
+ -httponly => 1,
+ -samesite => 'Strict',
+ ) or die "Can't create cookie: $!";
open my $out, '>', $cookiefile or die "Can't write to $cookiefile: $!";
- print $out "$new_login_cookie";
+ print $out "$rIP\n$uagent\n$new_login_cookie";
close $out;
print "Set-Cookie: $new_login_cookie\n";
}
@@ -102,7 +135,6 @@ my ($linkgen_notif, $link_asker, $mailisok_notif, $deletion_notif,
my @created_links = ();
delete @ENV{qw(IFS PATH CDPATH BASH_ENV)};
$ENV{'PATH'} = '/usr/bin';
-my $hostname = $ENV{'SERVER_NAME'};
my $argon2id_hash = q{argon2id_hash_goes_here};
my $cookies_dir = q{cookies_dir_goes_here};
@@ -127,7 +159,7 @@ my %text_strings = (
link_del_failed => 'Deletion failed and here is why : ',
mailto_body => 'Your link is ',
mailto_subject => 'Link to your one time GPG messaging form',
- notif_login_failure => 'Cannot login. Check if your username and password match.'
+ notif_login_failure => 'Cannot login. Check if your username and password match.',
refresh_btn_text => 'Refresh',
type_msg_below => 'Type your message below',
theader_link => 'Link',
@@ -146,12 +178,13 @@ if (not defined $id_cookie){
$hidden_pwfield = qq{<input type="hidden" name="password" value="$pw">};
$refresh_form = qq{<form method="POST">
$hidden_pwfield
- <input type="submit" value="$text_strings{refresh_btn_text}">
+ <input id="refreshbtn" type="submit" value="$text_strings{refresh_btn_text}">
</form>};
}
else{
+ $hidden_pwfield = '<!-- undef -->';
$refresh_form = qq{<form method="GET">
- <input type="submit" value="$text_strings{refresh_btn_text}">
+ <input id="refreshbtn" type="submit" value="$text_strings{refresh_btn_text}">
</form>};
$idval = $id_cookie->value;
@@ -188,10 +221,10 @@ if (ValidCookie($id_cookie, $cookies_dir) or argon2id_verify($argon2id_hash,$pw)
my $pending_deletion = $cgi_query_get->param('supprlien');
my $linkfile_fn = "./l/$pending_deletion";
if (unlink UntaintCGIFilename($linkfile_fn)){
- $deletion_notif = qq{<span style="color:green">$text_strings{link_del_ok}</span>};
+ $deletion_notif = qq{<span id="success">$text_strings{link_del_ok}</span>};
}
else {
- $deletion_notif = qq{<span style="color:red">$text_strings{link_del_failed} $linkfile_fn : $!</span>};
+ $deletion_notif = qq{<span id="failure">$text_strings{link_del_failed} $linkfile_fn : $!</span>};
}
}
@@ -200,7 +233,7 @@ if (ValidCookie($id_cookie, $cookies_dir) or argon2id_verify($argon2id_hash,$pw)
while (readdir $link_dir_handle) {
if ($_ ne '.' and $_ ne '..'){
unlink UntaintCGIFilename("./l/$_") or die "$!";
- $deletion_notif = qq{<span style="color:green">$text_strings{link_del_ok}</span>};
+ $deletion_notif = qq{<span id="success">$text_strings{link_del_ok}</span>};
}
}
closedir $link_dir_handle;
@@ -210,7 +243,7 @@ if (ValidCookie($id_cookie, $cookies_dir) or argon2id_verify($argon2id_hash,$pw)
$link_asker = scalar $cgi_query_get->param('mail');
if ( Email::Valid->address($link_asker) ){
- $mailisok_notif = qq{<span style="color:green">$text_strings{addr} $link_asker $text_strings{addr_ok}</span>};
+ $mailisok_notif = qq{<span id="success">$text_strings{addr} $link_asker $text_strings{addr_ok}</span>};
my $escaped_link_asker = EscapeArobase($link_asker);
my $str_rand_obj = String::Random->new;
my $generated_form_filename = $str_rand_obj->randregex('\w{64}') . '.cgi';
@@ -230,10 +263,10 @@ if (ValidCookie($id_cookie, $cookies_dir) or argon2id_verify($argon2id_hash,$pw)
close $in or die;
chmod(0755,$link_path) or die;
close $out or die;
- $linkgen_notif = qq{<span style="color:green">$text_strings{link_ok_for} $link_asker: </span><br><a href="$href">$href</a>};
+ $linkgen_notif = qq{<span id="success">$text_strings{link_ok_for} $link_asker: </span><br><a href="$href">$href</a>};
}
else{
- $mailisok_notif = qq{<span style="color:red">$text_strings{addr} $link_asker $text_strings{addr_nok}.</span>};
+ $mailisok_notif = qq{<span id="failure">$text_strings{addr} $link_asker $text_strings{addr_nok}.</span>};
}
}
@@ -249,7 +282,7 @@ if (ValidCookie($id_cookie, $cookies_dir) or argon2id_verify($argon2id_hash,$pw)
}
close $linkfile_handle;
- if (Email::Valid->address($link_asker){
+ if (Email::Valid->address($link_asker)){
push @created_links,
qq{<tr>
<td><a href="/cgi-bin/l/$linkfile_fn">$text_strings{here}</a></td>
@@ -258,7 +291,7 @@ if (ValidCookie($id_cookie, $cookies_dir) or argon2id_verify($argon2id_hash,$pw)
<form method="POST">
$hidden_pwfield
<input type="hidden" name="supprlien" value="$linkfile_fn">
- <input type="submit" value="$text_strings{delete_link_btn_text}">
+ <input id="deletelinkbtn" type="submit" value="$text_strings{delete_link_btn_text}">
</form>
</td>
</tr>};
@@ -286,7 +319,7 @@ if (ValidCookie($id_cookie, $cookies_dir) or argon2id_verify($argon2id_hash,$pw)
<p>$text_strings{web_greet_msg}</p>
<form method="GET">
<input type="hidden" name="logout" value="1">
- <input type="submit" value="$text_strings{logout_btn_text}">
+ <input id="logoutbtn" type="submit" value="$text_strings{logout_btn_text}">
</form>
$refresh_form
<hr>
@@ -295,7 +328,7 @@ if (ValidCookie($id_cookie, $cookies_dir) or argon2id_verify($argon2id_hash,$pw)
$hidden_pwfield
$text_strings{link_asker_field_label}<br>
<input tabindex="1" type="text" name="mail">
- <input tabindex="2" type="submit" value="$text_strings{create_link_btn}">
+ <input id="genlinkbtn" tabindex="2" type="submit" value="$text_strings{create_link_btn}">
</form>},
NotifIfDefined($mailisok_notif),
'<br>',
@@ -304,14 +337,14 @@ if (ValidCookie($id_cookie, $cookies_dir) or argon2id_verify($argon2id_hash,$pw)
<form method="POST">
$hidden_pwfield
<input type="hidden" name="supprtout">
- <input type="submit" value="$text_strings{delete_links_btn_text}">
+ <input id="deleteallbtn" type="submit" value="$text_strings{delete_links_btn_text}">
</form>},
NotifIfDefined($deletion_notif),
qq{<table>
<tr>
- <th>$text_strings{theader_link}</th>
- <th>$text_strings{theader_for}</th>
- <th>$text_strings{theader_deletion}</th>
+ <th>$text_strings{theader_link} &#128279;</th>
+ <th>$text_strings{theader_for} &#128231;</th>
+ <th>$text_strings{theader_deletion} &#128465;</th>
</tr>
@created_links
</table>
diff --git a/index.html b/index.html
index b88c8a0..e5f3e13 100644
--- a/index.html
+++ b/index.html
@@ -1,19 +1,28 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
<title>GPIGEON - Login</title>
- <link rel="icon" type="image/x-icon" href="/favicon.ico">
- <link rel="stylesheet" type="text/css" href="/styles.css">
<meta charset="utf-8">
+ <link rel="icon" type="image/x-icon" href="/favicon.ico">
+ <link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>
- <h1 style="text-align:center">GPIGEON</h1>
- <form action="/cgi-bin/gpigeon.cgi" method="POST">
- Password : <input type="password" name="password">
- <input type="submit" value="Login">
- </form>
-
- <p><a href="http://git.les-miquelots.net/gpigeon" title="gpigeon download link" alt="gpigeon download link">Source code here.</a> It is similar to <a href="https://hawkpost.co/">hawkpost.co</a>.</p>
+ <h1>GPIGEON - Login</h1>
+ <form action="/cgi-bin/gpigeon.cgi" method="POST">
+ <table id="loginbox">
+ <tbody>
+ <tr>
+ <td>Password :</td>
+ <td><input type="password" name="password"></td>
+ </tr>
+ <tr id="authbtn">
+ <td></td>
+ <td><input type="submit" value="S'authentifier"></td>
+ </tr>
+ </tbody>
+ </table>
+ </form>
+ <p><a href="http://git.les-miquelots.net/gpigeon" title="gpigeon download link">Source code here.</a> It is similar to <a href="https://hawkpost.co/">hawkpost.co</a>.</p>
</body>
</html>
diff --git a/link-tmpl-template.cgi b/link-tmpl-template.cgi
index d781252..c060131 100644
--- a/link-tmpl-template.cgi
+++ b/link-tmpl-template.cgi
@@ -1,6 +1,24 @@
#! /usr/bin/perl -wT
my $linkuser = q{link_user};
my $linkfilename = q{link_filename};
+# link-tmpl.cgi : self-destructing message form to send yourself GPG
+# encrypted messages. Part of gpigeon.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+# Copyright (c) 2020-2021, Miquel Lionel <lionel@les-miquelots.net>
+
use warnings;
use strict;
use GPG;
@@ -43,9 +61,9 @@ else {
if ($HAS_MAILSERVER){
use Mail::Sendmail;
- my %mail = ( To => "$mymailaddr"
- From => "$mailsender"
- Subject => '.'
+ my %mail = ( To => "$mymailaddr",
+ From => "$mailsender",
+ Subject => '.',
Message => "$enc_msg\n"
);
sendmail(%mail) or die $Mail::Sendmail::error;
diff --git a/nginx-example.conf b/nginx-example.conf
index 97e5027..f3d9252 100644
--- a/nginx-example.conf
+++ b/nginx-example.conf
@@ -30,5 +30,11 @@ server {
fastcgi_pass unix:/run/fcgiwrap.sock;
include /etc/nginx/fastcgi_params;
}
+
+ add_header Strict-Transport-Security "max-age=63072000; preload";
+ add_header Content-Security-Policy "default-src 'self'";
+ add_header X-Frame-Options DENY;
+ add_header Access-Control-Allow-Origin https://$server_name;
+ add_header Vary Origin; # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin#cors_and_caching
}
diff --git a/styles.css b/styles.css
index a83cd47..7f8770d 100644
--- a/styles.css
+++ b/styles.css
@@ -1,51 +1,158 @@
html{
- background-color:skyblue
-}
+ background-color:#87CEEB
+}
-th{
- padding:10px;
- font-size:110%;
-}
+body{
+ font-family:sans-serif;
+ width:80%;
+ margin:auto;
+ font-size:12pt;
+}
-td{
- text-align:center;
+h1, #msgbelow{
+ text-align:center;
+}
+
+
+#linkstable tr th{
+ padding:10px;
+ font-size:110%;
+ margin:0;
+}
+
+#linkstable td{
+ text-align:center;
padding: 5px ;
-}
+}
-input{
+#linkstable input{
padding:10px;
margin:5px;
margin-top:10px;
}
-table{
+#linkstable table{
margin-top:10px;
border: 1px solid black;
}
-th,tr,td{
+#linkstable td{
border:1px solid black;
}
-
-body{
- font-family:sans-serif;
- width:80%;
- margin:auto;
- font-size:12pt;
-}
#msg{
- border: 1px solid black;
- resize:vertical;
- width:50%;
+ display:block;
+ margin-left:auto;
+ margin-right:auto;
+ border: 1px solid black;
+ overflow: -moz-scrollbars-none;
+ resize:vertical;
+ width:50%;
+ -ms-overflow-style:none;
+}
+
+
+#msg::-webkit-scrollbar {
+ width: 0 !important
+}
+
+#success {
+ color:green;
+}
+
+#failure {
+ color:red;
+}
+
+#loginbox {
+ border:none;
+ margin-right:auto;
+ margin-left:auto
+}
+
+#loginbox input {
+ width:100%;
+ padding: 5px;
+ line-height:25px;
+
+}
+
+#loginbox td {
+ text-align:right;
+ border:none;
+}
+
+#loginbox tr {
+ border:none;
+}
+
+#authbtn td {
+ text-align:center;
+}
+
+#authbtn input {
+ width:100px;
+}
+
+#mailfied {
+ padding: 10px
+}
+
+#refreshbtn, #deletelinkbtn, #deleteallbtn,
+#logoutbtn, #genlinkbtn, #sendbtn {
+ border-radius:0
+ border:3px outset silver;
+ padding:15px;
+ margin:5px;
+}
+
+#mailfield {
+ padding: 10px;
}
@media screen and (max-width: 740px) {
- body { font-size:0.8em; }
- #msg{width:100%;}
- th, td{ padding:3px; }
- input {
- padding:4px;
- margin: 2px;
+ body {
+ font-size:0.8em;
+ }
+
+ #linkstable th,td{
+ padding:3px;
+ }
+
+ #linkstable input{
+ padding:4px;
+ margin:2px;
+ margin-top:10px;
+ }
+
+ #loginbox input{
+ padding: 2px;
+ line-height:15px;
+ }
+
+ #mailfield{
+ padding: 3px;
+ }
+
+ #msg {
+ width:50%;
+ margin:0;
+ }
+
+ #msgbelow {
+ text-align:left;
+ }
+
+ #refreshbtn, #deletelinkbtn, #deleteallbtn,
+ #logoutbtn, #genlinkbtn, #sendbtn {
+ padding: 8px
+ }
+
+ #genlinkbtn{
+ display:block
+ }
+
+ #sendbtn {
+ display:inline
}
}