zsm

Zen Secure Messaging
git clone https://codeberg.org/night0721/zsm
Log | Files | Refs | README | LICENSE

server.c (6199B)


      1 #include "packet.h"
      2 #include "notification.h"
      3 #include <pthread.h>
      4 
      5 socklen_t clilen;
      6 struct sockaddr_in cli_address;
      7 uint8_t shared_key[SHARED_KEY_SIZE];
      8 int clientfd;
      9 
     10 /*
     11  * Initialise socket server
     12  */
     13 int socket_init()
     14 {
     15     int serverfd = socket(AF_INET, SOCK_STREAM, 0);
     16     if (serverfd < 0) {
     17         error(1, "Error on opening socket");
     18     }
     19 
     20     /* Reuse addr(for debug) */
     21     int optval = 1;
     22     if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0) {
     23 
     24         error(1, "Error at setting SO_REUSEADDR");
     25     }
     26 
     27     struct sockaddr_in sv_addr;
     28     memset(&sv_addr, 0, sizeof(sv_addr));
     29     sv_addr.sin_family = AF_INET;
     30     sv_addr.sin_addr.s_addr = INADDR_ANY;
     31     sv_addr.sin_port = htons(PORT);
     32 
     33     if (bind(serverfd, (struct sockaddr *) &sv_addr, sizeof(sv_addr)) < 0) {
     34         error(1, "Error on bind");
     35     }
     36 
     37     if (listen(serverfd, MAX_CONNECTION) < 0) {
     38         error(1, "Error on listen");
     39     }
     40 
     41     printf("Listening on port %d\n", PORT);
     42     clilen = sizeof(cli_address);
     43     return serverfd;
     44 }
     45 
     46 /*
     47  * Performs key exchange with client
     48  */
     49 int key_exchange(int clientfd)
     50 {
     51     /* Generate the server's key pair */
     52     uint8_t sv_pk[PUBLIC_KEY_SIZE], sv_sk[PRIVATE_KEY_SIZE];
     53     crypto_kx_keypair(sv_pk, sv_sk);
     54     
     55     /* Get public key from client */
     56     uint8_t *pk;
     57     if ((pk = get_public_key(clientfd)) == NULL) {
     58         return -1;
     59     }
     60    
     61     /* Send our public key */
     62     if (send_public_key(clientfd, sv_pk) < 0) {
     63         free(pk);
     64         return -1;
     65     }
     66 
     67     /* Compute a shared key using the client's public key and our secret key. */
     68     if (crypto_kx_server_session_keys(NULL, shared_key, sv_pk, sv_sk, pk) != 0) {
     69         error(0, "Client public key is not acceptable");
     70         free(pk);
     71         close(clientfd);
     72         return -1;
     73     }
     74 
     75     free(pk);
     76     return 0;
     77 }
     78 
     79 void signal_handler(int signal)
     80 {
     81     switch (signal) {
     82         case SIGPIPE:
     83             error(0, "SIGPIPE received");
     84             break;
     85         case SIGABRT:
     86         case SIGINT:
     87         case SIGTERM:
     88             notify_uninit();
     89             error(1, "Shutdown signal received");
     90             break;
     91     }
     92 }
     93 
     94 void *receiver()
     95 {
     96     int serverfd = socket_init();
     97     clientfd = accept(serverfd, (struct sockaddr *) &cli_address, &clilen);
     98     if (clientfd < 0) {
     99         error(0, "Error on accepting client");
    100         /* Continue accpeting connections */
    101 /*         continue; */
    102     }
    103 
    104     if (key_exchange(clientfd) < 0) {
    105         error(0, "Error performing key exchange with client");
    106 /*         continue; */
    107     }
    108     while (1) {
    109         message msg;
    110         memset(&msg, 0, sizeof(msg));
    111         if (recv_packet(&msg, clientfd) != ZSM_STA_SUCCESS) {
    112             close(clientfd);
    113             break;
    114 /*             continue; */
    115         }
    116         
    117         size_t encrypted_len = msg.length - NONCE_SIZE;
    118         size_t msg_len = encrypted_len - ADDITIONAL_SIZE;
    119         uint8_t nonce[NONCE_SIZE];
    120         uint8_t encrypted[encrypted_len];
    121         uint8_t decrypted[msg_len + 1];
    122         unsigned long long decrypted_len;
    123         memcpy(nonce, msg.data, NONCE_SIZE);
    124         memcpy(encrypted, msg.data + NONCE_SIZE, encrypted_len);
    125         
    126         free(msg.data);
    127         if (crypto_aead_xchacha20poly1305_ietf_decrypt(decrypted, &decrypted_len,
    128                                                             NULL,
    129                                                             encrypted, encrypted_len,
    130                                                             NULL, 0,
    131                                                             nonce, shared_key) != 0) {
    132             error(0, "Cannot decrypt message");
    133         } else {
    134             /* Decrypted message */
    135             decrypted[msg_len] = '\0';
    136             printf("Decrypted: %s\n", decrypted);
    137             send_notification(decrypted);
    138             msg.data = malloc(14);
    139             strcpy(msg.data, "Received data");
    140             msg.length = 14;
    141             send_packet(&msg, clientfd);
    142             free(msg.data);
    143         }
    144     }
    145     close(clientfd);
    146     close(serverfd);
    147     return NULL;
    148 }
    149 
    150 void *sender()
    151 {
    152     while (1) {
    153         printf("Enter message to send to client: ");
    154         fflush(stdout);
    155         char line[1024];
    156         line[0] = '\0';
    157         size_t length = strlen(line);
    158         while (length <= 1) {
    159             fgets(line, sizeof(line), stdin);
    160             length = strlen(line);
    161         }
    162         length -= 1;
    163         line[length] = '\0';
    164 
    165         uint8_t nonce[NONCE_SIZE];
    166         uint8_t encrypted[length + ADDITIONAL_SIZE];
    167         unsigned long long encrypted_len;
    168         
    169         randombytes_buf(nonce, sizeof(nonce));
    170         crypto_aead_xchacha20poly1305_ietf_encrypt(encrypted, &encrypted_len,
    171                                                    line, length,
    172                                                    NULL, 0, NULL, nonce, shared_key);
    173         size_t payload_t = NONCE_SIZE + encrypted_len; 
    174         uint8_t encryptedwithnonce[payload_t];
    175         memcpy(encryptedwithnonce, nonce, NONCE_SIZE);
    176         memcpy(encryptedwithnonce + NONCE_SIZE, encrypted, encrypted_len);
    177         
    178         message *msg = create_packet(1, 0x10, payload_t, encryptedwithnonce);
    179         if (send_packet(msg, clientfd) != ZSM_STA_SUCCESS) {
    180             close(clientfd);
    181         }
    182         free_packet(msg);
    183     }
    184     close(clientfd);
    185     return NULL;
    186 }
    187 
    188 int main()
    189 {
    190     if (sodium_init() < 0) {
    191         error(1, "Error initializing libsodium");
    192     }
    193     /* Init libnotify with app name */
    194     if (notify_init("zsm") < 0) {
    195         error(1, "Error initializing libnotify");
    196     }
    197     signal(SIGPIPE, signal_handler);
    198     signal(SIGABRT, signal_handler);
    199 	signal(SIGINT, signal_handler);
    200 	signal(SIGTERM, signal_handler);
    201     
    202     pthread_t recv_worker, send_worker;
    203     if (pthread_create(&recv_worker, NULL, sender, NULL) != 0) {
    204         fprintf(stderr, "Error creating incoming thread\n");
    205         return 1;
    206     }
    207 
    208     if (pthread_create(&send_worker, NULL, receiver, NULL) != 0) {
    209         fprintf(stderr, "Error creating outgoing thread\n");
    210         return 1;
    211     }
    212 
    213     // Join threads
    214     pthread_join(recv_worker, NULL);
    215     pthread_join(send_worker, NULL);
    216 
    217     return 0;
    218 }