package gateway import ( "PD2/internal/protocol" "PD2/internal/utils/cryptoUtils" "crypto/x509" "fmt" "log" "net/http" "github.com/gin-gonic/gin" ) func HandleGetMessage(c *gin.Context) { fmt.Println("Get Message Handler") } func HandleGetUnreadMsgsInfo(c *gin.Context) { fmt.Println("Get Unread Messages Info Handler") } func HandleGetUserCert(c *gin.Context) { fmt.Println("Get User Cert Handler") } func HandleSendMessage(c *gin.Context) { fmt.Println("Send Message Handler") } 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 } //Check if the certificate pseudonym matches the uid in postRegister //And if it's signed by the CA userCert, err := x509.ParseCertificate(postRegister.Certificate) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "User certificate is invalid"}) return } oidMap := cryptoUtils.ExtractAllOIDValues(userCert) //Check if certificate usage is MSG SERVICE usage := oidMap["2.5.4.11"] if usage != "MSG SERVICE" { c.JSON(http.StatusBadRequest, gin.H{"error": "Certificate usage is not \"MSG SERVICE\""}) 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") } //TODO: Send the certificate to the server c.JSON(http.StatusOK, gin.H{}) } 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) { fmt.Println("Authentication Middleware") 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) }) auth.GET("/queue", func(c *gin.Context) { HandleGetUnreadMsgsInfo(c) }) auth.GET("/cert/:user", func(c *gin.Context) { HandleGetUserCert(c) }) auth.POST("/message", func(c *gin.Context) { HandleSendMessage(c) }) 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:8080", Handler: router, TLSConfig: keyStore.GetGatewayIncomingTLSConfig(), } err = server.ListenAndServeTLS("", "") if err != nil { log.Fatal(err.Error()) } }