This commit is contained in:
Tiago Sousa 2024-05-30 15:50:26 +01:00
commit c94831d0a2
Signed by: tiago
SSH key fingerprint: SHA256:rOmjD81ZIhKdCkFWS9UIKdBi4UByF5x3hRH/0YeXsPI
9 changed files with 160 additions and 133 deletions

View file

@ -1,7 +1,7 @@
package main
import (
"PD1/internal/client"
"PD2/internal/client"
)
func main(){

View file

@ -1,7 +1,7 @@
package main
import (
"PD1/internal/gateway"
"PD2/internal/gateway"
)
func main(){

View file

@ -1,7 +1,7 @@
package main
import (
"PD1/internal/server"
"PD2/internal/server"
)
func main(){

View file

@ -1,4 +1,4 @@
module PD1
module PD2
go 1.22.2

View file

@ -1,9 +1,9 @@
package client
import (
"PD1/internal/protocol"
"PD1/internal/utils/cryptoUtils"
"PD1/internal/utils/networking"
"PD2/internal/protocol"
"PD2/internal/utils/cryptoUtils"
"PD2/internal/utils/networking"
"crypto/x509"
"errors"
"flag"

View file

@ -1,8 +1,8 @@
package gateway
import (
"PD1/internal/protocol"
"PD1/internal/utils/cryptoUtils"
"PD2/internal/protocol"
"PD2/internal/utils/cryptoUtils"
"crypto/x509"
"fmt"
"log"
@ -32,30 +32,30 @@ func HandleRegister(c *gin.Context, dataStore DataStore, keyStore cryptoUtils.Ke
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
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
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
c.JSON(http.StatusBadRequest, gin.H{"error": "Certificate usage is not \"MSG SERVICE\""})
return
}
err = keyStore.CheckCert(userCert, postRegister.UID)
err = keyStore.CheckCert(userCert, postRegister.UID, "MSG SERVICE")
if err != nil {
c.JSON(http.StatusBadRequest,gin.H{"error": "User certificate is invalid, not trusted or belongs to another user"})
return
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)
@ -65,10 +65,10 @@ func HandleRegister(c *gin.Context, dataStore DataStore, keyStore cryptoUtils.Ke
err = dataStore.InsertUser(postRegister.UID, hashedPassword)
if err != nil {
log.Fatalln("Could not insert user into DB")
log.Fatalln("Could not insert user into DB")
}
//TODO: Send the certificate to the server
//TODO: Send the certificate to the server
c.JSON(http.StatusOK, gin.H{})
@ -91,31 +91,30 @@ func HandleLogin(c *gin.Context, dataStore DataStore, keyStore cryptoUtils.KeySt
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user id or password"})
return
}
jwToken, err := GenerateJWT(postLogin.UID)
jwToken, err := GenerateJWT(postLogin.UID)
if err != nil {
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})
}
//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()
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() {
@ -164,10 +163,10 @@ func Run() {
server := http.Server{
Addr: "0.0.0.0:8080",
Handler: router,
TLSConfig: serverKeyStore.GetServerTLSConfig(),
TLSConfig: keyStore.GetGatewayIncomingTLSConfig(),
}
err := server.ListenAndServeTLS("", "")
err = server.ListenAndServeTLS("", "")
if err != nil {
log.Fatal(err.Error())
}

View file

@ -1,7 +1,7 @@
package server
import (
"PD1/internal/protocol"
"PD2/internal/protocol"
"crypto/x509"
"database/sql"
"errors"

View file

@ -1,8 +1,8 @@
package server
import (
"PD1/internal/protocol"
"PD1/internal/utils/cryptoUtils"
"PD2/internal/protocol"
"PD2/internal/utils/cryptoUtils"
"log"
"net/http"
"strconv"
@ -10,29 +10,6 @@ import (
"github.com/gin-gonic/gin"
)
//func clientHandler(connection networking.Connection[protocol.Packet], dataStore DataStore) {
// defer connection.Conn.Close()
//
// //Get certificate sent by user
// clientCert := connection.GetPeerCertificate()
// //Get the OID values
// oidMap := cryptoUtils.ExtractAllOIDValues(clientCert)
// //Check if certificate usage is MSG SERVICE
// usage := oidMap["2.5.4.11"]
// if usage == "" {
// log.Fatalln("User certificate does not have the correct usage")
// }
// //Get the UID of this user
// UID := oidMap["2.5.4.65"]
// if UID == "" {
// log.Fatalln("User certificate does not specify it's PSEUDONYM")
// }
// err := dataStore.storeUserCertIfNotExists(UID, *clientCert)
// if err != nil {
// log.Fatalln(err)
// }
//}
func HandleGetUserCert(c *gin.Context, dataStore DataStore) {
user := c.Param("user")
userCertPacket, err := dataStore.GetUserCertificate(user)

View file

@ -19,19 +19,15 @@ import (
)
type KeyStore struct {
cert *x509.Certificate
caCertChain []*x509.Certificate
privKey *rsa.PrivateKey
cert *x509.Certificate
caCertPool *x509.CertPool
privKey *rsa.PrivateKey
}
func (k KeyStore) GetCert() *x509.Certificate {
return k.cert
}
func (k KeyStore) GetCACertChain() []*x509.Certificate {
return k.caCertChain
}
func (k KeyStore) GetPrivKey() *rsa.PrivateKey {
return k.privKey
}
@ -67,25 +63,31 @@ func LoadKeyStore(keyStorePath string, password string) (KeyStore, error) {
if err := privKey.Validate(); err != nil {
return KeyStore{}, err
}
return KeyStore{cert: cert, caCertChain: caCerts, privKey: privKey}, err
}
// Check if the cert is signed by the CA and is for the correct user
func (k KeyStore) CheckCert(cert *x509.Certificate, uid string) error {
caCertPool := x509.NewCertPool()
for _, caCert := range k.caCertChain {
for _, caCert := range caCerts {
caCertPool.AddCert(caCert)
}
return KeyStore{cert: cert, caCertPool: caCertPool, privKey: privKey}, err
}
// Check if the cert is signed by a known CA
func (k KeyStore) CheckCertCA(cert *x509.Certificate) error {
// Verify the peer's certificate
opts := x509.VerifyOptions{
Roots: caCertPool,
Roots: k.caCertPool,
}
// Check if the certificate is signed by the specified CA
_, err := cert.Verify(opts)
if err != nil {
log.Println("Certificate not signed by a trusted CA")
return err
return errors.New("certificate not signed by trusted CA")
}
return nil
}
// Check if the cert is valid
func (k KeyStore) CheckCertTime(cert *x509.Certificate) error {
if cert.NotAfter.Before(time.Now()) {
return errors.New("certificate has expired")
}
@ -93,10 +95,37 @@ func (k KeyStore) CheckCert(cert *x509.Certificate, uid string) error {
return errors.New("certificate is not valid yet")
}
//Check if the pseudonym field is set to UID
return nil
}
// Check if the pseudonym field is set to the correct pseudonym
func (k KeyStore) CheckCertPseudonym(cert *x509.Certificate, pseudonym string) error {
oidMap := ExtractAllOIDValues(cert)
if oidMap["2.5.4.65"] != uid {
log.Println("Certificate does not belong to the message's receiver")
if oidMap["2.5.4.65"] != pseudonym {
return errors.New("Certificate does not belong to the correct pseudonym")
}
return nil
}
func (k KeyStore) CheckCertUsage(cert *x509.Certificate, usage string) error {
oidMap := ExtractAllOIDValues(cert)
if oidMap["2.5.4.11"] != usage {
return errors.New("Certificate does not have the correct usage")
}
return nil
}
func (k KeyStore) CheckCert(cert *x509.Certificate, pseudonym string, usage string) error {
if err := k.CheckCertCA(cert); err != nil {
return err
}
if err := k.CheckCertTime(cert); err != nil {
return err
}
if err := k.CheckCertPseudonym(cert, pseudonym); err != nil {
return err
}
if err := k.CheckCertUsage(cert, usage); err != nil {
return err
}
return nil
@ -106,49 +135,58 @@ func (k *KeyStore) GetTLSConfig() *tls.Config {
certificate := tls.Certificate{Certificate: [][]byte{k.cert.Raw}, PrivateKey: k.privKey, Leaf: k.cert}
//Add the CA certificate chain to a CertPool
caCertPool := x509.NewCertPool()
for _, caCert := range k.caCertChain {
caCertPool.AddCert(caCert)
}
config := &tls.Config{
Certificates: []tls.Certificate{certificate},
}
return config
}
func (k *KeyStore) GetServerTLSConfig() *tls.Config {
func (k *KeyStore) GetGatewayIncomingTLSConfig() *tls.Config {
tlsConfig := k.GetTLSConfig()
//Add the CA certificate chain to a CertPool
caCertPool := x509.NewCertPool()
for _, caCert := range k.caCertChain {
caCertPool.AddCert(caCert)
}
tlsConfig.ClientCAs = caCertPool
tlsConfig.ClientAuth = tls.RequireAnyClientCert
tlsConfig.VerifyPeerCertificate = func(rawCerts [][]byte, _ [][]*x509.Certificate) error {
// Verify the peer's certificate
opts := x509.VerifyOptions{
Roots: caCertPool,
}
for _, certBytes := range rawCerts {
cert, err := x509.ParseCertificate(certBytes)
if err != nil {
return err
}
if cert.NotAfter.Before(time.Now()) {
return errors.New("certificate has expired")
if err = k.CheckCertCA(cert); err != nil {
return err
}
if cert.NotBefore.After(time.Now()) {
return errors.New("certificate is not valid yet")
if err = k.CheckCertTime(cert); err != nil {
return err
}
if err = k.CheckCertUsage(cert, "MSG SERVICE"); err != nil {
return err
}
}
return nil
}
return tlsConfig
}
// Check if the certificate is signed by the specified CA
_, err = cert.Verify(opts)
func (k *KeyStore) GetGatewayOutgoingTLSConfig() *tls.Config {
tlsConfig := k.GetTLSConfig()
tlsConfig.RootCAs = k.caCertPool
tlsConfig.InsecureSkipVerify = true
tlsConfig.VerifyPeerCertificate = func(rawCerts [][]byte, _ [][]*x509.Certificate) error {
for _, certBytes := range rawCerts {
cert, err := x509.ParseCertificate(certBytes)
if err != nil {
return errors.New("certificate not signed by trusted CA")
return err
}
if err = k.CheckCertCA(cert); err != nil {
return err
}
if err = k.CheckCertTime(cert); err != nil {
return err
}
if err = k.CheckCertPseudonym(cert, "SERVER"); err != nil {
return err
}
if err = k.CheckCertUsage(cert, "MSG SERVICE"); err != nil {
return err
}
}
return nil
@ -159,41 +197,54 @@ func (k *KeyStore) GetServerTLSConfig() *tls.Config {
func (k *KeyStore) GetClientTLSConfig() *tls.Config {
tlsConfig := k.GetTLSConfig()
//Add the CA certificate chain to a CertPool
caCertPool := x509.NewCertPool()
for _, caCert := range k.caCertChain {
caCertPool.AddCert(caCert)
}
tlsConfig.RootCAs = caCertPool
tlsConfig.RootCAs = k.caCertPool
tlsConfig.InsecureSkipVerify = true
tlsConfig.VerifyPeerCertificate = func(rawCerts [][]byte, _ [][]*x509.Certificate) error {
// Verify the peer's certificate
opts := x509.VerifyOptions{
Roots: caCertPool,
}
for _, certBytes := range rawCerts {
cert, err := x509.ParseCertificate(certBytes)
if err != nil {
return err
}
if cert.NotAfter.Before(time.Now()) {
return errors.New("certificate has expired")
if err = k.CheckCertCA(cert); err != nil {
return err
}
if cert.NotBefore.After(time.Now()) {
return errors.New("certificate is not valid yet")
if err = k.CheckCertTime(cert); err != nil {
return err
}
if err = k.CheckCertPseudonym(cert, "GATEWAY"); err != nil {
return err
}
if err = k.CheckCertUsage(cert, "MSG SERVICE"); err != nil {
return err
}
oidMap := ExtractAllOIDValues(cert)
// Check if the certificate is signed by the specified CA
_, err = cert.Verify(opts)
}
return nil
}
return tlsConfig
}
func (k *KeyStore) GetServerTLSConfig() *tls.Config {
tlsConfig := k.GetTLSConfig()
tlsConfig.ClientAuth = tls.RequireAnyClientCert
tlsConfig.VerifyPeerCertificate = func(rawCerts [][]byte, _ [][]*x509.Certificate) error {
for _, certBytes := range rawCerts {
cert, err := x509.ParseCertificate(certBytes)
if err != nil {
return errors.New("certificate not signed by trusted CA")
return err
}
//Check if the pseudonym field is set to "SERVER"
if oidMap["2.5.4.65"] != "SERVER" {
return errors.New("peer isn't the server")
if err = k.CheckCertCA(cert); err != nil {
return err
}
if err = k.CheckCertTime(cert); err != nil {
return err
}
if err = k.CheckCertPseudonym(cert, "GATEWAY"); err != nil {
return err
}
if err = k.CheckCertUsage(cert, "MSG SERVICE"); err != nil {
return err
}
}
return nil