Sensitive cookie without HttpOnly

This commit is contained in:
edvraa
2021-04-25 23:05:49 +03:00
committed by Owen Mansel-Chan
parent 191a4c1101
commit cbaad2efb9
14 changed files with 1133 additions and 0 deletions

View File

@@ -0,0 +1,165 @@
import go
/**
* A simplistic points-to alternative: given a struct creation and a field name, get the values that field can be assigned.
*
* Assumptions:
* - we don't reassign the variable that the creation is stored in
* - we always access the creation through the same variable it is initially assigned to
*
* This should cover most typical patterns...
*/
DataFlow::Node getValueForFieldWrite(StructLit sl, string field) {
exists(Write w, DataFlow::Node base, Field f, DataFlow::Node rhs |
f.getName() = field and
w.writesField(base, f, rhs) and
result = rhs and
(
sl = base.asExpr()
or
exists(VariableName vn |
vn = base.asExpr() and
exists(DataFlow::Node creation |
DataFlow::localFlow(creation, base) and
creation.asExpr() = sl and
base.asExpr() = vn
)
)
)
)
}
/**
* Tracks struct creation without `HttpOnly` to `SetCookie`.
*/
class HttpOnlyCookieTrackingConfiguration extends TaintTracking::Configuration {
HttpOnlyCookieTrackingConfiguration() { this = "HttpOnlyCookieTrackingConfiguration" }
override predicate isSource(DataFlow::Node source) {
exists(StructLit sl |
source.asExpr() = sl and
sl.getType().hasQualifiedName("net/http", "Cookie") and
(
not exists(DataFlow::Node rhs | rhs = getValueForFieldWrite(sl, "HttpOnly"))
or
exists(DataFlow::Node rhs |
rhs = getValueForFieldWrite(sl, "HttpOnly") and
exists(DataFlow::Node valSrc |
DataFlow::localFlow(valSrc, rhs) and
valSrc.asExpr().getBoolValue() = false
)
)
)
)
}
override predicate isSink(DataFlow::Node sink) { sink instanceof SetCookieSink }
}
/**
* A cookie passed the second parameter to `SetCookie`.
*/
class SetCookieSink extends DataFlow::Node {
SetCookieSink() {
exists(CallExpr c |
c.getTarget().hasQualifiedName("net/http", "SetCookie") and
this.asExpr() = c.getArgument(1)
)
}
}
/**
* Holds if the expression or its value has a sensitive name
*/
predicate isAuthVariable(Expr expr) {
exists(string val |
(
val = expr.getStringValue() or
val = expr.(Name).getTarget().getName()
) and
val.regexpMatch("(?i).*(session|login|token|user|auth|credential).*") and
not val.regexpMatch("(?i).*(xsrf|csrf|forgery).*")
)
}
/**
* Tracks if a variable with a sensitive name is used as a cookie name.
*/
class AuthCookieNameConfiguration extends TaintTracking::Configuration {
AuthCookieNameConfiguration() { this = "AuthCookieNameConfiguration" }
override predicate isSource(DataFlow::Node source) {
exists(StructLit sl |
source.asExpr() = sl and
sl.getType().hasQualifiedName("net/http", "Cookie") and
exists(DataFlow::Node rhs |
rhs = getValueForFieldWrite(sl, "Name") and
exists(DataFlow::Node valSrc |
DataFlow::localFlow(valSrc, rhs) and
isAuthVariable(valSrc.asExpr())
)
)
)
}
override predicate isSink(DataFlow::Node sink) { sink instanceof SetCookieSink }
}
/**
* Tracks from gorilla cookie store creation to session save.
*/
class CookieStoreSaveTrackingConfiguration extends DataFlow::Configuration {
CookieStoreSaveTrackingConfiguration() { this = "CookieStoreSaveTrackingConfiguration" }
override predicate isSource(DataFlow::Node source) {
exists(CallExpr c |
source.asExpr() = c and
c.getTarget().hasQualifiedName("github.com/gorilla/sessions", "NewCookieStore")
)
}
override predicate isSink(DataFlow::Node sink) {
exists(CallExpr c |
sink.asExpr() = c.getCalleeExpr().(SelectorExpr).getBase() and
c.getTarget().getQualifiedName() = "github.com/gorilla/sessions.Session.Save"
)
}
override predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(Function f, DataFlow::CallNode cn | cn = f.getACall() |
f.getQualifiedName() = "github.com/gorilla/sessions.CookieStore.Get" and
pred = cn.getReceiver() and
succ = cn.getResult(0)
)
}
}
/**
* Tracks session options to session save.
*/
class SessionOptionsTrackingConfiguration extends TaintTracking::Configuration {
SessionOptionsTrackingConfiguration() { this = "SessionOptionsTrackingConfiguration" }
override predicate isSource(DataFlow::Node source) {
exists(StructLit sl |
sl.getType().hasQualifiedName("github.com/gorilla/sessions", "Options") and
source.asExpr() = sl
)
}
override predicate isSink(DataFlow::Node sink) {
exists(CallExpr c |
sink.asExpr() = c.getCalleeExpr().(SelectorExpr).getBase() and
c.getTarget().getQualifiedName() = "github.com/gorilla/sessions.Session.Save"
)
}
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(Field f, DataFlow::Write w, DataFlow::Node base |
f.getQualifiedName() = "github.com/gorilla/sessions.Session.Options" and
w.writesField(base, f, _) and
pred = w.getRhs() and
succ = base
)
}
}

View File

@@ -0,0 +1,42 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
Cookies without <code>HttpOnly</code> attribute are accessible to JavaScript running in the same origin. In case of
Cross-Site Scripting (XSS) vulnerability the cookie can be stolen by malicious script.
</p>
</overview>
<recommendation>
<p>
Protect sensitive cookies, such as related to authentication, by setting <code>HttpOnly</code> to <code>true</code> to make
them not accessible to JavaScript.
</p>
</recommendation>
<example>
<p>
In the following example the default <code>HttpOnly</code> value is <code>false</code>.
</p>
<sample src="CookieWithoutHttpOnlyBad.go" />
<p>
In the example below <code>HttpOnly</code> is set to <code>true</code>.
</p>
<sample src="CookieWithoutHttpOnlyGood.go" />
</example>
<references>
<li><a href="https://golang.org/pkg/net/http/#Cookie">type Cookie,</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie">Set-Cookie</a> Header,</li>
</references>
</qhelp>

View File

@@ -0,0 +1,63 @@
/**
* @name 'HttpOnly' attribute is not set to true
* @description Omitting the 'HttpOnly' attribute for security sensitive data allows
* malicious JavaScript to steal it in case of XSS vulnerability. Always set
* 'HttpOnly' to 'true' to authentication related cookie to make it
* not accessible by JavaScript.
* @kind problem
* @problem.severity warning
* @precision high
* @id go/cookie-httponly-not-set
* @tags security
* external/cwe/cwe-1004
*/
import go
import AuthCookie
from Expr expr
where
exists(SetCookieSink sink, DataFlow::Node source |
exists(HttpOnlyCookieTrackingConfiguration httpOnlyCfg | httpOnlyCfg.hasFlow(source, sink)) and
exists(AuthCookieNameConfiguration cookieNameCfg | cookieNameCfg.hasFlow(source, sink)) and
sink.asExpr() = expr
)
or
exists(CallExpr c |
c.getTarget().getQualifiedName() = "github.com/gin-gonic/gin.Context.SetCookie" and
c.getArgument(6) = expr and
exists(DataFlow::Node valSrc, DataFlow::Node httpOnlyArg |
DataFlow::localFlow(valSrc, httpOnlyArg) and
httpOnlyArg.asExpr() = c.getArgument(6) and
valSrc.asExpr().getBoolValue() = false
) and
exists(DataFlow::Node nameSrc, DataFlow::Node nameArg |
DataFlow::localFlow(nameSrc, nameArg) and
nameArg.asExpr() = c.getArgument(0) and
isAuthVariable(nameSrc.asExpr())
)
)
or
exists(DataFlow::Node sessionSave |
sessionSave.asExpr() = expr and
exists(CookieStoreSaveTrackingConfiguration cfg | cfg.hasFlow(_, sessionSave)) and
(
not exists(SessionOptionsTrackingConfiguration cfg | cfg.hasFlow(_, sessionSave))
or
exists(SessionOptionsTrackingConfiguration cfg, DataFlow::Node options |
cfg.hasFlow(options, sessionSave) and
(
not exists(DataFlow::Node rhs | rhs = getValueForFieldWrite(options.asExpr(), "HttpOnly"))
or
exists(DataFlow::Node rhs |
rhs = getValueForFieldWrite(options.asExpr(), "HttpOnly") and
exists(DataFlow::Node valSrc |
DataFlow::localFlow(valSrc, rhs) and
valSrc.asExpr().getBoolValue() = false
)
)
)
)
)
)
select expr, "Cookie attribute 'HttpOnly' is not set to true."

View File

@@ -0,0 +1,17 @@
package main
import (
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
}
http.SetCookie(w, &c)
}
func main() {
http.HandleFunc("/", handler)
}

View File

@@ -0,0 +1,18 @@
package main
import (
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
HttpOnly: true,
}
http.SetCookie(w, &c)
}
func main() {
http.HandleFunc("/", handler)
}

View File

@@ -0,0 +1,11 @@
| CookieWithoutHttpOnly.go:14:20:14:21 | &... | Cookie attribute 'HttpOnly' is not set to true. |
| CookieWithoutHttpOnly.go:23:20:23:21 | &... | Cookie attribute 'HttpOnly' is not set to true. |
| CookieWithoutHttpOnly.go:50:20:50:21 | &... | Cookie attribute 'HttpOnly' is not set to true. |
| CookieWithoutHttpOnly.go:60:20:60:21 | &... | Cookie attribute 'HttpOnly' is not set to true. |
| CookieWithoutHttpOnly.go:90:20:90:21 | &... | Cookie attribute 'HttpOnly' is not set to true. |
| CookieWithoutHttpOnly.go:109:20:109:21 | &... | Cookie attribute 'HttpOnly' is not set to true. |
| CookieWithoutHttpOnly.go:119:20:119:21 | &... | Cookie attribute 'HttpOnly' is not set to true. |
| CookieWithoutHttpOnly.go:128:2:128:8 | session | Cookie attribute 'HttpOnly' is not set to true. |
| CookieWithoutHttpOnly.go:141:2:141:8 | session | Cookie attribute 'HttpOnly' is not set to true. |
| CookieWithoutHttpOnly.go:152:2:152:8 | session | Cookie attribute 'HttpOnly' is not set to true. |
| CookieWithoutHttpOnly.go:189:75:189:79 | false | Cookie attribute 'HttpOnly' is not set to true. |

View File

@@ -0,0 +1,194 @@
package main
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/gorilla/sessions"
)
func handler1(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
}
http.SetCookie(w, &c) // BAD: HttpOnly set to false by default
}
func handler2(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
HttpOnly: false,
}
http.SetCookie(w, &c) // BAD: HttpOnly explicitly set to false
}
func handler3(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
HttpOnly: true,
}
http.SetCookie(w, &c) // GOOD: HttpOnly explicitly set to true
}
func handler4(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
}
c.HttpOnly = true
http.SetCookie(w, &c) // GOOD: HttpOnly explicitly set to true
}
func handler5(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "session",
Value: "secret",
}
c.HttpOnly = false
http.SetCookie(w, &c) // BAD: HttpOnly explicitly set to false
}
func handler6(w http.ResponseWriter, r *http.Request) {
val := false
c := http.Cookie{
Name: "session",
Value: "secret",
HttpOnly: val,
}
http.SetCookie(w, &c) // BAD: HttpOnly explicitly set to false
}
func handler7(w http.ResponseWriter, r *http.Request) {
val := true
c := http.Cookie{
Name: "session",
Value: "secret",
HttpOnly: val,
}
http.SetCookie(w, &c) // GOOD: HttpOnly explicitly set to true
}
func handler8(w http.ResponseWriter, r *http.Request) {
val := true
c := http.Cookie{
Name: "session",
Value: "secret",
}
c.HttpOnly = val
http.SetCookie(w, &c) // GOOD: HttpOnly explicitly set to true
}
func handler9(w http.ResponseWriter, r *http.Request) {
val := false
c := http.Cookie{
Name: "session",
Value: "secret",
}
c.HttpOnly = val
http.SetCookie(w, &c) // BAD: HttpOnly explicitly set to false
}
func handler10(w http.ResponseWriter, r *http.Request) {
c := http.Cookie{
Name: "consent",
Value: "1",
}
c.HttpOnly = false
http.SetCookie(w, &c) // GOOD: Name is not auth related
}
func handler11(w http.ResponseWriter, r *http.Request) {
name := "session"
c := http.Cookie{
Name: name,
Value: "secret",
}
c.HttpOnly = false
http.SetCookie(w, &c) // BAD: auth related name
}
func handler12(w http.ResponseWriter, r *http.Request) {
session := "login_name"
c := http.Cookie{
Name: session,
Value: "secret",
}
c.HttpOnly = false
http.SetCookie(w, &c) // BAD: auth related name
}
var store = sessions.NewCookieStore([]byte("aa"))
func handler13(w http.ResponseWriter, r *http.Request) {
session, _ := store.Get(r, "session-name")
session.Values["foo"] = "secret"
session.Save(r, w) // BAD: Default options are set (false)
}
func handler14(w http.ResponseWriter, r *http.Request) {
httpOnly := false
session, _ := store.Get(r, "session-name")
session.Values["foo"] = "secret"
session.Options = &sessions.Options{
MaxAge: -1,
HttpOnly: httpOnly,
}
session.Save(r, w) // BAD: Explicitly set to false
}
func handler15(w http.ResponseWriter, r *http.Request) {
session, _ := store.Get(r, "session-name")
session.Values["foo"] = "secret"
session.Options = &sessions.Options{
MaxAge: -1,
}
session.Save(r, w) // BAD: default (false) is used
}
func handler16(w http.ResponseWriter, r *http.Request) {
httpOnly := true
session, _ := store.Get(r, "session-name")
session.Values["foo"] = "secret"
session.Options = &sessions.Options{
MaxAge: -1,
HttpOnly: httpOnly,
}
session.Save(r, w) // GOOD: value is true
}
func handler17(w http.ResponseWriter, r *http.Request, httpOnly bool) {
session, _ := store.Get(r, "session-name")
session.Values["foo"] = "secret"
session.Options = &sessions.Options{
MaxAge: -1,
HttpOnly: httpOnly,
}
session.Save(r, w) // GOOD: value is unknown
}
func main() {
router := gin.Default()
router.GET("/cookie", func(c *gin.Context) {
_, err := c.Cookie("session")
if err != nil {
c.SetCookie("session", "test", 3600, "/", "localhost", false, false) // BAD: httpOnly set to false
}
})
router.Run()
}

View File

@@ -0,0 +1 @@
experimental/CWE-1004/CookieWithoutHttpOnly.ql

View File

@@ -0,0 +1,8 @@
module example.com/m
go 1.14
require (
github.com/gin-gonic/gin v1.6.2
github.com/gorilla/sessions v1.2.1
)

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014 Manuel Martínez-Almeida
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,12 @@
// Code generated by depstubber. DO NOT EDIT.
// This is a simple stub for github.com/gin-gonic/gin/binding, strictly for use in testing.
// See the LICENSE file for information about the licensing of the original library.
// Source: github.com/gin-gonic/gin/binding (exports: ; functions: YAML)
// Package binding is a stub of github.com/gin-gonic/gin/binding, generated by depstubber.
package binding
import ()
var YAML interface{} = nil

View File

@@ -0,0 +1,500 @@
// Code generated by depstubber. DO NOT EDIT.
// This is a simple stub for github.com/gin-gonic/gin, strictly for use in testing.
// See the LICENSE file for information about the licensing of the original library.
// Source: github.com/gin-gonic/gin (exports: Context; functions: )
// Package gin is a stub of github.com/gin-gonic/gin, generated by depstubber.
package gin
import (
bufio "bufio"
io "io"
multipart "mime/multipart"
net "net"
http "net/http"
sync "sync"
time "time"
)
type Context struct {
Request *http.Request
Writer ResponseWriter
Params Params
KeysMutex *sync.RWMutex
Keys map[string]interface{}
Errors interface{}
Accepted []string
}
func (_ *Context) Abort() {}
func (_ *Context) AbortWithError(_ int, _ interface {
Error() string
}) *Error {
return nil
}
func (_ *Context) AbortWithStatus(_ int) {}
func (_ *Context) AbortWithStatusJSON(_ int, _ interface{}) {}
func (_ *Context) AsciiJSON(_ int, _ interface{}) {}
func (_ *Context) Bind(_ interface{}) interface {
Error() string
} {
return nil
}
func (_ *Context) BindHeader(_ interface{}) interface {
Error() string
} {
return nil
}
func (_ *Context) BindJSON(_ interface{}) interface {
Error() string
} {
return nil
}
func (_ *Context) BindQuery(_ interface{}) interface {
Error() string
} {
return nil
}
func (_ *Context) BindUri(_ interface{}) interface {
Error() string
} {
return nil
}
func (_ *Context) BindWith(_ interface{}, _ interface{}) interface {
Error() string
} {
return nil
}
func (_ *Context) BindXML(_ interface{}) interface {
Error() string
} {
return nil
}
func (_ *Context) BindYAML(_ interface{}) interface {
Error() string
} {
return nil
}
func (_ *Context) ClientIP() string {
return ""
}
func (_ *Context) ContentType() string {
return ""
}
func (_ *Context) Cookie(_ string) (string, interface {
Error() string
}) {
return "", nil
}
func (_ *Context) Copy() *Context {
return nil
}
func (_ *Context) Data(_ int, _ string, _ []uint8) {}
func (_ *Context) DataFromReader(_ int, _ int64, _ string, _ io.Reader, _ map[string]string) {}
func (_ *Context) Deadline() (time.Time, bool) {
return time.Time{}, false
}
func (_ *Context) DefaultPostForm(_ string, _ string) string {
return ""
}
func (_ *Context) DefaultQuery(_ string, _ string) string {
return ""
}
func (_ *Context) Done() <-chan struct{} {
return nil
}
func (_ *Context) Err() interface {
Error() string
} {
return nil
}
func (_ *Context) Error(_ interface {
Error() string
}) *Error {
return nil
}
func (_ *Context) File(_ string) {}
func (_ *Context) FileAttachment(_ string, _ string) {}
func (_ *Context) FileFromFS(_ string, _ http.FileSystem) {}
func (_ *Context) FormFile(_ string) (*multipart.FileHeader, interface {
Error() string
}) {
return nil, nil
}
func (_ *Context) FullPath() string {
return ""
}
func (_ *Context) Get(_ string) (interface{}, bool) {
return nil, false
}
func (_ *Context) GetBool(_ string) bool {
return false
}
func (_ *Context) GetDuration(_ string) time.Duration {
return 0
}
func (_ *Context) GetFloat64(_ string) float64 {
return 0
}
func (_ *Context) GetHeader(_ string) string {
return ""
}
func (_ *Context) GetInt(_ string) int {
return 0
}
func (_ *Context) GetInt64(_ string) int64 {
return 0
}
func (_ *Context) GetPostForm(_ string) (string, bool) {
return "", false
}
func (_ *Context) GetPostFormArray(_ string) ([]string, bool) {
return nil, false
}
func (_ *Context) GetPostFormMap(_ string) (map[string]string, bool) {
return nil, false
}
func (_ *Context) GetQuery(_ string) (string, bool) {
return "", false
}
func (_ *Context) GetQueryArray(_ string) ([]string, bool) {
return nil, false
}
func (_ *Context) GetQueryMap(_ string) (map[string]string, bool) {
return nil, false
}
func (_ *Context) GetRawData() ([]uint8, interface {
Error() string
}) {
return nil, nil
}
func (_ *Context) GetString(_ string) string {
return ""
}
func (_ *Context) GetStringMap(_ string) map[string]interface{} {
return nil
}
func (_ *Context) GetStringMapString(_ string) map[string]string {
return nil
}
func (_ *Context) GetStringMapStringSlice(_ string) map[string][]string {
return nil
}
func (_ *Context) GetStringSlice(_ string) []string {
return nil
}
func (_ *Context) GetTime(_ string) time.Time {
return time.Time{}
}
func (_ *Context) HTML(_ int, _ string, _ interface{}) {}
func (_ *Context) Handler() HandlerFunc {
return nil
}
func (_ *Context) HandlerName() string {
return ""
}
func (_ *Context) HandlerNames() []string {
return nil
}
func (_ *Context) Header(_ string, _ string) {}
func (_ *Context) IndentedJSON(_ int, _ interface{}) {}
func (_ *Context) IsAborted() bool {
return false
}
func (_ *Context) IsWebsocket() bool {
return false
}
func (_ *Context) JSON(_ int, _ interface{}) {}
func (_ *Context) JSONP(_ int, _ interface{}) {}
func (_ *Context) MultipartForm() (*multipart.Form, interface {
Error() string
}) {
return nil, nil
}
func (_ *Context) MustBindWith(_ interface{}, _ interface{}) interface {
Error() string
} {
return nil
}
func (_ *Context) MustGet(_ string) interface{} {
return nil
}
func (_ *Context) Negotiate(_ int, _ Negotiate) {}
func (_ *Context) NegotiateFormat(_ ...string) string {
return ""
}
func (_ *Context) Next() {}
func (_ *Context) Param(_ string) string {
return ""
}
func (_ *Context) PostForm(_ string) string {
return ""
}
func (_ *Context) PostFormArray(_ string) []string {
return nil
}
func (_ *Context) PostFormMap(_ string) map[string]string {
return nil
}
func (_ *Context) ProtoBuf(_ int, _ interface{}) {}
func (_ *Context) PureJSON(_ int, _ interface{}) {}
func (_ *Context) Query(_ string) string {
return ""
}
func (_ *Context) QueryArray(_ string) []string {
return nil
}
func (_ *Context) QueryMap(_ string) map[string]string {
return nil
}
func (_ *Context) Redirect(_ int, _ string) {}
func (_ *Context) Render(_ int, _ interface{}) {}
func (_ *Context) SSEvent(_ string, _ interface{}) {}
func (_ *Context) SaveUploadedFile(_ *multipart.FileHeader, _ string) interface {
Error() string
} {
return nil
}
func (_ *Context) SecureJSON(_ int, _ interface{}) {}
func (_ *Context) Set(_ string, _ interface{}) {}
func (_ *Context) SetAccepted(_ ...string) {}
func (_ *Context) SetCookie(_ string, _ string, _ int, _ string, _ string, _ bool, _ bool) {}
func (_ *Context) SetSameSite(_ http.SameSite) {}
func (_ *Context) ShouldBind(_ interface{}) interface {
Error() string
} {
return nil
}
func (_ *Context) ShouldBindBodyWith(_ interface{}, _ interface{}) interface {
Error() string
} {
return nil
}
func (_ *Context) ShouldBindHeader(_ interface{}) interface {
Error() string
} {
return nil
}
func (_ *Context) ShouldBindJSON(_ interface{}) interface {
Error() string
} {
return nil
}
func (_ *Context) ShouldBindQuery(_ interface{}) interface {
Error() string
} {
return nil
}
func (_ *Context) ShouldBindUri(_ interface{}) interface {
Error() string
} {
return nil
}
func (_ *Context) ShouldBindWith(_ interface{}, _ interface{}) interface {
Error() string
} {
return nil
}
func (_ *Context) ShouldBindXML(_ interface{}) interface {
Error() string
} {
return nil
}
func (_ *Context) ShouldBindYAML(_ interface{}) interface {
Error() string
} {
return nil
}
func (_ *Context) Status(_ int) {}
func (_ *Context) Stream(_ func(io.Writer) bool) bool {
return false
}
func (_ *Context) String(_ int, _ string, _ ...interface{}) {}
func (_ *Context) Value(_ interface{}) interface{} {
return nil
}
func (_ *Context) XML(_ int, _ interface{}) {}
func (_ *Context) YAML(_ int, _ interface{}) {}
type Error struct {
Err interface {
Error() string
}
Type ErrorType
Meta interface{}
}
func (_ Error) Error() string {
return ""
}
func (_ *Error) IsType(_ ErrorType) bool {
return false
}
func (_ *Error) JSON() interface{} {
return nil
}
func (_ *Error) MarshalJSON() ([]uint8, interface {
Error() string
}) {
return nil, nil
}
func (_ *Error) SetMeta(_ interface{}) *Error {
return nil
}
func (_ *Error) SetType(_ ErrorType) *Error {
return nil
}
type ErrorType uint64
type HandlerFunc func(*Context)
type Negotiate struct {
Offered []string
HTMLName string
HTMLData interface{}
JSONData interface{}
XMLData interface{}
YAMLData interface{}
Data interface{}
}
type Param struct {
Key string
Value string
}
type Params []Param
func (_ Params) ByName(_ string) string {
return ""
}
func (_ Params) Get(_ string) (string, bool) {
return "", false
}
type ResponseWriter interface {
CloseNotify() <-chan bool
Flush()
Header() http.Header
Hijack() (net.Conn, *bufio.ReadWriter, interface {
Error() string
})
Pusher() http.Pusher
Size() int
Status() int
Write(_ []uint8) (int, interface {
Error() string
})
WriteHeader(_ int)
WriteHeaderNow()
WriteString(_ string) (int, interface {
Error() string
})
Written() bool
}

View File

@@ -0,0 +1,75 @@
// Code generated by depstubber. DO NOT EDIT.
// This is a simple stub for github.com/gorilla/sessions, strictly for use in testing.
// See the LICENSE file for information about the licensing of the original library.
// Source: github.com/gorilla/sessions (exports: CookieStore; functions: NewCookieStore)
// Package sessions is a stub of github.com/gorilla/sessions, generated by depstubber.
package sessions
import (
http "net/http"
)
type CookieStore struct {
Codecs []interface{}
Options *Options
}
func (_ *CookieStore) Get(_ *http.Request, _ string) (*Session, error) {
return nil, nil
}
func (_ *CookieStore) MaxAge(_ int) {}
func (_ *CookieStore) New(_ *http.Request, _ string) (*Session, error) {
return nil, nil
}
func (_ *CookieStore) Save(_ *http.Request, _ http.ResponseWriter, _ *Session) error {
return nil
}
func NewCookieStore(_ ...[]byte) *CookieStore {
return nil
}
type Options struct {
Path string
Domain string
MaxAge int
Secure bool
HttpOnly bool
SameSite http.SameSite
}
type Session struct {
ID string
Values map[interface{}]interface{}
Options *Options
IsNew bool
}
func (_ *Session) AddFlash(_ interface{}, _ ...string) {}
func (_ *Session) Flashes(_ ...string) []interface{} {
return nil
}
func (_ *Session) Name() string {
return ""
}
func (_ *Session) Save(_ *http.Request, _ http.ResponseWriter) error {
return nil
}
func (_ *Session) Store() Store {
return nil
}
type Store interface {
Get(_ *http.Request, _ string) (*Session, error)
New(_ *http.Request, _ string) (*Session, error)
Save(_ *http.Request, _ http.ResponseWriter, _ *Session) error
}

View File

@@ -0,0 +1,6 @@
# github.com/gin-gonic/gin v1.6.2
## explicit
github.com/gin-gonic/gin
# github.com/gorilla/sessions v1.2.1
## explicit
github.com/gorilla/sessions