Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions db/migrate.sh
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#!/bin/bash
#!/bin/bash -x
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps change set -oeu pipefail to set -oeux pipefail?


# Create database and roles before running this script, see README for how.
#
# Before Use: Set the neccessary database credentials in ~/.pgpass on your
# management user, not on the user running this application.
#
# database.example.com:5432:*:username:password
# database.example.com:5432:pass:password_owner_role:password
#
# Export the following environment variables (e.g. in ~/.bash_profile):
#
Expand Down
11 changes: 6 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
module github.com/advania/pass
module github.com/Gunni/pass

go 1.12
go 1.22

require (
github.com/golang/gddo v0.0.0-20190419222130-af0f2af80721
github.com/google/go-cmp v0.3.0 // indirect
github.com/lib/pq v1.1.1
github.com/golang/gddo v0.0.0-20210115222349-20d68f94ee1f
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is only one caller that uses this library, to parse HTTP Accept headers. It is also responsible for everything in go.sum going bloated.

github.com/lib/pq v1.10.9
)

require github.com/google/go-cmp v0.3.0 // indirect
56 changes: 52 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,6 +1,54 @@
github.com/golang/gddo v0.0.0-20190419222130-af0f2af80721 h1:KRMr9A3qfbVM7iV/WcLY/rL5LICqwMHLhwRXKu99fXw=
github.com/golang/gddo v0.0.0-20190419222130-af0f2af80721/go.mod h1:xEhNfoBDX1hzLm2Nf80qUvZ2sVwoMZ8d6IE2SrsQfh4=
cloud.google.com/go v0.16.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/bradfitz/gomemcache v0.0.0-20170208213004-1952afaa557d/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fsnotify/fsnotify v1.4.3-0.20170329110642-4da3e2cfbabc/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/garyburd/redigo v1.1.1-0.20170914051019-70e1b1943d4f/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
github.com/go-stack/stack v1.6.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/golang/gddo v0.0.0-20210115222349-20d68f94ee1f h1:16RtHeWGkJMc80Etb8RPCcKevXGldr57+LOyZt8zOlg=
github.com/golang/gddo v0.0.0-20210115222349-20d68f94ee1f/go.mod h1:ijRvpgDJDI262hYq/IQVYgf8hd8IHUs93Ol0kvMBAx4=
github.com/golang/lint v0.0.0-20170918230701-e5d664eb928e/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.1.1-0.20171103154506-982329095285/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4=
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/gregjones/httpcache v0.0.0-20170920190843-316c5e0ff04e/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/hashicorp/hcl v0.0.0-20170914154624-68e816d1c783/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w=
github.com/inconshreveable/log15 v0.0.0-20170622235902-74a0988b5f80/go.mod h1:cOaXtrgN4ScfRrD9Bre7U1thNq5RtJ8ZoP4iXVGRj6o=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/magiconair/properties v1.7.4-0.20170902060319-8d7837e64d3c/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mattn/go-colorable v0.0.10-0.20170816031813-ad5389df28cd/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-isatty v0.0.2/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mitchellh/mapstructure v0.0.0-20170523030023-d0303fe80992/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/pelletier/go-toml v1.0.1-0.20170904195809-1d6b12b7cb29/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/spf13/afero v0.0.0-20170901052352-ee1bd8ee15a1/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.1.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg=
github.com/spf13/jwalterweatherman v0.0.0-20170901151539-12bd96e66386/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.1-0.20170901120850-7aff26db30c1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/viper v1.0.0/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/oauth2 v0.0.0-20170912212905-13449ad91cb2/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20170517211232-f52d1811a629/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/time v0.0.0-20170424234030-8be79e1e0910/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
google.golang.org/api v0.0.0-20170921000349-586095a6e407/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20170918111702-1e559d0a00ee/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/grpc v1.2.1-0.20170921194603-d4b75ebd4f9f/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
103 changes: 47 additions & 56 deletions pass.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import (
"strings"
"time"

"github.com/advania/pass/helpers"
"github.com/Gunni/pass/helpers"

"github.com/lib/pq"
)
Expand All @@ -30,6 +30,7 @@ type passConfiguration struct {
File string
Key string
}
ContentSecurityPolicyOverride string
HSTS struct {
MaxAge int
IncludeSubDomains bool
Expand Down Expand Up @@ -84,7 +85,7 @@ var contentSecurityPolicyHTML = strings.Join([]string{
"form-action 'self';",
"frame-ancestors 'none';",
"block-all-mixed-content;",
"sandbox allow-scripts allow-forms allow-same-origin;",
"sandbox allow-scripts allow-forms allow-popups allow-same-origin;",
"require-sri-for script style;",
"base-uri 'none';",
}, " ")
Expand All @@ -98,27 +99,6 @@ var contentSecurityPolicyJSON = strings.Join([]string{
"base-uri 'none';",
}, " ")

var featurePolicy = strings.Join([]string{
"accelerometer 'none';",
"ambient-light-sensor 'none';",
"autoplay 'none';",
"camera 'none';",
"encrypted-media 'none';",
"fullscreen 'none';",
"geolocation 'none';",
"gyroscope 'none';",
"magnetometer 'none';",
"microphone 'none';",
"midi 'none';",
"payment 'none';",
"picture-in-picture 'none';",
"speaker 'none';",
"sync-xhr 'none';",
"sync-script 'none';",
"usb 'none';",
"vr 'none';",
}, " ")

// generateSecurityHeaders generates the http securityHeaders to be outputted
// as http headers before every request
func (p *Pass) generateSecurityHeaders() {
Expand All @@ -133,7 +113,6 @@ func (p *Pass) generateSecurityHeaders() {
}

p.sv.securityHeaders["Access-Control-Allow-Origin"] = p.GetURL()
p.sv.securityHeaders["Feature-Policy"] = featurePolicy
p.sv.securityHeaders["Referrer-Policy"] = "no-referrer"
p.sv.securityHeaders["X-Content-Type-Options"] = "nosniff"
p.sv.securityHeaders["X-Frame-Options"] = "deny"
Expand Down Expand Up @@ -373,11 +352,16 @@ func (p *Pass) OutputHeaders(rw http.ResponseWriter, r *http.Request) {
rw.Header().Set(key, value)
}

// More restrictive CSP for json requests
if helpers.HTTPAcceptCheck("application/json", r.Header) {
rw.Header().Set("Content-Security-Policy", contentSecurityPolicyJSON)
if p.sv.cfg.ContentSecurityPolicyOverride == "" {
// More restrictive CSP for json requests
if helpers.HTTPAcceptCheck("application/json", r.Header) {
rw.Header().Set("Content-Security-Policy", contentSecurityPolicyJSON)
} else {
rw.Header().Set("Content-Security-Policy", contentSecurityPolicyHTML)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We got two policies, one for JSON and another for HTML, yet only one uniformally applied override? How about we use only one for the default as well?

}
} else {
rw.Header().Set("Content-Security-Policy", contentSecurityPolicyHTML)
// Allow config to override the CSP
rw.Header().Set("Content-Security-Policy", p.sv.cfg.ContentSecurityPolicyOverride)
}
}

Expand Down Expand Up @@ -524,34 +508,37 @@ func onBeforeRequest(rv *requestVariables) {

func handler(p *Pass, rv *requestVariables) {
if rv.r.Method == http.MethodGet {
switch rv.path[0] {
case "favicon.ico":
p.serveStatic(rv, "static/favicon.ico", "image/x-icon")
return
case "css":
p.serveStatic(rv, "static/css.css", "text/css")
return
case "js":
p.serveStatic(rv, "static/js.js", "application/javascript")
return
case "logo":
p.serveStatic(rv, "static/logo_header.png", "image/png")
return
case "robots.txt":
rv.w.Header().Set("Content-Type", "text/plain")
rv.w.Header().Set("Cache-Control", "max-age=2592000") // 30 days
rv.w.Write([]byte("User-agent: *\nDisallow: /"))
return
case "ping":
rv.w.Header().Set("Cache-Control", "max-age=0")
// Takes ~42 seconds if db is unresponsive, use it to check for it using client side js
// https://github.com/lib/pq/issues/620
// returns HTTP 500 if server can be instantly detected as being down
if err := rv.sv.db.ping(); err != nil {
log.Printf("db.Ping() returned %v\n", err)
rv.w.WriteHeader(http.StatusInternalServerError)
if len(rv.path) == 1 {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reduce indentation.

if len(rv.path) != 1 {
	return
}

And move this and the switch into a new helper function.

// All the below paths are length 1, prevent handling /logo/asdf as if /logo was used
switch rv.path[0] {
case "favicon.ico":
p.serveStatic(rv, "static/favicon.ico", "image/x-icon")
return
case "css":
p.serveStatic(rv, "static/css.css", "text/css")
return
case "js":
p.serveStatic(rv, "static/js.js", "application/javascript")
return
case "logo":
p.serveStatic(rv, "static/logo_header.png", "image/png")
return
case "robots.txt":
rv.w.Header().Set("Content-Type", "text/plain")
rv.w.Header().Set("Cache-Control", "max-age=2592000") // 30 days
rv.w.Write([]byte("User-agent: *\nDisallow: /"))
return
case "ping":
rv.w.Header().Set("Cache-Control", "max-age=0")
// Takes ~42 seconds if db is unresponsive, use it to check for it using client side js
// https://github.com/lib/pq/issues/620
// returns HTTP 500 if server can be instantly detected as being down
if err := rv.sv.db.ping(); err != nil {
log.Printf("db.Ping() returned %v\n", err)
rv.w.WriteHeader(http.StatusInternalServerError)
}
return
}
return
}
}

Expand Down Expand Up @@ -652,7 +639,7 @@ func loadConfig(configFileName string) (cfg passConfiguration, err error) {
}

if len(cfg.Secret) < 64 {
return cfg, fmt.Errorf("Site secret shorter than 64 characters, please make it at least 64 characters")
return cfg, fmt.Errorf("%s 'Secret' shorter than 64 characters, please make it at least 64 characters", configFileName)
}

return cfg, nil
Expand Down Expand Up @@ -784,6 +771,10 @@ func Main(pass *Pass) {
fmt.Printf("Main program: %s\n", mainApp)
fmt.Printf("Wrapped by: %s\n", wrapper)

if sv.cfg.ContentSecurityPolicyOverride != "" {
fmt.Printf("NOTE: Content-Security-Policy override applied for all requests: %s\n", sv.cfg.ContentSecurityPolicyOverride)
}

// goroutine that runs forever checking the state of the database connection
// This can not run in the normal process flow because of a bug in the pq
// module, it is not possible to cancel a query with a timeout
Expand Down
63 changes: 33 additions & 30 deletions pass.json.template
Original file line number Diff line number Diff line change
@@ -1,32 +1,35 @@
{
"Certificate": {
"File": "your.crt",
"Key": "your.key"
},
"HSTS": {
"MaxAge": 63072000,
"IncludeSubDomains": false,
"Preload": false
},
"Hostname": "pass.example.com",
"ListenAddress": "[::1]:4443",
"PDOString": "host=pass.example.com. port=5432 dbname=passwords user=password_frontend",
"Secret": "a good 64+ character site secret",
"PasswordLength": {
"Min": 6,
"Max": 10000
},
"TemplatePath": "templates",
"Title": "Advania Pass",
"TrustedProxies": [],
"TrustedProxyIPHeader": "",
"Addons": {
"email": {
"Server": "relay.example.com:smtp",
"Sender": {
"Address": "test@example.com",
"Name": "Example"
}
}
}
"Addons": {
"email": {
"Sender": {
"Address": "todo@example.com",
"Name": "Pass"
},
"Server": "todo.example.com"
}
},
"ContentSecurityPolicyOverride": "",
"Certificate": {
"File": "cert.crt",
"Key": "cert.key"
},
"HSTS": {
"MaxAge": 9000001,
"IncludeSubdomains": false,
"Preload": false
},
"Hostname": "pass.example.com",
"ListenAddress": "[::]:4443",
"PDOString": "postgres://password_frontend@localhost/passwords?sslmode=disable",
"Secret": "example: dd if=/dev/random bs=128 count=1 | base64 -w0 ; echo",
"PasswordLength": {
"Min": 20,
"Max": 1024
},
"MinEntryLength": 2048,
"SecretDays": 7,
"Title": "Pass",
"TemplatePath": "templates",
"TrustedProxies": [],
"TrustedProxyIPHeader": ""
}
4 changes: 2 additions & 2 deletions pass/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import (
"net/http"
textTemplate "text/template"

"github.com/advania/pass"
"github.com/advania/pass/senders"
"github.com/Gunni/pass"
"github.com/Gunni/pass/senders"
)

func main() {
Expand Down
4 changes: 2 additions & 2 deletions senders/sender_email.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import (
textTemplate "text/template"
"time"

"github.com/advania/pass"
"github.com/advania/pass/helpers"
"github.com/Gunni/pass"
"github.com/Gunni/pass/helpers"
)

// EmailConfig contains the config required for SendEmail
Expand Down
2 changes: 1 addition & 1 deletion templates/get/post.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ <h2>Password</h2>
<h2>I have the password, now what?</h2>

<p>
Add it to your <a href="https://keepassxc.org/">password manager</a>!
Add it to your <a target="_blank" href="https://keepassxc.org/">password manager</a>!
Or memorize it... because once you leave this page, you will
not be able to retrieve the password from here again!
</p>
Expand Down