summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pkg/backend/webapi.go38
-rw-r--r--pkg/bitmask/auth.go52
2 files changed, 86 insertions, 4 deletions
diff --git a/pkg/backend/webapi.go b/pkg/backend/webapi.go
index e3918c5..a8844e8 100644
--- a/pkg/backend/webapi.go
+++ b/pkg/backend/webapi.go
@@ -4,8 +4,35 @@ import (
"fmt"
"log"
"net/http"
+ "os"
+
+ "0xacab.org/leap/bitmask-vpn/pkg/bitmask"
)
+func Adapt(h http.Handler, adapters ...Adapter) http.Handler {
+ for _, adapter := range adapters {
+ h = adapter(h)
+ }
+ return h
+}
+
+type Adapter func(http.Handler) http.Handler
+
+func CheckAuth(token string) Adapter {
+ return func(h http.Handler) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ t := r.Header.Get("X-Auth-Token")
+ if t == token {
+ h.ServeHTTP(w, r)
+ } else {
+ w.WriteHeader(http.StatusUnauthorized)
+ w.Write([]byte("401 - Unauthorized"))
+ }
+
+ })
+ }
+}
+
func webOn(w http.ResponseWriter, r *http.Request) {
log.Println("Web UI: on")
SwitchOn()
@@ -24,12 +51,15 @@ func webStatus(w http.ResponseWriter, r *http.Request) {
func webQuit(w http.ResponseWriter, r *http.Request) {
log.Println("Web UI: quit")
Quit()
+ os.Exit(0)
}
func enableWebAPI() {
- http.HandleFunc("/vpn/start", webOn)
- http.HandleFunc("/vpn/stop", webOff)
- http.HandleFunc("/vpn/status", webStatus)
- http.HandleFunc("/vpn/quit", webQuit)
+ bitmask.GenerateAuthToken()
+ auth := CheckAuth(bitmask.ReadAuthToken())
+ http.Handle("/vpn/start", Adapt(http.HandlerFunc(webOn), auth))
+ http.Handle("/vpn/stop", Adapt(http.HandlerFunc(webOff), auth))
+ http.Handle("/vpn/status", Adapt(http.HandlerFunc(webStatus), auth))
+ http.Handle("/vpn/quit", Adapt(http.HandlerFunc(webQuit), auth))
http.ListenAndServe(":8080", nil)
}
diff --git a/pkg/bitmask/auth.go b/pkg/bitmask/auth.go
new file mode 100644
index 0000000..519eaf1
--- /dev/null
+++ b/pkg/bitmask/auth.go
@@ -0,0 +1,52 @@
+package bitmask
+
+import (
+ "io/ioutil"
+ "log"
+ "math/rand"
+ "os"
+ "runtime"
+ "strings"
+ "time"
+)
+
+/* functions for local authentication of control endpoints */
+
+const tokenPath = "/dev/shm/bitmask-token"
+
+func GenerateAuthToken() {
+ if runtime.GOOS != "linux" {
+ log.Println("Authentication token only implemented in linux at the moment.")
+ return
+ }
+ t := getRandomString()
+ err := ioutil.WriteFile(tokenPath, []byte(t), os.FileMode(int(0600)))
+ if err != nil {
+ log.Println("Could not write authentication token.")
+ }
+}
+
+func ReadAuthToken() string {
+ if runtime.GOOS != "linux" {
+ log.Println("Authentication token only implemented in linux at the moment.")
+ return ""
+ }
+ token, err := ioutil.ReadFile(tokenPath)
+ if err != nil {
+ log.Println("Error reading token:", err)
+ }
+ return string(token)
+}
+
+func getRandomString() string {
+ rand.Seed(time.Now().UnixNano())
+ chars := []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
+ "abcdefghijklmnopqrstuvwxyz" +
+ "0123456789")
+ length := 40
+ var b strings.Builder
+ for i := 0; i < length; i++ {
+ b.WriteRune(chars[rand.Intn(len(chars))])
+ }
+ return b.String()
+}