diff options
-rw-r--r-- | CHANGES.md | 40 | ||||
-rw-r--r-- | lang/de.lang | 1 | ||||
-rw-r--r-- | lib/JWebmail/Controller/Webmail.pm | 15 | ||||
-rw-r--r-- | lib/JWebmail/Model/ReadMails/MockJSON.pm | 7 | ||||
-rw-r--r-- | lib/JWebmail/Model/ReadMails/Role.pm | 2 | ||||
-rw-r--r-- | lib/JWebmail/Plugin/Helper.pm | 9 | ||||
-rw-r--r-- | public/style2.css | 5 | ||||
-rw-r--r-- | templates/webmail/login.html.ep | 26 | ||||
-rw-r--r-- | templates/webmail/readmail.html.ep | 2 | ||||
-rw-r--r-- | templates/webmail/writemail.html.ep | 3 |
10 files changed, 79 insertions, 31 deletions
@@ -113,13 +113,6 @@ Current v1.1.0 - [ ] QMailAuthuser - [x] repurpose status column in displayheader - [x] currently just renamed to 'Multipart' -- [x] advance ini config plugin - - [x] allow non-leaf nodes to be arrays - - [ ] allow quotes - - [ ] allow continuation over multiple lines - - [ ] warn about overrides - - [ ] add template support, maybe - - [ ] switch to TOML or a provided format, as INI is too basic - [x] refactor ReadMails into a role - [x] made languages in about clickable - [x] make loading auth data from session easier @@ -128,16 +121,15 @@ Current v1.1.0 - [x] merge read and raw (with content type) - how does one extract the body functionality? (One does not.) - [x] refactor templates to make use of link_to -- [x] improve html styling (especially for mobile) +- [ ] improve html styling (especially for mobile) - [x] about - [x] displayheaders - [x] nocation - [x] readmail - [x] writemail -- [ ] improve i18n - - [ ] add localization of dates and time - - [x] refactor I18N plugin to allow independent translate provider - - [x] extend matcher dynamic with a role + - [x] mobile optimize + - [ ] cleanup css + - [ ] improve styling of read- and writemail - [ ] fix tests - [ ] moving mails to other folders - [ ] creating new folders @@ -154,9 +146,24 @@ Current v1.1.0 - [ ] add exception types - [x] added exception for QMailAuthuser - [ ] extract version for Makefile.PL from Application -- [ ] add config validation -- [ ] read and write s3d only once per request ($c->on('finish')) -- [ ] compute h-mac on the client side +- [ ] add basic telemetry (goatcounter?) +- [ ] make mime_render return a mojo bytes object + +- [ ] advance ini config plugin + - [x] allow non-leaf nodes to be arrays + - [ ] allow quotes + - [ ] allow continuation over multiple lines + - [ ] warn about overrides + - [ ] add template support, maybe + - [ ] switch to TOML or a provided format, as INI is too basic + - [ ] add config validation +- [ ] improve i18n + - [ ] add localization of dates and time + - [x] refactor I18N plugin to allow independent translate provider + - [x] extend matcher dynamic with a role +- [x] compute hmac on the client side + - [x] better handling on form + - [ ] better random numbers Future ------ @@ -185,9 +192,7 @@ Future - [ ] better pagination - [ ] merge with partial templates, maybe - [ ] click on sender to answer -- [ ] mobile optimize - [ ] download mail and attachments -- [ ] cleanup css - [ ] allow multiple attachments - [ ] add mails to Sent folder - [ ] smtp send model, maybe @@ -197,3 +202,4 @@ Future - [ ] think about forgot password feature - [ ] address book support - [ ] add links on email addresses in header : click = add into address book +- [ ] read and write s3d only once per request ($c->on('finish')) diff --git a/lang/de.lang b/lang/de.lang index 7aaf598..c508854 100644 --- a/lang/de.lang +++ b/lang/de.lang @@ -36,6 +36,7 @@ last = letzte first = erste previous = vorherige sender = gesendet von +back = zurück # Mailboxen Queue = Warteschlange diff --git a/lib/JWebmail/Controller/Webmail.pm b/lib/JWebmail/Controller/Webmail.pm index ee4a532..bdd7176 100644 --- a/lib/JWebmail/Controller/Webmail.pm +++ b/lib/JWebmail/Controller/Webmail.pm @@ -31,7 +31,7 @@ sub auth { my $self = shift; my $user = $self->session(S_USER); - my $pw = $self->session_passwd; + my ($pw, $ch) = $self->session_passwd; unless ($user && $pw) { $self->flash(message => $self->l('no_session')); @@ -40,9 +40,7 @@ sub auth { return 0; } - my $authConf = {user => $user, password => $pw}; - $authConf->{challenge} = $self->app->secrets->[0] if $self->config->{session}{secure} eq 'cram'; - $self->stash(ST_AUTH() => $self->users->Auth($authConf)); + $self->stash(ST_AUTH() => $self->users->Auth(user => $user, password => $pw, challenge => $ch)); return 1; } @@ -67,10 +65,16 @@ sub _time :prototype(&$$) { sub login { my $self = shift; + my $uses_cram = $self->config->{session}{secure} eq 'cram'; + my $v = $self->validation; my $user = $v->required('userid')->size(4, 50)->param; my $passwd = $v->required('password')->size(4, 50)->like(qr/^.+$/)->param; # no new-lines + my $challenge; + if ($uses_cram) { + $challenge = $v->required('challenge')->size(4, 50)->param; # no new-lines + } if ($v->has_error) { $self->render(status => 400); @@ -78,11 +82,12 @@ sub login { } my $auth = $self->users->Auth(user => $user, password => $passwd); + $auth->{challenge} = $challenge if $uses_cram; my $valid = _time { $self->users->verify_user($auth) } $self, 'verify user'; if ($valid) { $self->session(S_USER() => $user); - $self->session_passwd($passwd); + $self->session_passwd($passwd, $challenge); $self->res->code(303); $self->redirect_to('displayheaders'); diff --git a/lib/JWebmail/Model/ReadMails/MockJSON.pm b/lib/JWebmail/Model/ReadMails/MockJSON.pm index 7decb7d..345573c 100644 --- a/lib/JWebmail/Model/ReadMails/MockJSON.pm +++ b/lib/JWebmail/Model/ReadMails/MockJSON.pm @@ -6,8 +6,9 @@ use utf8; use List::Util 'sum'; -use Mojo::JSON qw(decode_json); +use Mojo::JSON 'decode_json'; +use Digest::HMAC_MD5 'hmac_md5_hex'; use Role::Tiny::With; use namespace::clean; @@ -51,6 +52,10 @@ sub verify_user { my $self = shift; my $auth = shift; + if ($auth->{challenge}) { + my $res = hmac_md5_hex($auth->{challenge}, VALID_PW); + return $auth->{user} eq VALID_USER && $auth->{password} eq $res; + } return $auth->{user} eq VALID_USER && $auth->{password} eq VALID_PW; } diff --git a/lib/JWebmail/Model/ReadMails/Role.pm b/lib/JWebmail/Model/ReadMails/Role.pm index d6472a1..466e3b0 100644 --- a/lib/JWebmail/Model/ReadMails/Role.pm +++ b/lib/JWebmail/Model/ReadMails/Role.pm @@ -20,7 +20,7 @@ sub Auth { state $AuthCheck = { user => {defined => 1, required => 1}, password => {defined => 1, required => 1}, - challenge => {defined => 1}, + challenge => {}, }; my $self = @_ == 1 ? $_[0] : {@_}; diff --git a/lib/JWebmail/Plugin/Helper.pm b/lib/JWebmail/Plugin/Helper.pm index cd72bfa..5edb4af 100644 --- a/lib/JWebmail/Plugin/Helper.pm +++ b/lib/JWebmail/Plugin/Helper.pm @@ -3,6 +3,7 @@ package JWebmail::Plugin::Helper; use Mojo::Base Mojolicious::Plugin; use List::Util qw(all min max); +use Carp 'carp'; use POSIX qw(floor round log ceil); use Mojo::Util qw(encode decode b64_encode b64_decode xml_escape); @@ -156,7 +157,7 @@ sub _rand_data { } sub session_passwd { - my ($c, $passwd) = @_; + my ($c, $passwd, $challenge) = @_; my $secAlg = $c->config->{session}{secure}; die "you need to install Digest::HMAC_MD5 for cram to work" @@ -165,7 +166,7 @@ sub session_passwd { if (defined $passwd) { # set if ($secAlg eq 'cram') { - $c->session(S_PASSWD() => $passwd ? b64_encode(hmac_md5($passwd, $c->app->secrets->[0]), '') : ''); + $c->session(S_PASSWD() => $passwd, challenge => $challenge); } elsif ($secAlg eq 's3d') { unless ($passwd) { @@ -187,8 +188,8 @@ sub session_passwd { } else { # get if ($secAlg eq 'cram') { - wantarray or warn "you forgot the challenge"; - return ($c->app->secrets->[0], $c->session(S_PASSWD)); + wantarray or carp "you forgot the challenge"; + return ($c->session('challenge'), $c->session(S_PASSWD)); } elsif ($secAlg eq 's3d') { my $pw = b64_decode($c->s3d(S_PASSWD) || ''); diff --git a/public/style2.css b/public/style2.css index 664771a..81841e2 100644 --- a/public/style2.css +++ b/public/style2.css @@ -49,6 +49,11 @@ footer { padding: 0 1rem; } +.jwm-mail-header { + background-color: var(--jwm-color-front); + padding: 1rem; +} + .jwm-mail-body { width: 80%; margin: 0rem auto; diff --git a/templates/webmail/login.html.ep b/templates/webmail/login.html.ep index 3e224a8..0b7b080 100644 --- a/templates/webmail/login.html.ep +++ b/templates/webmail/login.html.ep @@ -1,5 +1,7 @@ % layout 'mainlayout'; +% my $uses_cram = config->{session}{secure} eq 'cram'; + <div id=login class="jwm-base"> <h1> @@ -22,14 +24,36 @@ %= label_for password => ucfirst l 'passwd' %= password_field 'password' => (required => '') </div> +% if ($uses_cram) { + %= hidden_field challenge => rand +% } <div class="pure-controls"> - %= submit_button l('login') => (class => 'pure-button pure-button-primary') + %= submit_button l('login') => (class => 'pure-button pure-button-primary') => (name => 'submit_button') => $uses_cram ? (disabled => '') : () </div> </fieldset> % end </div> +% if ($uses_cram) { +<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js" + integrity="sha512-E8QSvWZ0eCLGk4km3hxSsNmGWbLtSCSUcewDQPQWZF6pEU8GlT8a5fF32wOl1i8ftdMhssTrF/OhyGWwonTcXA==" + crossorigin="anonymous" referrerpolicy="no-referrer"></script> +<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/hmac-md5.min.js" + integrity="sha512-gy8JaBxTrtIxNLe1FfMAXey61VjQk3Af4EyY/EpVfmWPH16iCgdRZMHEFgKIyxMrarlc6+rDf6WneGL4SWqnpg==" + crossorigin="anonymous" referrerpolicy="no-referrer"></script> + +<script> + document.login1.submit_button.disabled = false; + + document.forms.login1.addEventListener("formdata", (form_data_evt) => { + const form_data = form_data_evt.formData; + const res = CryptoJS.HmacMD5(form_data.get("challenge"), form_data.get("password")) + form_data.set("password", res) + }); +</script> +% } + %= javascript begin if (!document.login1.userid.value) { document.login1.userid.focus(); diff --git a/templates/webmail/readmail.html.ep b/templates/webmail/readmail.html.ep index f39dd0e..5bad9f3 100644 --- a/templates/webmail/readmail.html.ep +++ b/templates/webmail/readmail.html.ep @@ -12,7 +12,7 @@ <h1>Read Mail</h1> - <dl> + <dl class="jwm-mail-header"> <dt> <%= uc l 'subject' %> </dt> <dd> <%= $msg->{head}{subject} %> </dd> diff --git a/templates/webmail/writemail.html.ep b/templates/webmail/writemail.html.ep index 6342927..9d148c1 100644 --- a/templates/webmail/writemail.html.ep +++ b/templates/webmail/writemail.html.ep @@ -27,7 +27,8 @@ %= email_field 'back_to' %= label_for txt => ucfirst l 'content' - %= text_area body => (cols => 80) => (rows => 24) => (name => 'txt') + %# text_area body => (cols => 80) => (rows => 24) => (name => 'txt') + %= text_area body => (style => 'width: 100%') => (rows => 24) => (name => 'txt') %= label_for attach => ucfirst l 'attach file' %= file_field 'attach' |