[PD1] Error handling project-wide
This commit is contained in:
parent
f5b3726673
commit
b918211736
13 changed files with 364 additions and 245 deletions
|
@ -5,6 +5,7 @@ import (
|
|||
"PD1/internal/utils/cryptoUtils"
|
||||
"PD1/internal/utils/networking"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"flag"
|
||||
"log"
|
||||
"sort"
|
||||
|
@ -17,45 +18,27 @@ func Run() {
|
|||
flag.Parse()
|
||||
|
||||
if flag.NArg() == 0 {
|
||||
panic("No command provided. Use 'help' for instructions.")
|
||||
log.Fatalln("No command provided. Use 'help' for instructions.")
|
||||
}
|
||||
//Get user KeyStore
|
||||
password := readStdin("Insert keystore passphrase")
|
||||
clientKeyStore := cryptoUtils.LoadKeyStore(userFile, password)
|
||||
clientKeyStore, err := cryptoUtils.LoadKeyStore(userFile, password)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
command := flag.Arg(0)
|
||||
switch command {
|
||||
case "send":
|
||||
if flag.NArg() < 3 {
|
||||
panic("Insufficient arguments for 'send' command. Usage: send <UID> <SUBJECT>")
|
||||
log.Fatalln("Insufficient arguments for 'send' command. Usage: send <UID> <SUBJECT>")
|
||||
}
|
||||
uid := flag.Arg(1)
|
||||
plainSubject := flag.Arg(2)
|
||||
plainBody := readStdin("Enter message content (limited to 1000 bytes):")
|
||||
//Turn content to bytes
|
||||
plainSubjectBytes := Marshal(plainSubject)
|
||||
plainBodyBytes := Marshal(plainBody)
|
||||
|
||||
cl := networking.NewClient[protocol.Packet](&clientKeyStore)
|
||||
defer cl.Connection.Conn.Close()
|
||||
|
||||
receiverCert := getUserCert(cl, clientKeyStore, uid)
|
||||
if receiverCert == nil {
|
||||
return
|
||||
}
|
||||
subject := clientKeyStore.EncryptMessageContent(receiverCert, plainSubjectBytes)
|
||||
body := clientKeyStore.EncryptMessageContent(receiverCert, plainBodyBytes)
|
||||
sendMsgPacket := protocol.NewSendMsgPacket(uid, subject, body)
|
||||
if !cl.Connection.Send(sendMsgPacket) {
|
||||
return
|
||||
}
|
||||
answerSendMsg, active := cl.Connection.Receive()
|
||||
if !active {
|
||||
return
|
||||
}
|
||||
if answerSendMsg.Flag == protocol.FlagReportError {
|
||||
reportError := protocol.UnmarshalReportError(answerSendMsg.Body)
|
||||
log.Println(reportError.ErrorMessage)
|
||||
err := sendCommand(clientKeyStore, plainSubject, plainBody, uid)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
case "askqueue":
|
||||
|
@ -74,41 +57,24 @@ func Run() {
|
|||
}
|
||||
}
|
||||
|
||||
cl := networking.NewClient[protocol.Packet](&clientKeyStore)
|
||||
defer cl.Connection.Conn.Close()
|
||||
askQueue(cl, clientKeyStore, page, pageSize)
|
||||
err := askQueueCommand(clientKeyStore, page, pageSize)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
case "getmsg":
|
||||
if flag.NArg() < 2 {
|
||||
panic("Insufficient arguments for 'getmsg' command. Usage: getmsg <NUM>")
|
||||
log.Fatalln("Insufficient arguments for 'getmsg' command. Usage: getmsg <NUM>")
|
||||
}
|
||||
numString := flag.Arg(1)
|
||||
cl := networking.NewClient[protocol.Packet](&clientKeyStore)
|
||||
defer cl.Connection.Conn.Close()
|
||||
num, err := strconv.Atoi(numString)
|
||||
if err != nil {
|
||||
log.Panicln("NUM argument provided is not a number")
|
||||
log.Fatalln(err)
|
||||
}
|
||||
packet := protocol.NewGetMsgPacket(num)
|
||||
cl.Connection.Send(packet)
|
||||
|
||||
receivedMsgPacket, active := cl.Connection.Receive()
|
||||
if !active {
|
||||
return
|
||||
err = getMsgCommand(clientKeyStore, num)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
if receivedMsgPacket.Flag == protocol.FlagReportError {
|
||||
reportError := protocol.UnmarshalReportError(receivedMsgPacket.Body)
|
||||
log.Println(reportError.ErrorMessage)
|
||||
return
|
||||
}
|
||||
answerGetMsg := protocol.UnmarshalAnswerGetMsg(receivedMsgPacket.Body)
|
||||
senderCert := getUserCert(cl, clientKeyStore, answerGetMsg.FromUID)
|
||||
decSubjectBytes := clientKeyStore.DecryptMessageContent(senderCert, answerGetMsg.Subject)
|
||||
decBodyBytes := clientKeyStore.DecryptMessageContent(senderCert, answerGetMsg.Body)
|
||||
subject := Unmarshal(decSubjectBytes)
|
||||
body := Unmarshal(decBodyBytes)
|
||||
message := newClientMessage(answerGetMsg.FromUID, answerGetMsg.ToUID, subject, body, answerGetMsg.Timestamp)
|
||||
showMessage(message)
|
||||
|
||||
case "help":
|
||||
showHelp()
|
||||
|
@ -119,43 +85,152 @@ func Run() {
|
|||
|
||||
}
|
||||
|
||||
func getUserCert(cl networking.Client[protocol.Packet], keyStore cryptoUtils.KeyStore, uid string) *x509.Certificate {
|
||||
getUserCertPacket := protocol.NewGetUserCertPacket(uid)
|
||||
if !cl.Connection.Send(getUserCertPacket) {
|
||||
return nil
|
||||
}
|
||||
var answerGetUserCertPacket *protocol.Packet
|
||||
answerGetUserCertPacket, active := cl.Connection.Receive()
|
||||
if !active {
|
||||
return nil
|
||||
}
|
||||
if answerGetUserCertPacket.Flag == protocol.FlagReportError {
|
||||
reportError := protocol.UnmarshalReportError(answerGetUserCertPacket.Body)
|
||||
log.Println(reportError.ErrorMessage)
|
||||
return nil
|
||||
}
|
||||
answerGetUserCert := protocol.UnmarshalAnswerGetUserCert(answerGetUserCertPacket.Body)
|
||||
userCert, err := x509.ParseCertificate(answerGetUserCert.Certificate)
|
||||
func sendCommand(clientKeyStore cryptoUtils.KeyStore, plainSubject, plainBody, uid string) error {
|
||||
//Turn content to bytes
|
||||
plainSubjectBytes, err := Marshal(plainSubject)
|
||||
if err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
if !keyStore.CheckCert(userCert, uid){
|
||||
return nil
|
||||
}
|
||||
return userCert
|
||||
plainBodyBytes, err := Marshal(plainBody)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cl, err := networking.NewClient[protocol.Packet](&clientKeyStore)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer cl.Connection.Conn.Close()
|
||||
|
||||
receiverCert, err := getUserCert(cl, clientKeyStore, uid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
subject, err := clientKeyStore.EncryptMessageContent(receiverCert, plainSubjectBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
body, err := clientKeyStore.EncryptMessageContent(receiverCert, plainBodyBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sendMsgPacket := protocol.NewSendMsgPacket(uid, subject, body)
|
||||
if err := cl.Connection.Send(sendMsgPacket); err != nil {
|
||||
return err
|
||||
}
|
||||
answerSendMsg, err := cl.Connection.Receive()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if answerSendMsg.Flag == protocol.FlagReportError {
|
||||
reportError, err := protocol.UnmarshalReportError(answerSendMsg.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return errors.New(reportError.ErrorMessage)
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func getManyMessagesInfo(cl networking.Client[protocol.Packet], keyStore cryptoUtils.KeyStore) (protocol.AnswerGetUnreadMsgsInfo, map[string]*x509.Certificate) {
|
||||
answerGetUnreadMsgsInfoPacket, active := cl.Connection.Receive()
|
||||
if !active {
|
||||
return protocol.NewAnswerGetUnreadMsgsInfo(0, 0, nil), nil
|
||||
func getMsgCommand(clientKeyStore cryptoUtils.KeyStore, num int) error {
|
||||
cl, err := networking.NewClient[protocol.Packet](&clientKeyStore)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer cl.Connection.Conn.Close()
|
||||
packet := protocol.NewGetMsgPacket(num)
|
||||
if err := cl.Connection.Send(packet); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
receivedMsgPacket, err := cl.Connection.Receive()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if receivedMsgPacket.Flag == protocol.FlagReportError {
|
||||
reportError, err := protocol.UnmarshalReportError(receivedMsgPacket.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return errors.New(reportError.ErrorMessage)
|
||||
}
|
||||
answerGetMsg, err := protocol.UnmarshalAnswerGetMsg(receivedMsgPacket.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
senderCert, err := getUserCert(cl, clientKeyStore, answerGetMsg.FromUID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
decSubjectBytes, err := clientKeyStore.DecryptMessageContent(senderCert, answerGetMsg.Subject)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
decBodyBytes, err := clientKeyStore.DecryptMessageContent(senderCert, answerGetMsg.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
subject, err := Unmarshal(decSubjectBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
body, err := Unmarshal(decBodyBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
message := newClientMessage(answerGetMsg.FromUID, answerGetMsg.ToUID, subject, body, answerGetMsg.Timestamp)
|
||||
showMessage(message)
|
||||
return nil
|
||||
}
|
||||
|
||||
func getUserCert(cl networking.Client[protocol.Packet], keyStore cryptoUtils.KeyStore, uid string) (*x509.Certificate, error) {
|
||||
getUserCertPacket := protocol.NewGetUserCertPacket(uid)
|
||||
if err := cl.Connection.Send(getUserCertPacket); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var answerGetUserCertPacket *protocol.Packet
|
||||
answerGetUserCertPacket, err := cl.Connection.Receive()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if answerGetUserCertPacket.Flag == protocol.FlagReportError {
|
||||
reportError, err := protocol.UnmarshalReportError(answerGetUserCertPacket.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, errors.New(reportError.ErrorMessage)
|
||||
}
|
||||
answerGetUserCert, err := protocol.UnmarshalAnswerGetUserCert(answerGetUserCertPacket.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
userCert, err := x509.ParseCertificate(answerGetUserCert.Certificate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := keyStore.CheckCert(userCert, uid); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return userCert, nil
|
||||
}
|
||||
|
||||
func getManyMessagesInfo(cl networking.Client[protocol.Packet], keyStore cryptoUtils.KeyStore) (protocol.AnswerGetUnreadMsgsInfo, map[string]*x509.Certificate, error) {
|
||||
answerGetUnreadMsgsInfoPacket, err := cl.Connection.Receive()
|
||||
if err != nil {
|
||||
return protocol.NewAnswerGetUnreadMsgsInfo(0, 0, nil), nil, err
|
||||
}
|
||||
if answerGetUnreadMsgsInfoPacket.Flag == protocol.FlagReportError {
|
||||
reportError := protocol.UnmarshalReportError(answerGetUnreadMsgsInfoPacket.Body)
|
||||
log.Println(reportError.ErrorMessage)
|
||||
return protocol.NewAnswerGetUnreadMsgsInfo(0, 0, nil), nil
|
||||
reportError, err := protocol.UnmarshalReportError(answerGetUnreadMsgsInfoPacket.Body)
|
||||
if err != nil {
|
||||
return protocol.AnswerGetUnreadMsgsInfo{}, nil, err
|
||||
}
|
||||
return protocol.NewAnswerGetUnreadMsgsInfo(0, 0, nil), nil, errors.New(reportError.ErrorMessage)
|
||||
}
|
||||
answerGetUnreadMsgsInfo, err := protocol.UnmarshalAnswerGetUnreadMsgsInfo(answerGetUnreadMsgsInfoPacket.Body)
|
||||
if err != nil {
|
||||
return protocol.AnswerGetUnreadMsgsInfo{}, nil, err
|
||||
}
|
||||
answerGetUnreadMsgsInfo := protocol.UnmarshalAnswerGetUnreadMsgsInfo(answerGetUnreadMsgsInfoPacket.Body)
|
||||
|
||||
//Create Set of needed certificates
|
||||
senderSet := map[string]bool{}
|
||||
|
@ -165,32 +240,60 @@ func getManyMessagesInfo(cl networking.Client[protocol.Packet], keyStore cryptoU
|
|||
certificatesMap := map[string]*x509.Certificate{}
|
||||
//Get senders' certificates
|
||||
for senderUID := range senderSet {
|
||||
senderCert := getUserCert(cl, keyStore, senderUID)
|
||||
certificatesMap[senderUID] = senderCert
|
||||
senderCert, err := getUserCert(cl, keyStore, senderUID)
|
||||
if err == nil {
|
||||
certificatesMap[senderUID] = senderCert
|
||||
}
|
||||
}
|
||||
return answerGetUnreadMsgsInfo, certificatesMap
|
||||
return answerGetUnreadMsgsInfo, certificatesMap, nil
|
||||
}
|
||||
|
||||
func askQueue(cl networking.Client[protocol.Packet], clientKeyStore cryptoUtils.KeyStore, page int, pageSize int) {
|
||||
requestUnreadMsgsQueuePacket := protocol.NewGetUnreadMsgsInfoPacket(page, pageSize)
|
||||
if !cl.Connection.Send(requestUnreadMsgsQueuePacket) {
|
||||
return
|
||||
func askQueueCommand(clientKeyStore cryptoUtils.KeyStore, page int, pageSize int) error {
|
||||
cl, err := networking.NewClient[protocol.Packet](&clientKeyStore)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer cl.Connection.Conn.Close()
|
||||
return askQueueRec(cl, clientKeyStore, page, pageSize)
|
||||
}
|
||||
|
||||
func askQueueRec(cl networking.Client[protocol.Packet], clientKeyStore cryptoUtils.KeyStore, page int, pageSize int) error {
|
||||
|
||||
requestUnreadMsgsQueuePacket := protocol.NewGetUnreadMsgsInfoPacket(page, pageSize)
|
||||
if err := cl.Connection.Send(requestUnreadMsgsQueuePacket); err != nil {
|
||||
return err
|
||||
}
|
||||
unreadMsgsInfo, certificates, err := getManyMessagesInfo(cl, clientKeyStore)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
unreadMsgsInfo, certificates := getManyMessagesInfo(cl, clientKeyStore)
|
||||
var clientMessages []ClientMessageInfo
|
||||
for _, message := range unreadMsgsInfo.MessagesInfo {
|
||||
var clientMessageInfo ClientMessageInfo
|
||||
senderCert, ok := certificates[message.FromUID]
|
||||
if ok {
|
||||
var subject string
|
||||
if senderCert != nil {
|
||||
decryptedSubjectBytes := clientKeyStore.DecryptMessageContent(senderCert, message.Subject)
|
||||
subject = Unmarshal(decryptedSubjectBytes)
|
||||
} else {
|
||||
subject = ""
|
||||
}
|
||||
clientMessage := newClientMessageInfo(message.Num, message.FromUID, subject, message.Timestamp)
|
||||
clientMessages = append(clientMessages, clientMessage)
|
||||
if !ok {
|
||||
clientMessageInfo = newClientMessageInfo(message.Num,
|
||||
message.FromUID,
|
||||
"",
|
||||
message.Timestamp,
|
||||
errors.New("certificate needed to decrypt not received"))
|
||||
clientMessages = append(clientMessages, clientMessageInfo)
|
||||
continue
|
||||
}
|
||||
decryptedSubjectBytes, err := clientKeyStore.DecryptMessageContent(senderCert, message.Subject)
|
||||
if err != nil {
|
||||
clientMessageInfo = newClientMessageInfo(message.Num, message.FromUID, "", message.Timestamp, err)
|
||||
clientMessages = append(clientMessages, clientMessageInfo)
|
||||
continue
|
||||
}
|
||||
subject, err := Unmarshal(decryptedSubjectBytes)
|
||||
if err != nil {
|
||||
clientMessageInfo = newClientMessageInfo(message.Num, message.FromUID, "", message.Timestamp, err)
|
||||
clientMessages = append(clientMessages, clientMessageInfo)
|
||||
continue
|
||||
}
|
||||
clientMessageInfo = newClientMessageInfo(message.Num, message.FromUID, subject, message.Timestamp, nil)
|
||||
clientMessages = append(clientMessages, clientMessageInfo)
|
||||
}
|
||||
//Sort the messages
|
||||
sort.Slice(clientMessages, func(i, j int) bool {
|
||||
|
@ -200,10 +303,10 @@ func askQueue(cl networking.Client[protocol.Packet], clientKeyStore cryptoUtils.
|
|||
action := showMessagesInfo(unreadMsgsInfo.Page, unreadMsgsInfo.NumPages, clientMessages)
|
||||
switch action {
|
||||
case -1:
|
||||
askQueue(cl, clientKeyStore, max(1, unreadMsgsInfo.Page-1), pageSize)
|
||||
case 0:
|
||||
return
|
||||
return askQueueRec(cl, clientKeyStore, max(1, unreadMsgsInfo.Page-1), pageSize)
|
||||
case 1:
|
||||
askQueue(cl, clientKeyStore, max(1, unreadMsgsInfo.Page+1), pageSize)
|
||||
return askQueueRec(cl, clientKeyStore, max(1, unreadMsgsInfo.Page+1), pageSize)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue