package gateway import ( "PD2/internal/protocol" "PD2/internal/utils/cryptoUtils" "crypto/x509" "log" "net/http" "github.com/gin-gonic/gin" ) func HandleGetMessage(c *gin.Context, keyStore cryptoUtils.KeyStore) { var getMsg protocol.GetMsg err := c.Bind(getMsg) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Request body is not a GetMsg"}) return } uid, exists := c.Get("uid") if !exists { c.JSON(http.StatusBadRequest, gin.H{"error": "User does not exist"}) return } uidString := uid.(string) statusCode, body, err := forwardGetMessage(keyStore.GetGatewayOutgoingTLSConfig(), uidString, getMsg) if err != nil { log.Println(err.Error()) } else { c.JSON(statusCode, body) } } func HandleGetUnreadMsgsInfo(c *gin.Context, keyStore cryptoUtils.KeyStore) { var getUnreadMsgsInfo protocol.GetUnreadMsgsInfo err := c.Bind(getUnreadMsgsInfo) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Request body is not a GetUnreadMsgsInfo"}) return } uid, exists := c.Get("uid") if !exists { c.JSON(http.StatusBadRequest, gin.H{"error": "User does not exist"}) return } uidString := uid.(string) statusCode, body, err := forwardGetUnreadMsgsInfo(keyStore.GetGatewayOutgoingTLSConfig(), uidString, getUnreadMsgsInfo) if err != nil { log.Println(err.Error()) } else { c.JSON(statusCode, body) } } func HandleGetUserCert(c *gin.Context,keyStore cryptoUtils.KeyStore) { var getUserCert protocol.GetUserCert err := c.Bind(getUserCert) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Request body is not a GetUserCert"}) return } statusCode, body, err := forwardGetUserCert(keyStore.GetGatewayOutgoingTLSConfig(), getUserCert) if err != nil { log.Println(err.Error()) } else { c.JSON(statusCode, body) } } func HandleSendMessage(c *gin.Context, keyStore cryptoUtils.KeyStore) { var sendMsg protocol.SendMsg err := c.Bind(sendMsg) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Request body is not a SendMsg"}) return } uid, exists := c.Get("uid") if !exists { c.JSON(http.StatusBadRequest, gin.H{"error": "User does not exist"}) return } uidString := uid.(string) statusCode, body, err := forwardSendMessage(keyStore.GetGatewayOutgoingTLSConfig(), uidString, sendMsg) if err != nil { log.Println(err.Error()) } else { c.JSON(statusCode, body) } } func HandleRegister(c *gin.Context, dataStore DataStore, keyStore cryptoUtils.KeyStore) { var postRegister protocol.PostRegister err := c.Bind(postRegister) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Request body is not a PostRegister"}) return } userCert, err := x509.ParseCertificate(postRegister.Certificate) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "User certificate is invalid"}) return } err = keyStore.CheckCert(userCert, postRegister.UID, "MSG SERVICE") if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "User certificate is invalid, not trusted, belongs to another user or has incorrect usage field"}) return } hashedPassword, err := HashPassword(postRegister.Password) if err != nil { log.Fatalln("Could not hash the password") } err = dataStore.InsertUser(postRegister.UID, hashedPassword) if err != nil { log.Fatalln("Could not insert user into DB") } storeUserCertificate := protocol.NewStoreUserCert(userCert.Raw) statusCode, body, err := forwardStoreUserCert(keyStore.GetGatewayOutgoingTLSConfig(), postRegister.UID, storeUserCertificate) if err != nil { log.Println(err.Error()) } else { c.JSON(statusCode, body) } } func HandleLogin(c *gin.Context, dataStore DataStore, keyStore cryptoUtils.KeyStore) { var postLogin protocol.PostLogin err := c.Bind(postLogin) if err != nil { c.AbortWithStatus(http.StatusBadRequest) } hashedPassword, err := dataStore.GetPassword(postLogin.UID) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user id or password"}) return } err = CheckPassword(hashedPassword, postLogin.Password) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user id or password"}) return } jwToken, err := GenerateJWT(postLogin.UID) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Failed to create token"}) } //Send token to user c.JSON(http.StatusOK, gin.H{"token": jwToken}) } func AuthMiddleware(c *gin.Context) { tokenList := c.Request.Header["Token"] if tokenList == nil { c.JSON(http.StatusUnauthorized, gin.H{"error": "No authentication token provided"}) } // We only care about the first entry token := tokenList[0] uid, err := ValidateJWT(token) if err != nil { c.JSON(http.StatusUnauthorized, gin.H{"error": "Token is invalid or has expired"}) } c.Set("uid", uid) c.Next() } func Run() { dataStore, err := OpenDB() if err != nil { log.Fatalln("Error opening the database") } defer dataStore.db.Close() passphrase := readStdin("Insert keystore passphrase") keyStore, err := cryptoUtils.LoadKeyStore("certs/gateway/gateway.p12", passphrase) if err != nil { log.Fatalln(err.Error()) } router := gin.Default() auth := router.Group("/", func(c *gin.Context) { AuthMiddleware(c) }) auth.GET("/message/:num", func(c *gin.Context) { HandleGetMessage(c, keyStore) }) auth.GET("/queue", func(c *gin.Context) { HandleGetUnreadMsgsInfo(c, keyStore) }) auth.GET("/cert/:user", func(c *gin.Context) { HandleGetUserCert(c, keyStore) }) auth.POST("/message", func(c *gin.Context) { HandleSendMessage(c, keyStore) }) router.POST("/register", func(c *gin.Context) { HandleRegister(c, dataStore, keyStore) }) router.POST("/login", func(c *gin.Context) { HandleLogin(c, dataStore, keyStore) }) server := http.Server{ Addr: "0.0.0.0:9090", Handler: router, TLSConfig: keyStore.GetGatewayIncomingTLSConfig(), } err = server.ListenAndServeTLS("", "") if err != nil { log.Fatal(err.Error()) } }