mirror of
https://github.com/syssecfsu/witty.git
synced 2024-12-25 04:02:36 +01:00
add CSRF protection
This commit is contained in:
parent
315759fd52
commit
5052b491f6
12
README.md
12
README.md
@ -43,7 +43,7 @@ Most icons were provided by [fontawesome](https://fontawesome.com/) under this [
|
|||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
1. Install the [go](https://go.dev/) compiler. __Make sure your have go 1.17 or higher.__
|
1. Install the [go](https://go.dev/) compiler. __Make sure you have go 1.17 or higher.__
|
||||||
2. Download the release and unzip it, or clone the repo
|
2. Download the release and unzip it, or clone the repo
|
||||||
|
|
||||||
```git clone https://github.com/syssecfsu/witty.git```
|
```git clone https://github.com/syssecfsu/witty.git```
|
||||||
@ -74,13 +74,17 @@ Most icons were provided by [fontawesome](https://fontawesome.com/) under this [
|
|||||||
|
|
||||||
If so desired, you can disable user authenticate with ```-n/-naked```, (not recommended) for example:
|
If so desired, you can disable user authenticate with ```-n/-naked```, (not recommended) for example:
|
||||||
|
|
||||||
```./witty run -naked htop```
|
```./witty run -naked htop```
|
||||||
|
|
||||||
7. Connect to the server, for example
|
You can also specify the port number WiTTY listens on with ```-p/port```. For example:
|
||||||
|
|
||||||
|
```./witty run -p 9090 ssh 192.168.1.2```
|
||||||
|
|
||||||
|
7. Connect to the server with your browser, using port 8080 or the one specified in step 6, for example
|
||||||
|
|
||||||
```https://<witty_server_ip>:8080```
|
```https://<witty_server_ip>:8080```
|
||||||
|
|
||||||
8. You can also replay the recorded sessions with witty
|
8. You can also replay the recorded sessions with witty. Set your terminal window to 120x36 before using this.
|
||||||
|
|
||||||
```./witty replay -w 500 records/<recorded file>.scr```
|
```./witty replay -w 500 records/<recorded file>.scr```
|
||||||
|
|
||||||
|
@ -28,10 +28,11 @@
|
|||||||
WiTTY: Web-based interactive TTY
|
WiTTY: Web-based interactive TTY
|
||||||
</a>
|
</a>
|
||||||
<div class="btn-toolbar float-end" role="toolbar" aria-label="top buttons">
|
<div class="btn-toolbar float-end" role="toolbar" aria-label="top buttons">
|
||||||
<a class="btn btn-primary btn-sm m-1" href="/new" onClick="setTimeout(function(){refresh(true)}, 1000)"
|
<form action="/new" method="post" target="_blank" onsubmit="setTimeout(function(){refresh(true)}, 1000)">
|
||||||
target="_blank" role="button">
|
{{.csrfField}}
|
||||||
New Session
|
<button class="btn btn-primary btn-sm m-1" type="submit">New Session</button>
|
||||||
</a>
|
</form>
|
||||||
|
|
||||||
<a class="btn btn-primary btn-sm m-1 {{.disabled}}" href="/logout" role="button">
|
<a class="btn btn-primary btn-sm m-1 {{.disabled}}" href="/logout" role="button">
|
||||||
Logout
|
Logout
|
||||||
</a>
|
</a>
|
||||||
@ -65,7 +66,13 @@
|
|||||||
var active_tab = 0
|
var active_tab = 0
|
||||||
|
|
||||||
function del_btn(path) {
|
function del_btn(path) {
|
||||||
fetch("/delete/" + path)
|
let formData = new FormData()
|
||||||
|
formData.append('gorilla.csrf.Token', {{.csrfToken}})
|
||||||
|
|
||||||
|
fetch("/delete/" + path, {
|
||||||
|
method: "POST",
|
||||||
|
body: formData,
|
||||||
|
})
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
refresh(true)
|
refresh(true)
|
||||||
}, 20);
|
}, 20);
|
||||||
|
@ -38,6 +38,9 @@
|
|||||||
<label for="passwd">Password</label>
|
<label for="passwd">Password</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="form-floating">
|
||||||
|
{{.csrfField}}
|
||||||
|
</div>
|
||||||
<button class="w-100 btn btn-lg btn-primary mt-5" type="submit">Sign in</button>
|
<button class="w-100 btn btn-lg btn-primary mt-5" type="submit">Sign in</button>
|
||||||
<p class="mt-5 mb-3 text-muted">WiTTY: Web-based Interactive TTY</p>
|
<p class="mt-5 mb-3 text-muted">WiTTY: Web-based Interactive TTY</p>
|
||||||
</form>
|
</form>
|
||||||
|
@ -23,7 +23,8 @@
|
|||||||
<nav class="navbar navbar-light bg-light shadow-sm navbar-xs">
|
<nav class="navbar navbar-light bg-light shadow-sm navbar-xs">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<a class="navbar-brand mx-auto" href="https://github.com/syssecfsu/witty" target="_blank">
|
<a class="navbar-brand mx-auto" href="https://github.com/syssecfsu/witty" target="_blank">
|
||||||
<img src="/assets/img/{{.logo}}.svg" style="margin-right: 0.5rem;" height="32" class="d-inline-block align-text-top">
|
<img src="/assets/img/{{.logo}}.svg" style="margin-right: 0.5rem;" height="32"
|
||||||
|
class="d-inline-block align-text-top">
|
||||||
{{.title}}
|
{{.title}}
|
||||||
</a>
|
</a>
|
||||||
<button type="button" id="record_onoff" class="btn btn-primary btn-sm float-end" value="Record"
|
<button type="button" id="record_onoff" class="btn btn-primary btn-sm float-end" value="Record"
|
||||||
@ -41,15 +42,24 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
function recordOnOff(on) {
|
function recordOnOff(on) {
|
||||||
|
let formData = new FormData()
|
||||||
|
formData.append('gorilla.csrf.Token', {{.csrfToken}})
|
||||||
|
|
||||||
var btn = document.getElementById("record_onoff");
|
var btn = document.getElementById("record_onoff");
|
||||||
if (btn.value == "Record") {
|
if (btn.value == "Record") {
|
||||||
btn.value = "Stop";
|
btn.value = "Stop";
|
||||||
btn.innerHTML = btn.value
|
btn.innerHTML = btn.value
|
||||||
fetch("/record/{{.id}}")
|
fetch("/record/{{.id}}", {
|
||||||
|
method: "POST",
|
||||||
|
body: formData,
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
btn.value = "Record";
|
btn.value = "Record";
|
||||||
btn.innerHTML = btn.value
|
btn.innerHTML = btn.value
|
||||||
fetch("/stop/{{.id}}")
|
fetch("/stop/{{.id}}", {
|
||||||
|
method: "POST",
|
||||||
|
body: formData,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +73,7 @@
|
|||||||
''
|
''
|
||||||
].join('');
|
].join('');
|
||||||
|
|
||||||
term.writeln (str)
|
term.writeln(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
Init()
|
Init()
|
||||||
|
3
go.mod
3
go.mod
@ -15,6 +15,7 @@ require (
|
|||||||
github.com/gorilla/context v1.1.1 // indirect
|
github.com/gorilla/context v1.1.1 // indirect
|
||||||
github.com/gorilla/securecookie v1.1.1 // indirect
|
github.com/gorilla/securecookie v1.1.1 // indirect
|
||||||
github.com/gorilla/sessions v1.2.1 // indirect
|
github.com/gorilla/sessions v1.2.1 // indirect
|
||||||
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@ -24,6 +25,8 @@ require (
|
|||||||
github.com/go-playground/universal-translator v0.17.0 // indirect
|
github.com/go-playground/universal-translator v0.17.0 // indirect
|
||||||
github.com/go-playground/validator/v10 v10.4.1 // indirect
|
github.com/go-playground/validator/v10 v10.4.1 // indirect
|
||||||
github.com/golang/protobuf v1.3.3 // indirect
|
github.com/golang/protobuf v1.3.3 // indirect
|
||||||
|
github.com/gorilla/csrf v1.7.1
|
||||||
|
github.com/gwatts/gin-adapter v0.0.0-20170508204228-c44433c485ad
|
||||||
github.com/json-iterator/go v1.1.9 // indirect
|
github.com/json-iterator/go v1.1.9 // indirect
|
||||||
github.com/leodido/go-urn v1.2.0 // indirect
|
github.com/leodido/go-urn v1.2.0 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.12 // indirect
|
github.com/mattn/go-isatty v0.0.12 // indirect
|
||||||
|
6
go.sum
6
go.sum
@ -28,6 +28,8 @@ github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp
|
|||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
|
github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
|
||||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||||
|
github.com/gorilla/csrf v1.7.1 h1:Ir3o2c1/Uzj6FBxMlAUB6SivgVMy1ONXwYgXn+/aHPE=
|
||||||
|
github.com/gorilla/csrf v1.7.1/go.mod h1:+a/4tCmqhG6/w4oafeAZ9pEa3/NZOWYVbD9fV0FwIQA=
|
||||||
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
|
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
|
||||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
||||||
github.com/gorilla/sessions v1.1.1/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w=
|
github.com/gorilla/sessions v1.1.1/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w=
|
||||||
@ -35,6 +37,8 @@ github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7Fsg
|
|||||||
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
||||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
|
github.com/gwatts/gin-adapter v0.0.0-20170508204228-c44433c485ad h1:eGCbPkMnsg02jXBIxxXn1Fxep9dAuTUvEi6UdJsbOhg=
|
||||||
|
github.com/gwatts/gin-adapter v0.0.0-20170508204228-c44433c485ad/go.mod h1:XywyZk8euPjg6CVt44eMyHjv0sZUiHbHtBnFKgmvj8I=
|
||||||
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
|
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
|
||||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
||||||
@ -45,6 +49,8 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OH
|
|||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
|
||||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
6
main.go
6
main.go
@ -17,9 +17,12 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var naked bool
|
var naked bool
|
||||||
|
var port uint
|
||||||
runCmd := flag.NewFlagSet("run", flag.ExitOnError)
|
runCmd := flag.NewFlagSet("run", flag.ExitOnError)
|
||||||
runCmd.BoolVar(&naked, "n", false, "Run WiTTY without user authentication")
|
runCmd.BoolVar(&naked, "n", false, "Run WiTTY without user authentication")
|
||||||
runCmd.BoolVar(&naked, "naked", false, "Run WiTTY without user authentication")
|
runCmd.BoolVar(&naked, "naked", false, "Run WiTTY without user authentication")
|
||||||
|
runCmd.UintVar(&port, "p", 8080, "Port number to listen on")
|
||||||
|
runCmd.UintVar(&port, "port", 8080, "Port number to listen on")
|
||||||
|
|
||||||
var wait uint
|
var wait uint
|
||||||
replayCmd := flag.NewFlagSet("replay", flag.ExitOnError)
|
replayCmd := flag.NewFlagSet("replay", flag.ExitOnError)
|
||||||
@ -65,7 +68,6 @@ func main() {
|
|||||||
runCmd.Parse(os.Args[2:])
|
runCmd.Parse(os.Args[2:])
|
||||||
|
|
||||||
var cmdToExec []string
|
var cmdToExec []string
|
||||||
|
|
||||||
args := runCmd.Args()
|
args := runCmd.Args()
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
cmdToExec = args
|
cmdToExec = args
|
||||||
@ -73,7 +75,7 @@ func main() {
|
|||||||
cmdToExec = []string{"bash"}
|
cmdToExec = []string{"bash"}
|
||||||
}
|
}
|
||||||
|
|
||||||
web.StartWeb(fp, cmdToExec, naked)
|
web.StartWeb(fp, cmdToExec, naked, uint16(port))
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fmt.Println("witty (adduser|deluser|replay|run)")
|
fmt.Println("witty (adduser|deluser|replay|run)")
|
||||||
|
@ -36,12 +36,22 @@ const (
|
|||||||
stopCmd = 0
|
stopCmd = 0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// simple function to check origin
|
||||||
|
func checkOrigin(r *http.Request) bool {
|
||||||
|
org := r.Header.Get("Origin")
|
||||||
|
|
||||||
|
if org != "https://"+r.Host {
|
||||||
|
log.Println("Failed origin check of ", org, r.Host)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
var upgrader = websocket.Upgrader{
|
var upgrader = websocket.Upgrader{
|
||||||
ReadBufferSize: readBufferSize,
|
ReadBufferSize: readBufferSize,
|
||||||
WriteBufferSize: WriteBufferSize,
|
WriteBufferSize: WriteBufferSize,
|
||||||
CheckOrigin: func(r *http.Request) bool {
|
CheckOrigin: checkOrigin,
|
||||||
return true
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TermConn represents the connected websocket and pty.
|
// TermConn represents the connected websocket and pty.
|
||||||
@ -420,8 +430,7 @@ func ConnectTerm(w http.ResponseWriter, r *http.Request, isViewer bool, name str
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Init(checkOrigin func(r *http.Request) bool) {
|
func Init() {
|
||||||
upgrader.CheckOrigin = checkOrigin
|
|
||||||
registry.init()
|
registry.init()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/gin-gonic/contrib/sessions"
|
"github.com/gin-gonic/contrib/sessions"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/gorilla/csrf"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -48,7 +49,6 @@ func login(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
host = &c.Request.Host
|
|
||||||
c.Redirect(http.StatusSeeOther, "/")
|
c.Redirect(http.StatusSeeOther, "/")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,5 +88,10 @@ func loginPage(c *gin.Context) {
|
|||||||
msg = "Login first"
|
msg = "Login first"
|
||||||
}
|
}
|
||||||
|
|
||||||
c.HTML(http.StatusOK, "login.html", gin.H{"msg": msg})
|
c.HTML(http.StatusOK, "login.html",
|
||||||
|
gin.H{
|
||||||
|
"msg": msg,
|
||||||
|
"csrfField": csrf.TemplateField(c.Request),
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
|
|
||||||
"github.com/dchest/uniuri"
|
"github.com/dchest/uniuri"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/gorilla/csrf"
|
||||||
"github.com/syssecfsu/witty/term_conn"
|
"github.com/syssecfsu/witty/term_conn"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -27,14 +28,18 @@ func collectSessions(c *gin.Context, cmd string) (players []InteractiveSession)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func indexPage(c *gin.Context) {
|
func indexPage(c *gin.Context) {
|
||||||
host = &c.Request.Host
|
|
||||||
var disabled = ""
|
var disabled = ""
|
||||||
|
|
||||||
if noAuth {
|
if noAuth {
|
||||||
disabled = "disabled"
|
disabled = "disabled"
|
||||||
}
|
}
|
||||||
|
|
||||||
c.HTML(http.StatusOK, "index.html", gin.H{"disabled": disabled})
|
c.HTML(http.StatusOK, "index.html",
|
||||||
|
gin.H{
|
||||||
|
"disabled": disabled,
|
||||||
|
"csrfField": csrf.TemplateField(c.Request),
|
||||||
|
"csrfToken": csrf.Token(c.Request),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateIndex(c *gin.Context) {
|
func updateIndex(c *gin.Context) {
|
||||||
@ -63,17 +68,14 @@ func updateIndex(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newInteractive(c *gin.Context) {
|
func newInteractive(c *gin.Context) {
|
||||||
if host == nil {
|
|
||||||
host = &c.Request.Host
|
|
||||||
}
|
|
||||||
|
|
||||||
id := uniuri.New()
|
id := uniuri.New()
|
||||||
|
|
||||||
c.HTML(http.StatusOK, "term.html", gin.H{
|
c.HTML(http.StatusOK, "term.html", gin.H{
|
||||||
"title": "interactive terminal",
|
"title": "interactive terminal",
|
||||||
"path": "/ws_new/" + id,
|
"path": "/ws_new/" + id,
|
||||||
"id": id,
|
"id": id,
|
||||||
"logo": "keyboard",
|
"logo": "keyboard",
|
||||||
|
"csrfToken": csrf.Token(c.Request),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,10 +87,11 @@ func newTermConn(c *gin.Context) {
|
|||||||
func viewPage(c *gin.Context) {
|
func viewPage(c *gin.Context) {
|
||||||
id := c.Param("id")
|
id := c.Param("id")
|
||||||
c.HTML(http.StatusOK, "term.html", gin.H{
|
c.HTML(http.StatusOK, "term.html", gin.H{
|
||||||
"title": "viewer terminal",
|
"title": "viewer terminal",
|
||||||
"path": "/ws_view/" + id,
|
"path": "/ws_view/" + id,
|
||||||
"id": id,
|
"id": id,
|
||||||
"logo": "view",
|
"logo": "view",
|
||||||
|
"csrfToken": csrf.Token(c.Request),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,38 +1,21 @@
|
|||||||
package web
|
package web
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/dchest/uniuri"
|
"github.com/dchest/uniuri"
|
||||||
"github.com/gin-gonic/contrib/sessions"
|
"github.com/gin-gonic/contrib/sessions"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/gorilla/csrf"
|
||||||
|
adapter "github.com/gwatts/gin-adapter"
|
||||||
"github.com/syssecfsu/witty/term_conn"
|
"github.com/syssecfsu/witty/term_conn"
|
||||||
)
|
)
|
||||||
|
|
||||||
var host *string = nil
|
|
||||||
var cmdToExec []string
|
var cmdToExec []string
|
||||||
var noAuth bool
|
var noAuth bool
|
||||||
|
|
||||||
// simple function to check origin
|
func StartWeb(fp *os.File, cmd []string, naked bool, port uint16) {
|
||||||
func checkOrigin(r *http.Request) bool {
|
|
||||||
org := r.Header.Get("Origin")
|
|
||||||
h, err := url.Parse(org)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (host == nil) || (*host != h.Host) {
|
|
||||||
log.Println("Failed origin check of ", org)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (host != nil) && (*host == h.Host)
|
|
||||||
}
|
|
||||||
|
|
||||||
func StartWeb(fp *os.File, cmd []string, naked bool) {
|
|
||||||
cmdToExec = cmd
|
cmdToExec = cmd
|
||||||
noAuth = naked
|
noAuth = naked
|
||||||
|
|
||||||
@ -47,6 +30,10 @@ func StartWeb(fp *os.File, cmd []string, naked bool) {
|
|||||||
store := sessions.NewCookieStore([]byte(uniuri.NewLen(32)))
|
store := sessions.NewCookieStore([]byte(uniuri.NewLen(32)))
|
||||||
rt.Use(sessions.Sessions("witty-session", store))
|
rt.Use(sessions.Sessions("witty-session", store))
|
||||||
|
|
||||||
|
csrfHttp := csrf.Protect([]byte(uniuri.NewLen(32)), csrf.SameSite(csrf.SameSiteStrictMode))
|
||||||
|
csrfGin := adapter.Wrap(csrfHttp)
|
||||||
|
rt.Use(csrfGin)
|
||||||
|
|
||||||
rt.SetTrustedProxies(nil)
|
rt.SetTrustedProxies(nil)
|
||||||
rt.LoadHTMLGlob("./assets/template/*")
|
rt.LoadHTMLGlob("./assets/template/*")
|
||||||
// handle static files
|
// handle static files
|
||||||
@ -71,7 +58,7 @@ func StartWeb(fp *os.File, cmd []string, naked bool) {
|
|||||||
g1.GET("/update/:active", updateIndex)
|
g1.GET("/update/:active", updateIndex)
|
||||||
|
|
||||||
// create a new interactive session
|
// create a new interactive session
|
||||||
g1.GET("/new", newInteractive)
|
g1.POST("/new", newInteractive)
|
||||||
g1.GET("/ws_new/:id", newTermConn)
|
g1.GET("/ws_new/:id", newTermConn)
|
||||||
|
|
||||||
// create a viewer of an interactive session
|
// create a viewer of an interactive session
|
||||||
@ -79,15 +66,15 @@ func StartWeb(fp *os.File, cmd []string, naked bool) {
|
|||||||
g1.GET("/ws_view/:id", newViewWS)
|
g1.GET("/ws_view/:id", newViewWS)
|
||||||
|
|
||||||
// start/stop recording the session
|
// start/stop recording the session
|
||||||
g1.GET("/record/:id", startRecord)
|
g1.POST("/record/:id", startRecord)
|
||||||
g1.GET("/stop/:id", stopRecord)
|
g1.POST("/stop/:id", stopRecord)
|
||||||
|
|
||||||
// create a viewer of an interactive session
|
// create a viewer of an interactive session
|
||||||
g1.GET("/replay/:id", replayPage)
|
g1.GET("/replay/:id", replayPage)
|
||||||
|
|
||||||
// delete a recording
|
// delete a recording
|
||||||
g1.GET("/delete/:fname", delRec)
|
g1.POST("/delete/:fname", delRec)
|
||||||
|
|
||||||
term_conn.Init(checkOrigin)
|
term_conn.Init()
|
||||||
rt.RunTLS(":8080", "./tls/cert.pem", "./tls/private-key.pem")
|
rt.RunTLS(":"+strconv.FormatUint(uint64(port), 10), "./tls/cert.pem", "./tls/private-key.pem")
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user