/* ** get data from the client and return it ** run in a child process that was forked off from the main process. */ void process(int sock) { char buf[XIA_MAXBUF + 1]; int n; pid_t pid = getpid(); fd_set fds; FD_ZERO(&fds); FD_SET(sock, &fds); #ifdef USE_SELECT struct timeval tv; tv.tv_sec = WAIT_FOR_DATA; tv.tv_usec = 0; #endif while (1) { memset(buf, 0, sizeof(buf)); #ifdef USE_SELECT tv.tv_sec = WAIT_FOR_DATA; tv.tv_usec = 0; if ((n = Xselect(sock + 1, &fds, NULL, NULL, &tv)) < 0) { warn("%5d Select failed, closing...\n", pid); break; } else if (n == 0) { // we timed out, close the socket say("%5d timed out on recv\n", pid); break; } else if (!FD_ISSET(sock, &fds)) { // this shouldn't happen! die(-4, "something is really wrong, exiting\n"); } #endif if ((n = Xrecv(sock, buf, sizeof(buf), 0)) < 0) { warn("Recv error on socket %d, closing connection\n", pid); break; } else if (n == 0) { warn("%d client closed the connection\n", pid); break; } say("%5d received %d bytes\n", pid, n); if ((n = Xsend(sock, buf, n, 0)) < 0) { warn("%5d send error\n", pid); break; } say("%5d sent %d bytes\n", pid, n); } say("%5d closing\n", pid); Xclose(sock); }
int getChunkCount(int sock, char *reply, int sz) { int n; if ((n = Xrecv(sock, reply, sz, 0)) < 0) { Xclose(sock); die(-1, "Unable to communicate with the server\n"); } if (strncmp(reply, "OK:", 3) != 0) { die(-1, "%s\n", reply); } reply[n] = 0; return n; }
int main(int argc, char **argv) { struct addrinfo *ai; sockaddr_x *sa; int seq = 0; // FIXME: put signal handlers back into code once Xselect is working // signal(SIGINT, handler); // signal(SIGTERM, handler); getConfig(argc, argv); if (Xgetaddrinfo(NAME, NULL, NULL, &ai) < 0) die("Unable to lookup address for %s\n", NAME); sa = (sockaddr_x*)ai->ai_addr; if ((sock = Xsocket(AF_XIA, SOCK_STREAM, 0)) < 0) die("Unable to create a socket\n"); say("Opening firehose: %s\n", NAME); if (Xconnect(sock, (struct sockaddr*)sa, sizeof(sockaddr_x)) < 0) { Xclose(sock); die("Unable to connect to %s\n", NAME); } // tell firehose how many packets we expect if (Xsend(sock, &fhc, sizeof(fhc), 0) < 0) { Xclose(sock); die("Unable to send config information to the firehose\n"); } int count = 0; char *buf = (char *)malloc(pktSize); while (!timetodie) { int n; fd_set fds; FD_ZERO(&fds); FD_SET(sock, &fds); struct timeval tv; tv.tv_sec = 2; tv.tv_usec = 0; if ((n = Xselect(sock + 1, &fds, NULL, NULL, &tv)) < 0) { printf("select failed\n"); break; } else if (n == 0) { printf("recv timeout\n"); break; } else if (!FD_ISSET(sock, &fds)) { // this shouldn't happen! printf("something is really wrong, exiting\n"); break; } int rc = Xrecv(sock, buf, sizeof(buf), 0); if (rc < 0) die("Receive failure\n"); memcpy(&seq, buf, sizeof(int)); say("expecting %d, got %d", count, seq); if (count == seq) say("\n"); else say(" lost %d\n", seq - count); count++; if (count == numPkts) break; if (delay) usleep(delay); } seq++; if (count != seq) printf("lost %d packets, received %d, expected %d\n", seq - count, count, seq); else printf("success!\n"); Xclose(sock); }
void *recvCmd (void *socketid) { int i, n, count = 0; ChunkInfo *info = NULL; char command[XIA_MAXBUF]; char reply[XIA_MAXBUF]; int sock = *((int*)socketid); char *fname; //ChunkContext contains size, ttl, policy, and contextID which for now is PID ChunkContext *ctx = XallocCacheSlice(POLICY_FIFO|POLICY_REMOVE_ON_EXIT, 0, 20000000); if (ctx == NULL) die(-2, "Unable to initilize the chunking system\n"); while (1) { say("waiting for server command\n"); memset(command, '\0', strlen(command)); memset(reply, '\0', strlen(reply)); if ((n = Xrecv(sock, command, 1024, 0)) < 0) { warn("socket error while waiting for data, closing connection\n"); break; } //Sender does the chunking and then should start the sending commands if (strncmp(command, "get", 3) == 0) { fname = &command[4]; say("Server requested file %s\n", fname); if (info) { // clean up the existing chunks first } info = NULL; count = 0; say("chunking file %s\n", fname); //Chunking is done by the XputFile which itself uses XputChunk, and fills out the info if ((count = XputFile(ctx, fname, CHUNKSIZE, &info)) < 0) { warn("unable to serve the file: %s\n", fname); sprintf(reply, "FAIL: File (%s) not found", fname); } else { sprintf(reply, "OK: %d", count); } say("%s\n", reply); //Just tells the receiver how many chunks it should expect. if (Xsend(sock, reply, strlen(reply), 0) < 0) { warn("unable to send reply to client\n"); break; } //Sending the blocks cids } else if (strncmp(command, "block", 5) == 0) { char *start = &command[6]; char *end = strchr(start, ':'); if (!end) { // we have an invalid command, return error to client sprintf(reply, "FAIL: invalid block command"); } else { *end = 0; end++; // FIXME: clean up naming, e is now a count int s = atoi(start); int e = s + atoi(end); strcpy(reply, "OK:"); for(i = s; i < e && i < count; i++) { strcat(reply, " "); strcat(reply, info[i].cid); } } printf("%s\n", reply); if (Xsend(sock, reply, strlen(reply), 0) < 0) { warn("unable to send reply to client\n"); break; } } else if (strncmp(command, "done", 4) == 0) { say("done sending file: removing the chunks from the cache\n"); for (int i = 0; i < count; i++) XremoveChunk(ctx, info[i].cid); XfreeChunkInfo(info); info = NULL; count = 0; break; } else { sprintf(reply, "FAIL: invalid command (%s)\n", command); warn(reply); if (Xsend(sock, reply, strlen(reply), 0) < 0) { warn("unable to send reply to client\n"); break; } } } if (info) XfreeChunkInfo(info); XfreeCacheSlice(ctx); return (void *)1; }
/** * @brief Initiate an XSSL connection with server. * * @param xssl * * @return 1 on success, <1 on failure */ int XSSL_connect(XSSL *xssl) { char buf[XIA_MAXBUF]; int n; /* Send CLIENT HELLO */ sprintf(buf, "CLIENT HELLO"); if ((n = Xsend(xssl->sockfd, buf, strlen(buf), 0)) != strlen(buf)) { ERROR("ERROR sending CLIENT HELLO"); return 0; } /* Wait for SERVER HELLO */ // Receive public key + temporary public key signed by server's long-term private key // Continue receiving until we see "SERVER DONE" int offset = 0; while ( offset < 11 || strcmp("SERVER DONE", &buf[offset-11]) != 0 ) { n = Xrecv(xssl->sockfd, &buf[offset], sizeof(buf)-offset, 0); if (n < 0) { ERROR("ERROR receiving SERVER HELLO"); return n; } if (n == 0) { ERROR("ERROR: server closed connection during SERVER HELLO"); return n; } offset += n; } /* Parse public keys from SERVER HELLO */ offset = strlen("SERVER HELLO"); char *keys = &buf[offset]; // start of signed portion of message uint32_t *keybufsizeptr = (uint32_t*)&buf[offset]; uint32_t keybufsize = *keybufsizeptr; // TODO: error checking here offset += sizeof(uint32_t); RSA *pubkey = deserialize_rsa_pub_key(&buf[offset], keybufsize); offset += keybufsize; uint32_t *tempkeybufsizeptr = (uint32_t*)&buf[offset]; uint32_t tempkeybufsize = *tempkeybufsizeptr; offset += sizeof(uint32_t); RSA *sessionPubkey = deserialize_rsa_pub_key(&buf[offset], tempkeybufsize); offset += tempkeybufsize; uint32_t *siglenptr = (uint32_t*)&buf[offset]; uint32_t siglen = *siglenptr; offset += sizeof(uint32_t); char* sig = &buf[offset]; offset += siglen; DBGF("Received keys:\n\tkeylen: %d\n\ttempkeylen: %d\n\tsiglen: %d", keybufsize, tempkeybufsize, siglen); /* Verify two things: * 1) hash(key) == SID so we trust the signature * 2) verify the sig so we trust the temp key */ sockaddr_x *sa = (sockaddr_x*)malloc(sizeof(sockaddr_x)); socklen_t len = sizeof(sockaddr_x); if (Xgetpeername(xssl->sockfd, (struct sockaddr*)sa, &len) < 0) { ERRORF("Error in Xgetpeername on socket %d: %s", xssl->sockfd, strerror(errno)); return 0; } Graph g(sa); Node sid_node = g.get_final_intent(); DBGF("SID: %s", sid_node.to_string().c_str()); char *sid_from_key_hash = SID_from_keypair(pubkey); DBGF("Pub key hash: %s", sid_from_key_hash); if (strcmp(sid_node.to_string().c_str(), sid_from_key_hash) != 0) { WARN("Hash of received public key does not match SID! Closing connection."); return 0; } if (verify(pubkey, keys, keybufsize+tempkeybufsize+2*sizeof(uint32_t), sig, siglen) != 1) { WARN("Unable to verify signature on temporary RSA keypair! Closing connection."); return 0; } /* Generate pre-master secret and send to server, encrypted with sessionPubKey */ unsigned char* pms = (unsigned char*)malloc(PRE_MASTER_SECRET_LENGTH); if (RAND_bytes(pms, PRE_MASTER_SECRET_LENGTH) != 1) { ERROR("ERROR: Couldn't generate pre-master secret"); return 0; } if (VERBOSITY >= V_DEBUG) { DBG("Pre-Master Secret:"); print_bytes(pms, PRE_MASTER_SECRET_LENGTH); } int ciphertext_len; if ( (ciphertext_len = pub_encrypt(sessionPubkey, pms, PRE_MASTER_SECRET_LENGTH, buf, XIA_MAXBUF)) == -1 ) { ERROR("ERROR: Unable to encrypt session key"); return 0; } n = 0; offset = 0; while (offset < ciphertext_len) { if ((n = Xsend(xssl->sockfd, &buf[offset], ciphertext_len-offset, 0)) < 0) { ERROR("ERROR sending pre-master secret"); return 0; } offset += n; } /* Init symmetric session ciphers with pre-master secret. Client encrypt context initialized with same key data as server decrypt context and vice versa. */ uint32_t salt[] = SALT; if (aes_init(pms, PRE_MASTER_SECRET_LENGTH/2, &pms[PRE_MASTER_SECRET_LENGTH/2], PRE_MASTER_SECRET_LENGTH/2, (unsigned char *)&salt, xssl->en, xssl->de)) { ERROR("ERROR initializing AES ciphers"); return 0; } free(pms); /* For now, omitting CLIENT DONE */ return 1; }
void process(int peer) { fhConfig fhc; char *buf = NULL; uint32_t count = 0; int n; signal(SIGINT, handler); fd_set fds; FD_ZERO(&fds); FD_SET(peer, &fds); struct timeval tv; tv.tv_sec = 5; tv.tv_usec = 0; n = Xselect(peer + 1, &fds, NULL, NULL, &tv); if (n < 0) { printf("select failed\n"); goto done; } else if (n == 0) { printf("recv timeout\n"); goto done; } else if (!FD_ISSET(peer, &fds)) { // this shouldn't happen! printf("something is really wrong, exiting\n"); goto done; } if (Xrecv(peer, &fhc, sizeof(fhc), 0) < 0) { printf("Unable to get configuration block\n"); goto done; } fhc.numPkts = ntohl(fhc.numPkts); fhc.delay = ntohl(fhc.delay); fhc.pktSize = ntohl(fhc.pktSize); // need to have at least enough room for the sequence # fhc.pktSize = MAX(fhc.pktSize, sizeof(unsigned)); if (fhc.numPkts == 0) say("packet count = non-stop\n"); else say("packet count = %d\n", fhc.numPkts); say("packet size = %d\n", fhc.pktSize); say("inter-packet delay = %d\n", fhc.delay); if (!(buf = (char *)malloc(fhc.pktSize))) { printf("Memory error\n"); goto done; } while (!timetodie) { if (fhc.numPkts > 0 && count == fhc.numPkts) break; printf("sending packet %d\n", count); data(count, buf, sizeof(buf)); Xsend(peer, buf, sizeof(buf), 0); count++; if (fhc.delay != 0) usleep(fhc.delay); } done: say("done\n"); if (buf) free(buf); Xclose(peer); }