\n' +
@@ -24,9 +29,9 @@ const wake_on_lan_new_template = '
\n' +
'
';
jQuery(function ($) {
- $.validator.addMethod('mac', function (value, element) {
- return this.optional(element) || /^([0-9A-F]{2}[:]){5}([0-9A-F]{2})$/.test(value);
- }, 'Please enter a valid MAC Address.(uppercase letters and numbers, : only) ex: 00:AB:12:EF:DD:AA');
+ $.validator.addMethod('mac', function (value, element) {
+ return this.optional(element) || /^([0-9A-F]{2}[:]){5}([0-9A-F]{2})$/.test(value);
+ }, 'Please enter a valid MAC Address.(uppercase letters and numbers, : only) ex: 00:AB:12:EF:DD:AA');
});
jQuery.each(["put", "delete"], function (i, method) {
@@ -42,7 +47,8 @@ jQuery.each(["put", "delete"], function (i, method) {
type: method,
dataType: type,
data: data,
- success: callback
+ success: callback,
+ contentType: 'application/json'
});
};
});
@@ -55,7 +61,7 @@ jQuery(function ($) {
jQuery(function ($) {
$('.btn-outline-success').click(function () {
const $this = $(this);
- $.put('/wake_on_lan_host/' + $this.data('mac-address'), function (result) {
+ $.put(base_url + 'wake_on_lan_host/' + $this.data('mac-address'), function (result) {
$this.parents('.info-box').find('.latest-used').text(prettyDateTime(result));
});
});
@@ -76,7 +82,7 @@ jQuery(function ($) {
$remove_client_confirm.click(function () {
const macAddress = $remove_client_confirm.val().replaceAll(":", "-");
- $.delete('/wake_on_lan_host/' + macAddress);
+ $.delete(base_url + 'wake_on_lan_host/' + macAddress);
$('#' + macAddress).remove();
$modal_remove_wake_on_lan_host.modal('hide');
@@ -84,10 +90,18 @@ jQuery(function ($) {
});
jQuery(function ($) {
- $('.latest-used').each(function () {
- const $this = $(this);
- $this.text(prettyDateTime($this.text().trim()));
- });
+ $('.latest-used').each(function () {
+ const $this = $(this);
+ const timeText = $this.text().trim();
+ try {
+ if (timeText != "Unused") {
+ $this.text(prettyDateTime(timeText));
+ }
+ } catch (ex) {
+ console.log(timeText);
+ throw ex;
+ }
+ });
});
jQuery(function ($) {
@@ -109,7 +123,7 @@ jQuery(function ($) {
$.ajax({
cache: false,
method: 'POST',
- url: '/wake_on_lan_host',
+ url: base_url + 'wake_on_lan_host',
dataType: 'json',
contentType: "application/json",
data: JSON.stringify(data),
diff --git a/emailer/smtp.go b/emailer/smtp.go
index 38ac995..d1fdbae 100644
--- a/emailer/smtp.go
+++ b/emailer/smtp.go
@@ -3,9 +3,9 @@ package emailer
import (
"crypto/tls"
"fmt"
- "time"
-
mail "github.com/xhit/go-simple-mail/v2"
+ "strings"
+ "time"
)
type SmtpMail struct {
@@ -14,13 +14,14 @@ type SmtpMail struct {
username string
password string
authType mail.AuthType
+ encryption mail.Encryption
noTLSCheck bool
fromName string
from string
}
func authType(authType string) mail.AuthType {
- switch authType {
+ switch strings.ToUpper(authType) {
case "PLAIN":
return mail.AuthPlain
case "LOGIN":
@@ -30,8 +31,21 @@ func authType(authType string) mail.AuthType {
}
}
-func NewSmtpMail(hostname string, port int, username string, password string, noTLSCheck bool, auth string, fromName, from string) *SmtpMail {
- ans := SmtpMail{hostname: hostname, port: port, username: username, password: password, noTLSCheck: noTLSCheck, fromName: fromName, from: from, authType: authType(auth)}
+func encryptionType(encryptionType string) mail.Encryption {
+ switch strings.ToUpper(encryptionType) {
+ case "SSL":
+ return mail.EncryptionSSL
+ case "SSLTLS":
+ return mail.EncryptionSSLTLS
+ case "TLS":
+ return mail.EncryptionTLS
+ default:
+ return mail.EncryptionSTARTTLS
+ }
+}
+
+func NewSmtpMail(hostname string, port int, username string, password string, noTLSCheck bool, auth string, fromName, from string, encryption string) *SmtpMail {
+ ans := SmtpMail{hostname: hostname, port: port, username: username, password: password, noTLSCheck: noTLSCheck, fromName: fromName, from: from, authType: authType(auth), encryption: encryptionType(encryption)}
return &ans
}
@@ -50,7 +64,7 @@ func (o *SmtpMail) Send(toName string, to string, subject string, content string
server.Authentication = o.authType
server.Username = o.username
server.Password = o.password
- server.Encryption = mail.EncryptionSTARTTLS
+ server.Encryption = o.encryption
server.KeepAlive = false
server.ConnectTimeout = 10 * time.Second
server.SendTimeout = 10 * time.Second
diff --git a/go.mod b/go.mod
index 6cacd1e..dfe3c40 100644
--- a/go.mod
+++ b/go.mod
@@ -19,6 +19,7 @@ require (
github.com/sendgrid/sendgrid-go v3.10.0+incompatible
github.com/skip2/go-qrcode v0.0.0-20191027152451-9434209cb086
github.com/xhit/go-simple-mail/v2 v2.10.0
+ golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e
//golang.zx2c4.com/wireguard v0.0.20200121 // indirect
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20210803171230-4253848d036c
gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
diff --git a/go.sum b/go.sum
index 607f7a1..beffdb5 100644
--- a/go.sum
+++ b/go.sum
@@ -1,11 +1,7 @@
-github.com/GeertJohan/go.incremental v1.0.0 h1:7AH+pY1XUgQE4Y1HcXYaMqAI0m9yrFqo/jt0CW30vsg=
github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0=
-github.com/GeertJohan/go.rice v1.0.0 h1:KkI6O9uMaQU3VEKaj01ulavtF7o1fWT7+pk/4voiMLQ=
-github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0=
github.com/GeertJohan/go.rice v1.0.2 h1:PtRw+Tg3oa3HYwiDBZyvOJ8LdIyf6lAovJJtr7YOAYk=
github.com/GeertJohan/go.rice v1.0.2/go.mod h1:af5vUNlDNkCjOZeSGFgIJxDje9qdjsO6hshx0gTmZt4=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
-github.com/akavel/rsrc v0.8.0 h1:zjWn7ukO9Kc5Q62DOJCcxGpXC18RawVtYAGdz2aLlfw=
github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@@ -19,6 +15,7 @@ github.com/coreos/bbolt v1.3.1-coreos.6.0.20180223184059-4f5275f4ebbf/go.mod h1:
github.com/daaku/go.zipexe v1.0.0 h1:VSOgZtH418pH9L16hC/JrgSNJbbAL26pj7lmD1+CGdY=
github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
@@ -55,7 +52,6 @@ github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/z
github.com/jcelliott/lumber v0.0.0-20160324203708-dd349441af25 h1:EFT6MH3igZK/dIVqgGbTqWVvkZ7wJ5iGN03SVtvvdd8=
github.com/jcelliott/lumber v0.0.0-20160324203708-dd349441af25/go.mod h1:sWkGw/wsaHtRsT9zGQ/WyJCotGWG/Anow/9hsAcBWRw=
github.com/jessevdk/go-flags v0.0.0-20150816100521-1acbbaff2f34/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
-github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/josharian/native v0.0.0-20200817173448-b6b71def0850 h1:uhL5Gw7BINiiPAo24A2sxkcDI0Jt/sqp1v5xQCniEFA=
github.com/josharian/native v0.0.0-20200817173448-b6b71def0850/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
@@ -65,6 +61,7 @@ github.com/jsimonetti/rtnetlink v0.0.0-20201009170750-9c6f07d100c1/go.mod h1:hqo
github.com/jsimonetti/rtnetlink v0.0.0-20201216134343-bde56ed16391/go.mod h1:cR77jAZG3Y3bsb8hF6fHJbFoyFukLFOkQ98S0pQz3xw=
github.com/jsimonetti/rtnetlink v0.0.0-20201220180245-69540ac93943/go.mod h1:z4c53zj6Eex712ROyh8WI0ihysb5j2ROyV42iNogmAs=
github.com/jsimonetti/rtnetlink v0.0.0-20210122163228-8d122574c736/go.mod h1:ZXpIyOK59ZnN7J0BV99cZUPmsqDRZ3eq5X+st7u/oSA=
+github.com/jsimonetti/rtnetlink v0.0.0-20210212075122-66c871082f2b h1:c3NTyLNozICy8B4mlMXemD3z/gXgQzVXZS/HqT+i3do=
github.com/jsimonetti/rtnetlink v0.0.0-20210212075122-66c871082f2b/go.mod h1:8w9Rh8m+aHZIG69YPGGem1i5VzoyRC8nw2kA8B+ik5U=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
@@ -91,6 +88,7 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
+github.com/mdlayher/ethtool v0.0.0-20210210192532-2b88debcdd43 h1:WgyLFv10Ov49JAQI/ZLUkCZ7VJS3r74hwFIGXJsgZlY=
github.com/mdlayher/ethtool v0.0.0-20210210192532-2b88debcdd43/go.mod h1:+t7E0lkKfbBsebllff1xdTmyJt8lH37niI6kwFk9OTo=
github.com/mdlayher/genetlink v1.0.0 h1:OoHN1OdyEIkScEmRgxLEe2M9U8ClMytqA5niynLtfj0=
github.com/mdlayher/genetlink v1.0.0/go.mod h1:0rJ0h4itni50A86M2kHcgS85ttZazNt7a8H2a2cw0Gc=
@@ -104,18 +102,18 @@ github.com/mdlayher/netlink v1.2.2-0.20210123213345-5cc92139ae3e/go.mod h1:bacnN
github.com/mdlayher/netlink v1.3.0/go.mod h1:xK/BssKuwcRXHrtN04UBkwQ6dY9VviGGuriDdoPSWys=
github.com/mdlayher/netlink v1.4.0 h1:n3ARR+Fm0dDv37dj5wSWZXDKcy+U0zwcXS3zKMnSiT0=
github.com/mdlayher/netlink v1.4.0/go.mod h1:dRJi5IABcZpBD2A3D0Mv/AiX8I9uDEu5oGkAVrekmf8=
+github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721 h1:RlZweED6sbSArvlE924+mUcZuXKLBHA35U7LN621Bws=
github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721/go.mod h1:Ickgr2WtCLZ2MDGd4Gr0geeCH5HybhRJbonOgQpvSxc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
-github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E=
-github.com/nkovacs/streamquote v1.0.0 h1:PmVIV08Zlx2lZK5fFZlMZ04eHcDTIFJCv/5/0twVUow=
github.com/nkovacs/streamquote v1.0.0/go.mod h1:BN+NaZ2CmdKqUuTUXUEm9j95B2TRbpOWpxbJYzzgUsc=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
@@ -147,6 +145,7 @@ github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoH
github.com/stretchr/testify v0.0.0-20150929183540-2b15294402a8/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/uber-go/atomic v1.4.0/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g=
github.com/uber/jaeger-client-go v2.19.1-0.20191002155754-0be28c34dabf+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
@@ -230,16 +229,20 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190608022120-eacb66d2a7c3/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.zx2c4.com/wireguard v0.0.0-20210427022245-097af6e1351b h1:XDLXhn7ryprJVo+Lpkiib6CIuXE2031GDwtfEm7vLjI=
golang.zx2c4.com/wireguard v0.0.0-20210427022245-097af6e1351b/go.mod h1:a057zjmoc00UN7gVkaJt2sXVK523kMJcogDTEvPIasg=
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20210803171230-4253848d036c h1:ADNrRDI5NR23/TUCnEmlLZLt4u9DnZ2nwRkPrAcFvto=
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20210803171230-4253848d036c/go.mod h1:+1XihzyZUBJcSc5WO9SwNA7v26puQwOEDwanaxfNXPQ=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
gopkg.in/go-playground/validator.v9 v9.31.0 h1:bmXmP2RSNtFES+bn4uYuHT7iJFJv7Vj+an+ZQdDaD1M=
gopkg.in/go-playground/validator.v9 v9.31.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
diff --git a/handler/routes.go b/handler/routes.go
index 6b85e5b..19512c1 100644
--- a/handler/routes.go
+++ b/handler/routes.go
@@ -51,7 +51,18 @@ func Login(db store.IStore) echo.HandlerFunc {
}
userCorrect := subtle.ConstantTimeCompare([]byte(user.Username), []byte(dbuser.Username)) == 1
- passwordCorrect := subtle.ConstantTimeCompare([]byte(user.Password), []byte(dbuser.Password)) == 1
+
+ var passwordCorrect bool
+ if dbuser.PasswordHash != "" {
+ match, err := util.VerifyHash(dbuser.PasswordHash, user.Password)
+ if err != nil {
+ return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, "Cannot verify password"})
+ }
+ passwordCorrect = match
+ } else {
+ passwordCorrect = subtle.ConstantTimeCompare([]byte(user.Password), []byte(dbuser.Password)) == 1
+ }
+
if userCorrect && passwordCorrect {
// TODO: refresh the token
sess, _ := session.Get("session", c)
diff --git a/main.go b/main.go
index b28dd86..84f1b78 100644
--- a/main.go
+++ b/main.go
@@ -33,6 +33,7 @@ var (
flagSmtpPassword string
flagSmtpAuthType string = "None"
flagSmtpNoTLSCheck bool = false
+ flagSmtpEncryption string = "STARTTLS"
flagSendgridApiKey string
flagEmailFrom string
flagEmailFromName string = "WireGuard UI"
@@ -57,10 +58,11 @@ func init() {
flag.StringVar(&flagBindAddress, "bind-address", util.LookupEnvOrString("BIND_ADDRESS", flagBindAddress), "Address:Port to which the app will be bound.")
flag.StringVar(&flagSmtpHostname, "smtp-hostname", util.LookupEnvOrString("SMTP_HOSTNAME", flagSmtpHostname), "SMTP Hostname")
flag.IntVar(&flagSmtpPort, "smtp-port", util.LookupEnvOrInt("SMTP_PORT", flagSmtpPort), "SMTP Port")
- flag.StringVar(&flagSmtpUsername, "smtp-username", util.LookupEnvOrString("SMTP_USERNAME", flagSmtpUsername), "SMTP Password")
+ flag.StringVar(&flagSmtpUsername, "smtp-username", util.LookupEnvOrString("SMTP_USERNAME", flagSmtpUsername), "SMTP Username")
flag.StringVar(&flagSmtpPassword, "smtp-password", util.LookupEnvOrString("SMTP_PASSWORD", flagSmtpPassword), "SMTP Password")
flag.BoolVar(&flagSmtpNoTLSCheck, "smtp-no-tls-check", util.LookupEnvOrBool("SMTP_NO_TLS_CHECK", flagSmtpNoTLSCheck), "Disable TLS verification for SMTP. This is potentially dangerous.")
- flag.StringVar(&flagSmtpAuthType, "smtp-auth-type", util.LookupEnvOrString("SMTP_AUTH_TYPE", flagSmtpAuthType), "SMTP Auth Type : Plain or None.")
+ flag.StringVar(&flagSmtpEncryption, "smtp-encryption", util.LookupEnvOrString("SMTP_ENCRYPTION", flagSmtpEncryption), "SMTP Encryption : SSL, SSLTLS, TLS or STARTTLS (by default)")
+ flag.StringVar(&flagSmtpAuthType, "smtp-auth-type", util.LookupEnvOrString("SMTP_AUTH_TYPE", flagSmtpAuthType), "SMTP Auth Type : Plain, Login or None.")
flag.StringVar(&flagSendgridApiKey, "sendgrid-api-key", util.LookupEnvOrString("SENDGRID_API_KEY", flagSendgridApiKey), "Your sendgrid api key.")
flag.StringVar(&flagEmailFrom, "email-from", util.LookupEnvOrString("EMAIL_FROM_ADDRESS", flagEmailFrom), "'From' email address.")
flag.StringVar(&flagEmailFromName, "email-from-name", util.LookupEnvOrString("EMAIL_FROM_NAME", flagEmailFromName), "'From' email name.")
@@ -78,6 +80,7 @@ func init() {
util.SmtpPassword = flagSmtpPassword
util.SmtpAuthType = flagSmtpAuthType
util.SmtpNoTLSCheck = flagSmtpNoTLSCheck
+ util.SmtpEncryption = flagSmtpEncryption
util.SendgridApiKey = flagSendgridApiKey
util.EmailFrom = flagEmailFrom
util.EmailFromName = flagEmailFromName
@@ -138,7 +141,7 @@ func main() {
if util.SendgridApiKey != "" {
sendmail = emailer.NewSendgridApiMail(util.SendgridApiKey, util.EmailFromName, util.EmailFrom)
} else {
- sendmail = emailer.NewSmtpMail(util.SmtpHostname, util.SmtpPort, util.SmtpUsername, util.SmtpPassword, util.SmtpNoTLSCheck, util.SmtpAuthType, util.EmailFromName, util.EmailFrom)
+ sendmail = emailer.NewSmtpMail(util.SmtpHostname, util.SmtpPort, util.SmtpUsername, util.SmtpPassword, util.SmtpNoTLSCheck, util.SmtpAuthType, util.EmailFromName, util.EmailFrom, util.SmtpEncryption)
}
app.GET(util.BasePath+"/_health", handler.Health())
diff --git a/model/user.go b/model/user.go
index 24a7e53..711ebd1 100644
--- a/model/user.go
+++ b/model/user.go
@@ -4,4 +4,6 @@ package model
type User struct {
Username string `json:"username"`
Password string `json:"password"`
+ // PasswordHash takes precedence over Password.
+ PasswordHash string `json:"password_hash"`
}
diff --git a/store/jsondb/jsondb.go b/store/jsondb/jsondb.go
index 755145b..285bc19 100644
--- a/store/jsondb/jsondb.go
+++ b/store/jsondb/jsondb.go
@@ -102,7 +102,15 @@ func (o *JsonDB) Init() error {
if _, err := os.Stat(userPath); os.IsNotExist(err) {
user := new(model.User)
user.Username = util.LookupEnvOrString(util.UsernameEnvVar, util.DefaultUsername)
- user.Password = util.LookupEnvOrString(util.PasswordEnvVar, util.DefaultPassword)
+ user.PasswordHash = util.LookupEnvOrString(util.PasswordHashEnvVar, "")
+ if user.PasswordHash == "" {
+ plaintext := util.LookupEnvOrString(util.PasswordEnvVar, util.DefaultPassword)
+ hash, err := util.HashPassword(plaintext)
+ if err != nil {
+ return err
+ }
+ user.PasswordHash = hash
+ }
o.conn.Write("server", "users", user)
}
diff --git a/templates/global_settings.html b/templates/global_settings.html
index 0288306..1c01438 100644
--- a/templates/global_settings.html
+++ b/templates/global_settings.html
@@ -91,9 +91,9 @@ Global Settings
2. DNS Servers
The DNS servers will be set to client config.
3. MTU
-
The MTU will be set to server config. By default it is 1420. You might want
+ The MTU will be set to server and client config. By default it is 1420. You might want
to adjust the MTU size if your connection (e.g PPPoE, 3G, satellite network, etc) has a low MTU.
- Leave blank to omit this setting in the Server config.
+ Leave blank to omit this setting in the configs.
4. Persistent Keepalive
By default, WireGuard peers remain silent while they do not need to communicate,
so peers located behind a NAT and/or firewall may be unreachable from other peers
diff --git a/templates/wake_on_lan_hosts.html b/templates/wake_on_lan_hosts.html
index c949f96..80ba3f6 100644
--- a/templates/wake_on_lan_hosts.html
+++ b/templates/wake_on_lan_hosts.html
@@ -103,7 +103,7 @@
{{ if .LatestUsed }}
- {{ .LatestUsed }}
+ {{ .LatestUsed.Format "2006-01-02T15:04:05Z07:00"}}
{{ else }}
Unused
{{ end }}
diff --git a/util/config.go b/util/config.go
index f5967eb..6a08904 100644
--- a/util/config.go
+++ b/util/config.go
@@ -11,6 +11,7 @@ var (
SmtpUsername string
SmtpPassword string
SmtpNoTLSCheck bool
+ SmtpEncryption string
SmtpAuthType string
SendgridApiKey string
EmailFrom string
@@ -34,6 +35,7 @@ const (
DefaultConfigFilePath = "/etc/wireguard/wg0.conf"
UsernameEnvVar = "WGUI_USERNAME"
PasswordEnvVar = "WGUI_PASSWORD"
+ PasswordHashEnvVar = "WGUI_PASSWORD_HASH"
EndpointAddressEnvVar = "WGUI_ENDPOINT_ADDRESS"
DNSEnvVar = "WGUI_DNS"
MTUEnvVar = "WGUI_MTU"
diff --git a/util/hash.go b/util/hash.go
new file mode 100644
index 0000000..0ee0ec9
--- /dev/null
+++ b/util/hash.go
@@ -0,0 +1,30 @@
+package util
+
+import (
+ "encoding/base64"
+ "fmt"
+ "golang.org/x/crypto/bcrypt"
+)
+
+func HashPassword(plaintext string) (string, error) {
+ bytes, err := bcrypt.GenerateFromPassword([]byte(plaintext), 14)
+ if err != nil {
+ return "", fmt.Errorf("cannot hash password: %w", err)
+ }
+ return base64.StdEncoding.EncodeToString(bytes), nil
+}
+
+func VerifyHash(base64Hash string, plaintext string) (bool, error) {
+ hash, err := base64.StdEncoding.DecodeString(base64Hash)
+ if err != nil {
+ return false, fmt.Errorf("cannot decode base64 hash: %w", err)
+ }
+ err = bcrypt.CompareHashAndPassword(hash, []byte(plaintext))
+ if err == bcrypt.ErrMismatchedHashAndPassword {
+ return false, nil
+ }
+ if err != nil {
+ return false, fmt.Errorf("cannot verify password: %w", err)
+ }
+ return true, nil
+}
diff --git a/util/util.go b/util/util.go
index 9e67f9e..8826ee6 100644
--- a/util/util.go
+++ b/util/util.go
@@ -28,6 +28,11 @@ func BuildClientConfig(client model.Client, server model.Server, setting model.G
if client.UseServerDNS {
clientDNS = fmt.Sprintf("DNS = %s\n", strings.Join(setting.DNSServers, ","))
}
+ clientMTU := ""
+ if setting.MTU > 0 {
+ clientMTU = fmt.Sprintf("MTU = %d\n", setting.MTU)
+ }
+
clientPostUp := ""
if strings.TrimSpace(client.PostUp) != "" {
clientPostUp = fmt.Sprintf("PostUp = %s\n", client.PostUp)
@@ -74,6 +79,7 @@ func BuildClientConfig(client model.Client, server model.Server, setting model.G
clientAddress +
clientPrivateKey +
clientDNS +
+ clientMTU +
forwardMark +
clientPostUp +
clientPostDown +