Mercurial > gemma
annotate pkg/controllers/pwreset.go @ 1010:8f23ec811afb
Fixed and harmonized wording in importer queue a bit.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Tue, 23 Oct 2018 10:14:41 +0200 |
parents | e2860eff5d03 |
children | a244b18cb916 |
rev | line source |
---|---|
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
1 package controllers |
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
2 |
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
3 import ( |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
4 "bytes" |
501
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
5 "context" |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
6 "database/sql" |
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
7 "encoding/hex" |
535
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
8 "errors" |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
9 "log" |
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
10 "net/http" |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
11 "os/exec" |
511
b96b1b258cfa
Use already declared password length in reset password.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
501
diff
changeset
|
12 "strconv" |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
13 "strings" |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
14 "text/template" |
304
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
15 "time" |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
16 |
339
33b59c848771
Factored out some miscellaneous code into own package.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
332
diff
changeset
|
17 "github.com/gorilla/mux" |
33b59c848771
Factored out some miscellaneous code into own package.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
332
diff
changeset
|
18 |
414
c1047fd04a3a
Moved project specific Go packages to new pkg folder.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
408
diff
changeset
|
19 "gemma.intevation.de/gemma/pkg/auth" |
c1047fd04a3a
Moved project specific Go packages to new pkg folder.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
408
diff
changeset
|
20 "gemma.intevation.de/gemma/pkg/common" |
1001
e2860eff5d03
Wait in PW reset clean up code until config is loaded.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
562
diff
changeset
|
21 "gemma.intevation.de/gemma/pkg/config" |
414
c1047fd04a3a
Moved project specific Go packages to new pkg folder.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
408
diff
changeset
|
22 "gemma.intevation.de/gemma/pkg/misc" |
442
fc37e7072022
Moved some models used in controllers to to model package because they may be needed elsewhere (e.g. GeoServer config).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
438
diff
changeset
|
23 "gemma.intevation.de/gemma/pkg/models" |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
24 ) |
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
25 |
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
26 const ( |
478
3af7ca761f6a
Purge password reset role
Tom Gottfried <tom@intevation.de>
parents:
442
diff
changeset
|
27 insertRequestSQL = `INSERT INTO sys_admin.password_reset_requests |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
28 (hash, username) VALUES ($1, $2)` |
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
29 |
478
3af7ca761f6a
Purge password reset role
Tom Gottfried <tom@intevation.de>
parents:
442
diff
changeset
|
30 countRequestsSQL = `SELECT count(*) FROM sys_admin.password_reset_requests` |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
31 |
478
3af7ca761f6a
Purge password reset role
Tom Gottfried <tom@intevation.de>
parents:
442
diff
changeset
|
32 countRequestsUserSQL = `SELECT count(*) FROM sys_admin.password_reset_requests |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
33 WHERE username = $1` |
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
34 |
478
3af7ca761f6a
Purge password reset role
Tom Gottfried <tom@intevation.de>
parents:
442
diff
changeset
|
35 deleteRequestSQL = `DELETE FROM sys_admin.password_reset_requests |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
36 WHERE hash = $1` |
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
37 |
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
38 findRequestSQL = `SELECT lu.email_address, lu.username |
478
3af7ca761f6a
Purge password reset role
Tom Gottfried <tom@intevation.de>
parents:
442
diff
changeset
|
39 FROM sys_admin.password_reset_requests prr |
3af7ca761f6a
Purge password reset role
Tom Gottfried <tom@intevation.de>
parents:
442
diff
changeset
|
40 JOIN users.list_users lu on prr.username = lu.username |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
41 WHERE prr.hash = $1` |
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
42 |
478
3af7ca761f6a
Purge password reset role
Tom Gottfried <tom@intevation.de>
parents:
442
diff
changeset
|
43 cleanupRequestsSQL = `DELETE FROM sys_admin.password_reset_requests |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
44 WHERE issued < $1` |
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
45 |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
46 userExistsSQL = `SELECT email_address |
478
3af7ca761f6a
Purge password reset role
Tom Gottfried <tom@intevation.de>
parents:
442
diff
changeset
|
47 FROM users.list_users WHERE username = $1` |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
48 |
478
3af7ca761f6a
Purge password reset role
Tom Gottfried <tom@intevation.de>
parents:
442
diff
changeset
|
49 updatePasswordSQL = `UPDATE users.list_users |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
50 SET pw = $1 WHERE username = $2` |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
51 ) |
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
52 |
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
53 const ( |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
54 hashLength = 16 |
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
55 passwordLength = 20 |
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
56 passwordResetValid = 12 * time.Hour |
304
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
57 maxPasswordResets = 1000 |
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
58 maxPasswordRequestsPerUser = 5 |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
59 cleanupPause = 15 * time.Minute |
304
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
60 ) |
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
61 |
478
3af7ca761f6a
Purge password reset role
Tom Gottfried <tom@intevation.de>
parents:
442
diff
changeset
|
62 const pwResetRole = "sys_admin" |
438
ffdb507d5b42
Removed db service user. Use an impersonated metamorph user instead.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
414
diff
changeset
|
63 |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
64 var ( |
535
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
65 errTooMuchPasswordResets = errors.New("Too many password resets") |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
66 errTooMuchPasswordResetsPerUser = errors.New("Too many password resets per user") |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
67 errNoSuchUser = errors.New("User does not exist") |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
68 errInvalidUser = errors.New("Invalid user") |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
69 ) |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
70 |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
71 var ( |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
72 passwordResetRequestMailTmpl = template.Must( |
516
9b3db1d7a7eb
proxy: improve texts for password reset mails.
Bernhard Reiter <bernhard@intevation.de>
parents:
511
diff
changeset
|
73 template.New("request").Parse(`You or someone else has requested a password change |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
74 for your account {{ .User }} on |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
75 {{ .HTTPS }}://{{ .Server }} |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
76 |
516
9b3db1d7a7eb
proxy: improve texts for password reset mails.
Bernhard Reiter <bernhard@intevation.de>
parents:
511
diff
changeset
|
77 Please follow this link to have a new password generated and mailed to you: |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
78 |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
79 {{ .HTTPS }}://{{ .Server }}/api/users/passwordreset/{{ .Hash }} |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
80 |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
81 The link is only valid for 12 hours. |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
82 |
516
9b3db1d7a7eb
proxy: improve texts for password reset mails.
Bernhard Reiter <bernhard@intevation.de>
parents:
511
diff
changeset
|
83 If you did not initiate this password reset or do not want to reset the |
9b3db1d7a7eb
proxy: improve texts for password reset mails.
Bernhard Reiter <bernhard@intevation.de>
parents:
511
diff
changeset
|
84 password, just ignore this email. |
9b3db1d7a7eb
proxy: improve texts for password reset mails.
Bernhard Reiter <bernhard@intevation.de>
parents:
511
diff
changeset
|
85 |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
86 Best regards |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
87 Your service team`)) |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
88 |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
89 passwordResetMailTmpl = template.Must( |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
90 template.New("reset").Parse(`Your password for your account {{ .User }} on |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
91 {{ .HTTPS }}://{{ .Server }} |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
92 |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
93 has been changed to |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
94 {{ .Password }} |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
95 |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
96 Change it as soon as possible. |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
97 |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
98 Best regards |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
99 Your service team`)) |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
100 ) |
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
101 |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
102 func init() { |
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
103 go removeOutdated() |
304
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
104 } |
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
105 |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
106 func removeOutdated() { |
1001
e2860eff5d03
Wait in PW reset clean up code until config is loaded.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
562
diff
changeset
|
107 config.WaitReady() |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
108 for { |
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
109 time.Sleep(cleanupPause) |
501
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
110 err := auth.RunAs( |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
111 pwResetRole, context.Background(), |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
112 func(conn *sql.Conn) error { |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
113 good := time.Now().Add(-passwordResetValid) |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
114 _, err := conn.ExecContext( |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
115 context.Background(), cleanupRequestsSQL, good) |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
116 return err |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
117 }) |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
118 if err != nil { |
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
119 log.Printf("error: %v\n", err) |
304
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
120 } |
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
121 } |
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
122 } |
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
123 |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
124 func requestMessageBody(https, user, hash, server string) string { |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
125 var content = struct { |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
126 User string |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
127 HTTPS string |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
128 Server string |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
129 Hash string |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
130 }{ |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
131 User: user, |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
132 HTTPS: https, |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
133 Server: server, |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
134 Hash: hash, |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
135 } |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
136 var buf bytes.Buffer |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
137 if err := passwordResetRequestMailTmpl.Execute(&buf, &content); err != nil { |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
138 log.Printf("error: %v\n", err) |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
139 } |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
140 return buf.String() |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
141 } |
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
142 |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
143 func changedMessageBody(https, user, password, server string) string { |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
144 var content = struct { |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
145 User string |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
146 HTTPS string |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
147 Server string |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
148 Password string |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
149 }{ |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
150 User: user, |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
151 HTTPS: https, |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
152 Server: server, |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
153 Password: password, |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
154 } |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
155 var buf bytes.Buffer |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
156 if err := passwordResetMailTmpl.Execute(&buf, &content); err != nil { |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
157 log.Printf("error: %v\n", err) |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
158 } |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
159 return buf.String() |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
160 } |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
161 |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
162 func useHTTPS(req *http.Request) string { |
560
66073a476baf
If header "X-Use-Protocol" is set by proxy generate https URLS in password resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
558
diff
changeset
|
163 if req.Header.Get("X-Use-Protocol") == "https" || |
66073a476baf
If header "X-Use-Protocol" is set by proxy generate https URLS in password resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
558
diff
changeset
|
164 req.URL.Scheme == "https" { |
66073a476baf
If header "X-Use-Protocol" is set by proxy generate https URLS in password resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
558
diff
changeset
|
165 return "https" |
66073a476baf
If header "X-Use-Protocol" is set by proxy generate https URLS in password resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
558
diff
changeset
|
166 } |
66073a476baf
If header "X-Use-Protocol" is set by proxy generate https URLS in password resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
558
diff
changeset
|
167 return "http" |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
168 } |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
169 |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
170 func generateHash() string { |
408
ac23905e64b1
Improve WFS proxy a lot. It now generates signed re-writings.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
339
diff
changeset
|
171 return hex.EncodeToString(common.GenerateRandomKey(hashLength)) |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
172 } |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
173 |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
174 func generateNewPassword() string { |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
175 // First try pwgen |
511
b96b1b258cfa
Use already declared password length in reset password.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
501
diff
changeset
|
176 out, err := exec.Command( |
b96b1b258cfa
Use already declared password length in reset password.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
501
diff
changeset
|
177 "pwgen", "-y", strconv.Itoa(passwordLength), "1").Output() |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
178 if err == nil { |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
179 return strings.TrimSpace(string(out)) |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
180 } |
317
5cb18bedb3a9
Simplified internal password generator.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
316
diff
changeset
|
181 // Use internal generator. |
511
b96b1b258cfa
Use already declared password length in reset password.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
501
diff
changeset
|
182 return common.RandomString(passwordLength) |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
183 } |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
184 |
535
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
185 func backgroundRequest(https, host string, user *models.PWResetUser) error { |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
186 |
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
187 if user.User == "" { |
535
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
188 return errInvalidUser |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
189 } |
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
190 |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
191 var hash, email string |
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
192 |
535
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
193 ctx := context.Background() |
521
139214cecc8f
backend: add FIXMEs to password reset.
Bernhard Reiter <bernhard@intevation.de>
parents:
516
diff
changeset
|
194 |
535
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
195 if err := auth.RunAs( |
501
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
196 pwResetRole, ctx, |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
197 func(conn *sql.Conn) error { |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
198 |
501
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
199 var count int64 |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
200 if err := conn.QueryRowContext( |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
201 ctx, countRequestsSQL).Scan(&count); err != nil { |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
202 return err |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
203 } |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
204 |
501
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
205 // Limit total number of password requests. |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
206 if count >= maxPasswordResets { |
535
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
207 return errTooMuchPasswordResets |
501
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
208 } |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
209 |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
210 err := conn.QueryRowContext(ctx, userExistsSQL, user.User).Scan(&email) |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
211 |
501
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
212 switch { |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
213 case err == sql.ErrNoRows: |
535
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
214 return errNoSuchUser |
501
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
215 case err != nil: |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
216 return err |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
217 } |
304
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
218 |
501
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
219 if err := conn.QueryRowContext( |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
220 ctx, countRequestsUserSQL, user.User).Scan(&count); err != nil { |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
221 return err |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
222 } |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
223 |
501
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
224 // Limit requests per user |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
225 if count >= maxPasswordRequestsPerUser { |
535
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
226 return errTooMuchPasswordResetsPerUser |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
227 } |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
228 |
501
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
229 hash = generateHash() |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
230 _, err = conn.ExecContext(ctx, insertRequestSQL, hash, user.User) |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
231 return err |
535
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
232 }, |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
233 ); err != nil { |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
234 return err |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
235 } |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
236 |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
237 body := requestMessageBody(https, user.User, hash, host) |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
238 |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
239 return misc.SendMail(email, "Password Reset Link", body) |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
240 } |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
241 |
557
009171c1485c
Password reset: Generate right URLs for the server if we are behind a proxy.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
535
diff
changeset
|
242 // host checks if we are behind a proxy and returns the name |
009171c1485c
Password reset: Generate right URLs for the server if we are behind a proxy.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
535
diff
changeset
|
243 // of the up-front server. |
009171c1485c
Password reset: Generate right URLs for the server if we are behind a proxy.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
535
diff
changeset
|
244 func host(req *http.Request) string { |
009171c1485c
Password reset: Generate right URLs for the server if we are behind a proxy.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
535
diff
changeset
|
245 if fwd := req.Header.Get("X-Forwarded-Host"); fwd != "" { |
009171c1485c
Password reset: Generate right URLs for the server if we are behind a proxy.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
535
diff
changeset
|
246 return fwd |
009171c1485c
Password reset: Generate right URLs for the server if we are behind a proxy.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
535
diff
changeset
|
247 } |
009171c1485c
Password reset: Generate right URLs for the server if we are behind a proxy.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
535
diff
changeset
|
248 return req.Host |
009171c1485c
Password reset: Generate right URLs for the server if we are behind a proxy.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
535
diff
changeset
|
249 } |
009171c1485c
Password reset: Generate right URLs for the server if we are behind a proxy.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
535
diff
changeset
|
250 |
535
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
251 func passwordResetRequest( |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
252 input interface{}, |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
253 req *http.Request, |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
254 _ *sql.Conn, |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
255 ) (jr JSONResult, err error) { |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
256 |
535
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
257 // We do the checks and the emailing in background |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
258 // no reduce the risks of timing attacks. |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
259 go func(https, host string, user *models.PWResetUser) { |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
260 if err := backgroundRequest(https, host, user); err != nil { |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
261 log.Printf("error: %v\n", err) |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
262 } |
557
009171c1485c
Password reset: Generate right URLs for the server if we are behind a proxy.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
535
diff
changeset
|
263 }(useHTTPS(req), host(req), input.(*models.PWResetUser)) |
535
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
264 |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
265 // Send a neutral message to avoid being an user oracle. |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
266 const neutralMessage = "If this account exists, a reset link will be mailed." |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
267 |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
268 jr.Result = &struct { |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
269 Message string `json:"message"` |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
270 }{neutralMessage} |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
271 |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
272 return |
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
273 } |
304
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
274 |
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
275 func passwordReset( |
316
423d0f1d8ee0
JSON input is not used when doing a password reset.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
315
diff
changeset
|
276 _ interface{}, |
304
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
277 req *http.Request, |
486
b2dc9c2f69e0
First stab to use the metamorphic db to do all database stuff.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
478
diff
changeset
|
278 _ *sql.Conn, |
304
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
279 ) (jr JSONResult, err error) { |
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
280 |
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
281 hash := mux.Vars(req)["hash"] |
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
282 if _, err = hex.DecodeString(hash); err != nil { |
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
283 err = JSONError{http.StatusBadRequest, "Invalid hash"} |
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
284 return |
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
285 } |
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
286 |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
287 var email, user, password string |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
288 |
501
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
289 ctx := req.Context() |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
290 |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
291 if err = auth.RunAs( |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
292 pwResetRole, ctx, func(conn *sql.Conn) error { |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
293 err := conn.QueryRowContext(ctx, findRequestSQL, hash).Scan(&email, &user) |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
294 switch { |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
295 case err == sql.ErrNoRows: |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
296 return JSONError{http.StatusNotFound, "No such hash"} |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
297 case err != nil: |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
298 return err |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
299 } |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
300 password = generateNewPassword() |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
301 res, err := conn.ExecContext(ctx, updatePasswordSQL, password, user) |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
302 if err != nil { |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
303 return err |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
304 } |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
305 if n, err2 := res.RowsAffected(); err2 == nil && n == 0 { |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
306 return JSONError{http.StatusNotFound, "User not found"} |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
307 } |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
308 _, err = conn.ExecContext(ctx, deleteRequestSQL, hash) |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
309 return err |
501
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
310 }); err == nil { |
557
009171c1485c
Password reset: Generate right URLs for the server if we are behind a proxy.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
535
diff
changeset
|
311 body := changedMessageBody(useHTTPS(req), user, password, host(req)) |
339
33b59c848771
Factored out some miscellaneous code into own package.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
332
diff
changeset
|
312 if err = misc.SendMail(email, "Password Reset Done", body); err == nil { |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
313 jr.Result = &struct { |
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
314 SendTo string `json:"send-to"` |
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
315 }{email} |
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
316 } |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
317 } |
304
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
318 return |
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
319 } |