#include #include #include //#include #include #include #include #include #include #include #include #include #include #include "ds.h" int openSslLoaded = 0; void *clear(void *ptr){ int e = errno; if(ptr){ free(ptr); } errno = e; return NULL; } void loadOpenSSL(){ if(!openSslLoaded){ openSslLoaded = 1; SSL_load_error_strings(); ERR_load_BIO_strings(); ERR_load_crypto_strings(); SSL_library_init(); OpenSSL_add_all_algorithms(); } } void copy6addr(unsigned char d[16], const unsigned char s[16]){ int i; for(i = 0; i < 16; i++) d[i] = s[i]; } void zero6addr(unsigned char d[16]){ int i; for(i = 0; i < 16; i++) d[i] = 0; } nethandler getNethandler(const int ipv6, const int port){ nethandler h = (nethandler)malloc(sizeof(s_nethandler)); h->ipv6 = ipv6; if(ipv6){ h->s = socket(AF_INET6, SOCK_STREAM, 0); }else{ h->s = socket(AF_INET, SOCK_STREAM, 0); } int optval = 1; setsockopt(h->s, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); int e, en; if(ipv6){ struct sockaddr_in6 add; add.sin6_family = AF_INET6; zero6addr(add.sin6_addr.s6_addr); add.sin6_port = htons(port); e = bind(h->s, (struct sockaddr*) &add, sizeof(add)); }else{ struct sockaddr_in add; add.sin_family = AF_INET; add.sin_addr.s_addr = INADDR_ANY; add.sin_port = htons(port); e = bind(h->s, (struct sockaddr*) &add, sizeof(add)); } if(e) return clear(h); e = listen(h->s, DEFAULT_LISTENNING_QUEUE); if(e) return clear(h); return h; } nethandler getIPv4Port(const int port){ return getNethandler(0, port); } nethandler getPort(const int port){ return getNethandler(1, port); } fileDs createFromFile(int f){ fileDs d = (fileDs)malloc(sizeof(s_fileDs)); d->f = f; return d; } fileDs createFromFileName(const char *f){ int fd = open(f, O_CREAT | O_RDWR); if(fd == -1){ return NULL; } return createFromFile(fd); } sockDs createFromHandler(nethandler h){ sockDs d = (sockDs)malloc(sizeof(s_sockDs)); unsigned int s = sizeof(d->peer); d->s = accept(h->s, (struct sockaddr*)&(d->peer), &s); if(d->s <= 0) return clear(d); d->ipv6 = d->peer.ss_family == AF_INET6; d->server = 1; return d; } sockDs createToHost(struct sockaddr *add, const int add_size, const int ipv6){ sockDs d = (sockDs)malloc(sizeof(s_sockDs)); if(ipv6){ d->s = socket(AF_INET6, SOCK_STREAM, 0); }else{ d->s = socket(AF_INET, SOCK_STREAM, 0); } if(connect(d->s, add, add_size) < 0){ int e = errno; free(d); errno = e; return NULL; } d->server = 0; return d; } sockDs createToIPv4Host(const unsigned long host, const int port){ struct sockaddr_in add; add.sin_family = AF_INET; add.sin_port = htons(port); add.sin_addr.s_addr = host; return createToHost((struct sockaddr*) &add, sizeof(add), 0); } sockDs createToIPv6Host(const unsigned char host[16], const int port){ struct sockaddr_in6 add; add.sin6_family = AF_INET6; add.sin6_port = htons(port); add.sin6_flowinfo = 0; copy6addr(add.sin6_addr.s6_addr, host); add.sin6_scope_id = 0; return createToHost((struct sockaddr*) &add, sizeof(add), 1); } int getPeer(sockDs d, unsigned long *ipv4peer, unsigned char ipv6peer[16], int *ipv6){ int port = 0; struct sockaddr_storage peer; int peer_size = sizeof(peer); if(getpeername(d->s, (struct sockaddr*)&peer, &peer_size)){ return 0; } if(peer.ss_family == AF_INET){ struct sockaddr_in *a = (struct sockaddr_in*)&(peer); zero6addr(ipv6peer); *ipv6 = -1; *ipv4peer = a->sin_addr.s_addr; port = a->sin_port; }else{ struct sockaddr_in6 *a = (struct sockaddr_in6*)&(peer); *ipv4peer = 0; *ipv6 = 1; copy6addr(ipv6peer, a->sin6_addr.s6_addr); port = a->sin6_port; } return port; } int fileDsSend(fileDs d, const char *b, const int s){ return write(d->f, b, s); } int sockDsSend(sockDs d, const char *b, const int s){ return write(d->s, b, s); } int tlsDsSend(tlsDs d, const char *b, const int s){ return SSL_write(d->s, b, s); } int stdDsSend(const char *b, const int s){ return write(1, b, s); } int fileDsRecv(fileDs d, char *b, const int s){ return read(d->f, b, s); } int sockDsRecv(sockDs d, char *b, const int s){ return read(d->s, b, s); } int tlsDsRecv(tlsDs d, char *b, const int s){ return SSL_read(d->s, b, s); } int stdDsRecv(char *b, const int s){ return read(0, b, s); } void closeFileDs(fileDs d){ close(d->f); free(d); } void closeSockDs(sockDs d){ close(d->s); free(d); } void closeTlsDs(tlsDs d){ SSL_shutdown(d->s); SSL_shutdown(d->s); SSL_free(d->s); switch(d->tp){ case file: closeFileDs(d->original); break; case sock: closeSockDs(d->original); break; } free(d); } void closeHandler(nethandler h){ close(h->s); free(h); } tlsDs startSockTls(sockDs d, const char *cert, const char *key){ loadOpenSSL(); SSL_CTX * ctx = NULL; if(d->server) ctx = SSL_CTX_new(TLSv1_server_method()); else ctx = SSL_CTX_new(TLSv1_client_method()); if(!ctx) return NULL; SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE); if(cert) if(SSL_CTX_use_certificate_chain_file(ctx, cert) != 1){ closeSockDs(d); return clear(ctx); } if(key) if(SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM) != 1){ closeSockDs(d); return clear(ctx); } tlsDs t = (tlsDs)malloc(sizeof(s_tlsDs)); t->original = d; if(!(t->s = SSL_new(ctx))){ closeSockDs(d); clear(ctx); return clear(t); } if(!SSL_set_fd(t->s, d->s)){ closeTlsDs(t); return NULL; } printf("Starting handshake\n"); int retry = 1; int e; while(retry){ retry = 0; if(d->server) e = SSL_accept(t->s); else e = SSL_connect(t->s); if(e <= 0){ retry = 1; int erval = SSL_get_error(t->s, e); if((erval == SSL_ERROR_WANT_READ) || (erval == SSL_ERROR_WANT_WRITE)){ }else{ printf("Error\n"); ERR_print_errors(t->s->bbio); closeTlsDs(t); return NULL; } } } printf("Success\n"); return t; }