#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->fd = socket(AF_INET6, SOCK_STREAM, 0); }else{ h->fd = socket(AF_INET, SOCK_STREAM, 0); } int optval = 1; setsockopt(h->fd, 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->fd, (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->fd, (struct sockaddr*) &add, sizeof(add)); } if(e) return clear(h); e = listen(h->fd, 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); } ds createFromFile(int f){ ds d = (ds)malloc(sizeof(s_ds)); d->tp = file; d->fd = f; return d; } ds createFromFileName(const char *f){ int fd = open(f, O_CREAT | O_RDWR); if(fd == -1){ return NULL; } return createFromFile(fd); } ds createFromHandler(nethandler h){ ds d = (ds)malloc(sizeof(s_ds)); d->tp = sock; unsigned int s = sizeof(d->peer); d->fd = accept(h->fd, (struct sockaddr*)&(d->peer), &s); if(d->fd <= 0) return clear(d); d->ipv6 = d->peer.ss_family == AF_INET6; d->server = 1; return d; } ds createToHost(struct sockaddr *add, const int add_size, const int ipv6){ ds d = (ds)malloc(sizeof(s_ds)); d->tp = sock; if(ipv6){ d->fd = socket(AF_INET6, SOCK_STREAM, 0); }else{ d->fd = socket(AF_INET, SOCK_STREAM, 0); } if(connect(d->fd, add, add_size) < 0){ int e = errno; free(d); errno = e; return NULL; } d->server = 0; return d; } ds 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); } ds 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(ds 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->fd, (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 sendDs(ds d, const char *b, const int s){ return write(d->fd, 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 recvDs(ds d, char *b, const int s){ return read(d->fd, 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); } int prepareToClose(ds d){ int fd = d->fd; free(d); return fd; } ds closeTlsDs(tlsDs d){ ds original = d->original; SSL_shutdown(d->s); SSL_shutdown(d->s); SSL_free(d->s); free(d); return original; } void closeHandler(nethandler h){ close(h->fd); free(h); } tlsDs startSockTls(ds 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){ int f = prepareToClose(d); closeFd(f); return clear(ctx); } if(key) if(SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM) != 1){ int f = prepareToClose(d); closeFd(f); return clear(ctx); } tlsDs t = (tlsDs)malloc(sizeof(s_tlsDs)); t->original = d; if(!(t->s = SSL_new(ctx))){ int f = prepareToClose(d); closeFd(f); clear(ctx); return clear(t); } if(!SSL_set_fd(t->s, d->fd)){ closeTlsDs(t); return NULL; } 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{ //ERR_print_errors(t->s->bbio); closeTlsDs(t); return NULL; } } } return t; } int getFd(ds d){ return d->fd; } void closeFd(int fd){ close(fd); }