Răsfoiți Sursa

work on auth

reid 2 ani în urmă
părinte
comite
2296681c47
2 a modificat fișierele cu 68 adăugiri și 17 ștergeri
  1. 60 16
      auth/auth.go
  2. 8 1
      ws/ws.go

+ 60 - 16
auth/auth.go

@@ -1,4 +1,8 @@
 package auth
+// package for authenticating websockets
+// we use a homespun jwt knock-off because no tls on lan
+// authentication adds you to the AuthenticatedClients map
+// broadcasts get sent to members of this map
 
 import (
 	"crypto/rand"
@@ -44,24 +48,64 @@ func WsIsAuthenticated(conn *websocket.Conn) bool {
 	return exists
 }
 
-// // CheckToken checks the validity of the token.
-// func CheckToken(token string, conn *websocket.Conn, setup bool) (bool, string, error) {
-// 	if token == "" {
-// 		authStatus := false
-// 		if setup {
-// 			authStatus = true
-// 		}
-// 		newToken, err := CreateToken(conn, setup)
-// 		if err != nil {
-// 			return false, "", err
-// 		}
-// 		return authStatus, newToken["token"], nil
-// 	}
+// check if a hash is in the auth map
+func hashAuthenticated(hash string) bool {
+	AuthenticatedClients.RLock() // Acquire read lock
+	defer AuthenticatedClients.RUnlock() // Release read lock
+	for _, v := range AuthenticatedClients.Conns {
+		if v == hash {
+			return true
+		}
+	}
+	return false
+}
 
-// 	return false, "", nil
-// }
+// check the validity of the token
+func CheckToken(token string, conn *websocket.Conn, r *http.Request, setup bool) (bool, string, error) {
+	if token == "" {
+		authStatus := false
+		if setup {
+			authStatus = true
+		}
+		newToken, err := CreateToken(conn, r, setup)
+		if err != nil {
+			return false, "", err
+		}
+		return authStatus, newToken["token"], nil
+	} else {
+		conf := config.Conf()
+		key := conf.KeyFile
+		res, err := KeyfileDecrypt(token, key)
+		if err != nil {
+			config.Logger.Warn("Invalid token provided")
+			return false, "", err
+		} else {
+			var ip string
+			if forwarded := r.Header.Get("X-Forwarded-For"); forwarded != "" {
+				ip = strings.Split(forwarded, ",")[0]
+			} else {
+				ip, _, _ = net.SplitHostPort(r.RemoteAddr)
+			}
+			userAgent := r.Header.Get("User-Agent")
+			hashed := sha256.Sum256([]byte(token))
+			hash := hex.EncodeToString(hashed[:])
+			if hashAuthenticated(hash) {
+				if ip == res["ip"] && userAgent == res["user_agent"] {
+					return true, res["id"], nil
+				} else {
+					config.Logger.Warn("Token doesn't match session!")
+					return false, res["id"], err
+				}
+			} else {
+				config.Logger.Warn("Token isn't an authenticated session")
+				return false, res["id"], err
+			}
+		}
+	}
+	return false, "", nil
+}
 
-// CreateToken creates a new session token.
+// create a new session token
 func CreateToken(conn *websocket.Conn, r *http.Request, setup bool) (map[string]string, error) {
 	// extract conn info
 	var ip string

+ 8 - 1
ws/ws.go

@@ -102,7 +102,9 @@ func WsHandler(w http.ResponseWriter, r *http.Request) {
 		case "urbit":
 			config.Logger.Info("Urbit")
 		case "support":
-			config.Logger.Info("Support")
+			if err = supportHandler(msg, payload, r, conn); err != nil {
+				config.Logger.Error(fmt.Sprintf("%v", err))
+			}
 		case "broadcast":
 			if err := broadcast.BroadcastToClients(); err != nil {
 				errmsg := fmt.Sprintf("Unable to broadcast to peer(s): %v", err)
@@ -158,3 +160,8 @@ func verifyHandler(msg []byte, payload structs.WsPayload, r *http.Request, conn
 	}
 	return nil
 }
+
+func supportHandler(msg []byte, payload structs.WsPayload, r *http.Request, conn *websocket.Conn) error {
+	config.Logger.Info("Support")
+	return nil
+}