Skip to content

Commit caf3572

Browse files
committed
Merge pull request akensho#2 from AllenDang/master
Patch from Allen Dang using glog to replace revel's old logging system to keep compatibility with revel V1.
2 parents fa6a992 + 5683216 commit caf3572

File tree

1 file changed

+77
-76
lines changed

1 file changed

+77
-76
lines changed

csrf.go

Lines changed: 77 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -4,103 +4,104 @@
44
package csrf
55

66
import (
7-
"crypto/subtle"
8-
"github.com/robfig/revel"
9-
"net/url"
10-
"regexp"
7+
"crypto/subtle"
8+
"github.com/golang/glog"
9+
"github.com/robfig/revel"
10+
"net/url"
11+
"regexp"
1112
)
1213

1314
const (
14-
cookieName = "csrf_token"
15-
fieldName = "csrf_token"
16-
headerName = "X-CSRF-Token"
15+
cookieName = "csrf_token"
16+
fieldName = "csrf_token"
17+
headerName = "X-CSRF-Token"
1718
)
1819

1920
var (
20-
errNoReferer = "A secure request contained no Referer or its value was malformed."
21-
errBadReferer = "Same-origin policy failure."
22-
errBadToken = "CSRF tokens mismatch."
21+
errNoReferer = "A secure request contained no Referer or its value was malformed."
22+
errBadReferer = "Same-origin policy failure."
23+
errBadToken = "CSRF tokens mismatch."
2324
)
2425

2526
var CSRFFilter = func(c *revel.Controller, fc []revel.Filter) {
26-
r := c.Request.Request
27+
r := c.Request.Request
2728

28-
// OWASP; General Recommendation: Synchronizer Token Pattern.
29-
// CSRF tokens must be associated with the user's current session.
30-
tokenCookie, found := c.Session[cookieName]
31-
realToken := ""
32-
if !found {
33-
realToken = generateNewToken(c)
34-
} else {
35-
realToken = tokenCookie
36-
revel.TRACE.Printf("Session's CSRF token: '%s'", realToken)
37-
if len(realToken) != tokenLength {
38-
// Wrong length; token has either been tampered with, we're migrating
39-
// onto a new algorithm for generating tokens, or a new session has
40-
// been initiated. In any case, a new token is generated and the
41-
// error will be detected later.
42-
revel.TRACE.Printf("Bad CSRF token length: found %d, expected %d",
43-
len(realToken), tokenLength)
44-
realToken = generateNewToken(c)
45-
}
46-
}
29+
// OWASP; General Recommendation: Synchronizer Token Pattern.
30+
// CSRF tokens must be associated with the user's current session.
31+
tokenCookie, found := c.Session[cookieName]
32+
realToken := ""
33+
if !found {
34+
realToken = generateNewToken(c)
35+
} else {
36+
realToken = tokenCookie
37+
glog.Infof("Session's CSRF token: '%s'", realToken)
38+
if len(realToken) != tokenLength {
39+
// Wrong length; token has either been tampered with, we're migrating
40+
// onto a new algorithm for generating tokens, or a new session has
41+
// been initiated. In any case, a new token is generated and the
42+
// error will be detected later.
43+
glog.Infof("Bad CSRF token length: found %d, expected %d",
44+
len(realToken), tokenLength)
45+
realToken = generateNewToken(c)
46+
}
47+
}
4748

48-
c.RenderArgs[fieldName] = realToken
49+
c.RenderArgs[fieldName] = realToken
4950

50-
// See http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Safe_methods
51-
safeMethod, _ := regexp.MatchString("^(GET|HEAD|OPTIONS|TRACE)$", r.Method)
52-
if !safeMethod {
53-
revel.TRACE.Printf("Unsafe %s method...", r.Method)
54-
if r.URL.Scheme == "https" {
55-
// See OWASP; Checking the Referer Header.
56-
referer, err := url.Parse(r.Header.Get("Referer"))
57-
if err != nil || referer.String() == "" {
58-
// Parse error or empty referer.
59-
c.Result = c.Forbidden(errNoReferer)
60-
return
61-
}
62-
// See OWASP; Checking the Origin Header.
63-
if !sameOrigin(referer, r.URL) {
64-
c.Result = c.Forbidden(errBadReferer)
65-
return
66-
}
67-
}
51+
// See http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Safe_methods
52+
safeMethod, _ := regexp.MatchString("^(GET|HEAD|OPTIONS|TRACE)$", r.Method)
53+
if !safeMethod {
54+
glog.Infof("Unsafe %s method...", r.Method)
55+
if r.URL.Scheme == "https" {
56+
// See OWASP; Checking the Referer Header.
57+
referer, err := url.Parse(r.Header.Get("Referer"))
58+
if err != nil || referer.String() == "" {
59+
// Parse error or empty referer.
60+
c.Result = c.Forbidden(errNoReferer)
61+
return
62+
}
63+
// See OWASP; Checking the Origin Header.
64+
if !sameOrigin(referer, r.URL) {
65+
c.Result = c.Forbidden(errBadReferer)
66+
return
67+
}
68+
}
6869

69-
// Accept CSRF token in the custom HTTP header X-CSRF-Token, as well as
70-
// in the form submission itself, for ease of use with popular JavaScript
71-
// toolkits which allow insertion of custom headers into all AJAX
72-
// requests. See http://erlend.oftedal.no/blog/?blogid=118
73-
sentToken := r.Header.Get(headerName)
74-
if sentToken == "" {
75-
sentToken = c.Params.Get(fieldName)
76-
}
77-
revel.TRACE.Printf("CSRF token received: '%s'", sentToken)
70+
// Accept CSRF token in the custom HTTP header X-CSRF-Token, as well as
71+
// in the form submission itself, for ease of use with popular JavaScript
72+
// toolkits which allow insertion of custom headers into all AJAX
73+
// requests. See http://erlend.oftedal.no/blog/?blogid=118
74+
sentToken := r.Header.Get(headerName)
75+
if sentToken == "" {
76+
sentToken = r.PostFormValue(fieldName)
77+
}
78+
glog.Infof("CSRF token received: '%s'", sentToken)
7879

79-
if len(sentToken) != len(realToken) {
80-
c.Result = c.Forbidden(errBadToken)
81-
return
82-
} else {
83-
comparison := subtle.ConstantTimeCompare([]byte(sentToken), []byte(realToken))
84-
if comparison != 1 {
85-
c.Result = c.Forbidden(errBadToken)
86-
return
87-
}
88-
}
89-
}
90-
revel.TRACE.Println("CSRF token successfully checked.")
80+
if len(sentToken) != len(realToken) {
81+
c.Result = c.Forbidden(errBadToken)
82+
return
83+
} else {
84+
comparison := subtle.ConstantTimeCompare([]byte(sentToken), []byte(realToken))
85+
if comparison != 1 {
86+
c.Result = c.Forbidden(errBadToken)
87+
return
88+
}
89+
}
90+
}
91+
glog.Infoln("CSRF token successfully checked.")
9192

92-
fc[0](c, fc[1:])
93+
fc[0](c, fc[1:])
9394
}
9495

9596
// See http://en.wikipedia.org/wiki/Same-origin_policy
9697
func sameOrigin(u1, u2 *url.URL) bool {
97-
return (u1.Scheme == u2.Scheme && u1.Host == u2.Host)
98+
return (u1.Scheme == u2.Scheme && u1.Host == u2.Host)
9899
}
99100

100101
// Generate a new CSRF token.
101102
func generateNewToken(c *revel.Controller) string {
102-
token := generateToken()
103-
revel.TRACE.Printf("Generated new CSRF Token: '%s'", token)
104-
c.Session[cookieName] = token
105-
return token
103+
token := generateToken()
104+
glog.Infof("Generated new CSRF Token: '%s'", token)
105+
c.Session[cookieName] = token
106+
return token
106107
}

0 commit comments

Comments
 (0)