sodiumTest

Libsodium examples, client/server system
git clone https://noulin.net/git/sodiumTest.git
Log | Files | Refs | README

server3.c (5423B)


      1 #! /usr/bin/env sheepy
      2 
      3 #include "libsheepyObject.h"
      4 
      5 #include <sys/socket.h>
      6 #include <netinet/in.h>
      7 
      8 #include "sel.h"
      9 #include "bloom.h"
     10 
     11 int main(int ac, char **av){
     12 
     13   setLogMode(LOG_FUNC);
     14 
     15   if (not selInit()) ret 1;
     16 
     17   // initialize bloomfilter for 45 million sessions, 10% false positive
     18   struct bloom bloom;
     19   u32 filterCount = 0;
     20   bloom_init2(&bloom, 45000000, 0.1);
     21 
     22   // generate id keys
     23   newSignKeys();
     24 
     25 
     26   // start event loop
     27   int sock;
     28   struct sockaddr_in server;
     29   int mysock;
     30   char buf[128*1024];
     31   int rval;
     32 
     33   sock = socket(AF_INET, SOCK_STREAM, 0);
     34   if (sock < 0){
     35     perror("Failed to create socket");
     36     ret 1;
     37   }
     38 
     39   server.sin_family = AF_INET;
     40   server.sin_addr.s_addr = INADDR_ANY;
     41   server.sin_port = htons(5000);
     42 
     43   if (bind(sock, (struct sockaddr *) &server, sizeof(server))){
     44     perror("bind failed");
     45     ret 1;
     46   }
     47 
     48   listen(sock, 5);
     49 
     50   logI("Server started");
     51   forever {
     52     mysock = accept(sock, (struct sockaddr *)0, 0);
     53     if (mysock == -1)
     54       perror("accept failed");
     55     else {
     56 
     57       bool snd(void *buf, size_t sz) {
     58         logVarG(sz);
     59         if(send(mysock, buf, sz, 0) < 0){
     60           perror("send failed");
     61           close(mysock);
     62           ret no;
     63         }
     64         ret yes;
     65       }
     66 
     67       bool rcv(void *buf, size_t sz) {
     68         while (sz > 0) {
     69           // TODO add timeout
     70           rval = recv(mysock, buf, sz, MSG_WAITALL);
     71           if (rval < 0) {
     72             perror("reading message");
     73             ret no;
     74           }
     75           else if (rval == 0) {
     76             logI("Ending connection");
     77             close(mysock);
     78             ret no;
     79           }
     80           sz -= rval;
     81         }
     82         ret yes;
     83       }
     84 
     85       // public key for session
     86       newKeys();
     87 	    randombytes_buf(sessionKeys.nonce, sizeof(sessionKeys.nonce));
     88 
     89       // store remote public key
     90       u8 clientInfo[crypto_sign_BYTES + crypto_sign_PUBLICKEYBYTES + sizeof(keys.remotePublicKey)] = init0Var;
     91       rcv(clientInfo, sizeof(clientInfo));
     92 
     93       // check if the clientInfo is signed
     94       bool is0 = yes;
     95       range(i, crypto_sign_BYTES + crypto_sign_PUBLICKEYBYTES) {
     96         if (clientInfo[i]) {
     97           is0 = no;
     98           break;
     99         }
    100       }
    101 
    102       if (is0) {
    103         logN("Client id not checked");
    104       }
    105       else {
    106         // check client
    107         // id key should already be known
    108         u8 unsigned_message[crypto_sign_PUBLICKEYBYTES + sizeof(keys.remotePublicKey)] = init0Var;
    109         unsigned long long unsigned_message_len;
    110 
    111         if (crypto_sign_open(unsigned_message, &unsigned_message_len, clientInfo, sizeof(clientInfo), clientInfo + crypto_sign_BYTES) != 0) {
    112           logE("Incorrect signature!");
    113         }
    114         else {
    115           logP("Correct client signature");
    116         }
    117       }
    118 
    119       memcpy(keys.remotePublicKey, clientInfo + crypto_sign_BYTES + crypto_sign_PUBLICKEYBYTES, sizeof(keys.remotePublicKey));
    120 
    121       // check if key is in bloom filter
    122       if (filterCount == bloom.entries) {
    123         logD("Reseting bloom filter");
    124         bloom_reset(&bloom);
    125         filterCount = 0;
    126       }
    127       int bfr = bloom_check(&bloom, keys.remotePublicKey, sizeof(keys.remotePublicKey));
    128       if (bfr == -1) {
    129         logE("Bloom filter is not initialized");
    130       }
    131       elif (bfr == 1) {
    132         logI("Client key already is already in bloom filter, request a new key");
    133       }
    134       elif (bfr == 0) {
    135         // if not add it to the bloom filter
    136         bloom_add(&bloom, keys.remotePublicKey, sizeof(keys.remotePublicKey));
    137         inc filterCount;
    138       }
    139 
    140       logD("Remote public key");
    141       loghex(keys.remotePublicKey, sizeof(keys.remotePublicKey));
    142       put;
    143 
    144       // send public key
    145       u8 exchange[crypto_sign_PUBLICKEYBYTES + sizeof(keys.publicKey) + crypto_box_NONCEBYTES] = init0Var;
    146       u8 signed_message[crypto_sign_BYTES + sizeof(exchange)] = init0Var;
    147       unsigned long long signed_message_len = 0;
    148 
    149       memcpy(exchange, identityKeys.publicKey, crypto_sign_PUBLICKEYBYTES);
    150       memcpy(exchange + crypto_sign_PUBLICKEYBYTES, keys.publicKey, sizeof(keys.publicKey));
    151       memcpy(exchange + crypto_sign_PUBLICKEYBYTES + sizeof(keys.publicKey), sessionKeys.nonce, sizeof(sessionKeys.nonce));
    152 
    153       crypto_sign(signed_message, &signed_message_len, exchange, sizeof(exchange), identityKeys.secretKey);
    154 
    155       if (!snd(signed_message, sizeof(signed_message))) continue;
    156 
    157       // key exchange
    158       if (not computeSharedKeys(SERVER_SESSION_KEYS)) {
    159         logE("Invalid client key");
    160         exit(1);
    161       }
    162 
    163       // get encrypted message
    164       int len;
    165       // *nonce is incremented by after sending or receiving a message
    166       // *nonce is allowed to wrap from the max value
    167       u64 *nonce = (u64*)sessionKeys.nonce;
    168       if (!rcv(&len, sizeof(len))) continue;
    169       rcv(buf, len);
    170 
    171       u8 decrypted[1000];
    172       logVarG(*nonce);
    173       len = selDecrypt(decrypted, sizeof(decrypted), buf, len);
    174       inc *nonce;
    175 
    176       if (!len) {
    177         logE("failed to decrypt");
    178         close(mysock);
    179         continue;
    180       }
    181 
    182       decrypted[len] = 0;
    183 
    184       logI("decrypted: %s", decrypted);
    185 
    186       // send encrypted response
    187 
    188       char *msg = "OK";
    189 
    190       logVarG(*nonce);
    191       len = selEncrypt(buf, sizeof(buf), msg, strlen(msg));
    192       inc *nonce;
    193 
    194       logVarG(len);
    195 
    196       snd(&len, sizeof(len));
    197       snd(buf, len);
    198 
    199       close(mysock);
    200     }
    201   }
    202   bloom_free(&bloom);
    203 }
    204 // vim: set expandtab ts=2 sw=2: