Exemplo n.º 1
0
static int fill_urandom_buf(unsigned char *buf, size_t cnt)
{
        int crypto_fd;
        int ret = -1;

        crypto_fd = open("/dev/urandom", O_RDONLY);
        if (crypto_fd < 0)
                return crypto_fd;

        ret = insist_read(crypto_fd, buf, cnt);
        close(crypto_fd);

        return ret;
}
Exemplo n.º 2
0
void server(unsigned char * key) {

	char addrstr[INET_ADDRSTRLEN];
    	socklen_t len;
	int sd, yes = 1, sd_max, curr_sd, cfd, ret, newsd;

    	struct sockaddr_in sa;

	struct client *clients = NULL, *ptr = NULL, *ptr2 = NULL;
			
	ssize_t n;
	fd_set readfds, master;
	struct timeval tv;
	struct session_op sess;
        struct crypt_op cryp;
	struct crypt_data data ; 
	/* Make sure a broken connection doesn't kill us */
    	signal(SIGPIPE, SIG_IGN);
   	/* Create TCP/IP socket, used as main chat channel */
    	if ((sd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
       		perror("socket");
        	exit(1);
 	}
 	fprintf(stderr, "Created TCP socket\n");
	
	setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));

 	/* Bind to a well-known port */
   	memset(&sa, 0, sizeof(sa));
  	sa.sin_family = AF_INET;
   	sa.sin_port = htons(TCP_PORT);
  	sa.sin_addr.s_addr = htonl(INADDR_ANY);
   	if (bind(sd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
     		perror("bind");
       		exit(1);
  	}
 	fprintf(stderr, "Bound TCP socket to port %d\n", TCP_PORT);

  	/* Listen for incoming connections */
 	if (listen(sd, TCP_BACKLOG) < 0) {
     		perror("listen");
      		exit(1);
    	}	

	memset(&sess, 0, sizeof(sess));
        memset(&cryp, 0, sizeof(cryp));
	memset(data.in,'\0', BUF_SIZE);
	memset(data.encin,'\0', BUF_SIZE);
	memset(data.encout,'\0', BUF_SIZE);
	memset(data.decrypted,'\0', BUF_SIZE);

        cfd = open("/dev/cryptodev0", O_RDWR);
	if (cfd < 0) {
		perror("open(/dev/cryptodev0)");
		exit(1);
	}
	if (fill_urandom_buf(data.iv, BLOCK_SIZE) < 0) {
                perror("getting data from /dev/urandom\n");
                exit(1);
        }

	/*
         * Get crypto session for AES128
         */
        sess.cipher = CRYPTO_AES_CBC;
        sess.keylen = KEY_SIZE;
        sess.key = key;
        if (ioctl(cfd, CIOCGSESSION, &sess)) {
                perror("ioctl(CIOCGSESSION)");
                exit(1);
        }

	cryp.ses = sess.ses;
	cryp.len = sizeof(data.in);
        cryp.iv = data.iv;
	sd_max = sd; 
	/* Clear the reading and master set */
	FD_ZERO(&master);
	FD_ZERO(&readfds);

    	/* Add the proper file descriptors to sets */
    	FD_SET(sd, &master);

	for (;;) {
		/* Determine a timeout parameter */
		tv.tv_sec = 100;
        	tv.tv_usec = 0;

		readfds = master;
        	ret = select(sd_max+1, &readfds, NULL, NULL, &tv);

        	if (ret == -1) {
            		perror("select");
            		exit(1);
        	}	
        	else if (ret == 0) {
            		fprintf(stderr, "Timeout occured! No data after 1000 seconds!\n");
			printf("Attention server shutting down!\n");
			goto out;
        	}
		else {
			if (FD_ISSET(sd, &readfds)) {
				fprintf(stderr, "Waiting for an incoming connection...\n");
				/* Accept an incoming connection */
   				len = sizeof(struct sockaddr_in);
   				if ((newsd = accept(sd, (struct sockaddr *)&sa, &len)) < 0) {
       					perror("accept");
      					exit(1);
  				}
				if (!inet_ntop(AF_INET, &sa.sin_addr, addrstr, sizeof(addrstr))) {
    					perror("could not format IP address");
       					exit(1);
  				}

				printf("[%s:%d] logged in.\n", addrstr, ntohs(sa.sin_port));
                                snprintf((char *) data.in, BUF_SIZE, "[%s:%d]: logged in.\n", addrstr, ntohs(sa.sin_port));
				/* encrypt data.in to data.encin */
				encrypt_data(cfd,&cryp,&data);

                                for (ptr = clients; ptr != NULL; ptr = ptr->next) {
                                        n = insist_write(ptr->sd, data.encin, BUF_SIZE);
                                }

				memset(data.in,'\0', BUF_SIZE);
                                memset(data.encin,'\0', BUF_SIZE);

				if (newsd > sd_max)
					sd_max = newsd;
				FD_SET(newsd, &master);
				clients = insert(clients, newsd, addrstr, sa.sin_port);
			}
			else {
				for (ptr = clients; ptr != NULL; ptr = ptr->next) {
					if (FD_ISSET(ptr->sd, &readfds)) {
						curr_sd = ptr->sd;
						n = insist_read(curr_sd, data.encout, BUF_SIZE);
                				if (n < 0){
                    					perror("read from remote peer failed");
                    					exit(1);
                				}
                				if (n == 0) {
                    					printf("[%s:%d] logged out.\n", ptr->addr, ntohs(ptr->port));
							snprintf((char *) data.in, BUF_SIZE, "[%s:%d]: logged out.\n", ptr->addr, ntohs(ptr->port));
								
							encrypt_data(cfd,&cryp,&data);

							for (ptr2 = clients; ptr2 != NULL; ptr2=ptr2->next) {
								if (curr_sd != ptr2->sd) {
									n = insist_write(ptr2->sd, data.encin, BUF_SIZE);
								}								
							}
							memset(data.in,'\0', BUF_SIZE);
                                                        memset(data.encin,'\0', BUF_SIZE);
						
							FD_CLR(curr_sd, &master);
							clients = delete(clients, curr_sd);
							if (close(curr_sd) < 0) {
								perror("close");
								exit(1);
							}
							continue;
                				}
						if (n != BUF_SIZE) {
                                        		fprintf(stderr, "Unexpected short read!\n");
                                        		exit(1);
                                		}

						snprintf((char *) data.in, BUF_SIZE, "[%s:%d]: ", ptr->addr, ntohs(ptr->port));	
						encrypt_data(cfd,&cryp,&data);
						
						for (ptr2 = clients; ptr2 != NULL; ptr2=ptr2->next) {
							n = insist_write(ptr2->sd, data.encin, BUF_SIZE);
							n = insist_write(ptr2->sd, data.encout, BUF_SIZE);								
						}
						memset(data.in,'\0', BUF_SIZE);
                                                memset(data.encin,'\0', BUF_SIZE);
                                                memset(data.encout, '\0', BUF_SIZE);						
					}
				}
			}
		}
	}

 	if (close(sd) < 0) {
      		perror("close");
		exit(1);	
	}

out:
	if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
        	perror("ioctl(CIOCFSESSION)");
       		exit(1);
    	}

	exit(0);
}