Delete obsolete code for openssl-based test server See https://dev.eclipse.org/ipzilla/show_bug.cgi?id=10521#c15 and following. Change-Id: I5a2caf1c713ada011dfc6bb11b30401304a06f12
diff --git a/tests/secure-server.c b/tests/secure-server.c deleted file mode 100644 index 6ba5258..0000000 --- a/tests/secure-server.c +++ /dev/null
@@ -1,862 +0,0 @@ -/* secure-server -- A (broken) DTLS server example - * - * Copyright (C) 2011 Olaf Bergmann <bergmann@tzi.org> - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include <string.h> -#include <stdlib.h> -#include <unistd.h> -#include <fcntl.h> -#include <stdio.h> -#include <ctype.h> -#include <sys/select.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <netdb.h> -#include <sys/stat.h> -#include <errno.h> -#include <signal.h> - -#include <openssl/ssl.h> -#include <openssl/bio.h> -#include <openssl/err.h> -#include <openssl/rand.h> - -#ifdef WITH_DTLS -#define SERVER_CERT_PEM "./server-cert.pem" -#define SERVER_KEY_PEM "./server-key.pem" -#define CA_CERT_PEM "./ca-cert.pem" -#endif - -#ifdef HAVE_ASSERT_H -# include <assert.h> -#else -# define assert(x) -#endif /* HAVE_ASSERT_H */ - -static int quit=0; - -/* SIGINT handler: set quit to 1 for graceful termination */ -void -handle_sigint(int signum) { - quit = 1; -} - -int -check_connect(int sockfd, char *buf, int buflen, - struct sockaddr *src, int *ifindex) { - - /* for some reason, the definition in netinet/in.h is not exported */ -#ifndef IN6_PKTINFO - struct in6_pktinfo - { - struct in6_addr ipi6_addr; /* src/dst IPv6 address */ - unsigned int ipi6_ifindex; /* send/recv interface index */ - }; -#endif - - size_t bytes; - - struct iovec iov[1] = { {buf, buflen} }; - char cmsgbuf[CMSG_SPACE(sizeof(struct in6_pktinfo))]; - struct in6_pktinfo *p = NULL; - - struct msghdr msg = { 0 }; - struct cmsghdr *cmsg; - - msg.msg_name = src; - msg.msg_namelen = sizeof(struct sockaddr_in6); - msg.msg_iov = iov; - msg.msg_iovlen = 1; - msg.msg_control = cmsgbuf; - msg.msg_controllen = sizeof(cmsgbuf); - - bytes = recvmsg(sockfd, &msg, MSG_DONTWAIT | MSG_PEEK); - if (bytes < 0) { - perror("recvmsg"); - return bytes; - } - - /* TODO: handle msg.msg_flags & MSG_TRUNC */ - if (msg.msg_flags & MSG_CTRUNC) { - fprintf(stderr, "control was truncated!\n"); - return -1; - } - - if (ifindex) { - /* Here we try to retrieve the interface index where the packet was received */ - *ifindex = 0; - for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; - cmsg = CMSG_NXTHDR(&msg, cmsg)) { - - if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) { - p = (struct in6_pktinfo *)(CMSG_DATA(cmsg)); - *ifindex = p->ipi6_ifindex; - break; - } - } - } - - return bytes; -} - -typedef enum { UNKNOWN=0, DTLS=1 } protocol_t; - -protocol_t -demux_protocol(const char *buf, int len) { - return DTLS; -} - -#ifdef WITH_DTLS -typedef enum { - PEER_ST_ESTABLISHED, PEER_ST_PENDING, PEER_ST_CLOSED - } peer_state_t; -typedef struct { - peer_state_t state; - unsigned long h; - SSL *ssl; -} ssl_peer_t; - -#define MAX_SSL_PENDING 2 /* must be less than MAX_SSL_PEERS */ -#define MAX_SSL_PEERS 10 /* MAX_SSL_PENDING of these might be pending */ -ssl_peer_t *ssl_peer_storage[MAX_SSL_PEERS]; -static int pending = 0; - -void -check_peers() { -typedef struct bio_dgram_data_st - { - union { - struct sockaddr sa; - struct sockaddr_in sa_in; - struct sockaddr_in6 sa_in6; - } peer; - unsigned int connected; - unsigned int _errno; - unsigned int mtu; - struct timeval next_timeout; - struct timeval socket_timeout; - } bio_dgram_data; - - struct sockaddr_in6 peer; - int i; - BIO *bio; - for (i = 0; i < MAX_SSL_PEERS; i++) { - if (ssl_peer_storage[i]) { - if (!ssl_peer_storage[i]->ssl) - fprintf(stderr, "invalid SSL object for peer %d!\n",i); - else { - bio = SSL_get_rbio(ssl_peer_storage[i]->ssl); - if (bio) { - (void) BIO_dgram_get_peer(bio, (struct sockaddr *)&peer); - if (peer.sin6_port && ssl_peer_storage[i]->h != ntohs(peer.sin6_port)) { - fprintf(stderr, " bio %p: port differs from hash: %d != %d! (%sconnected)\n", bio, - ssl_peer_storage[i]->h, - ntohs(((struct sockaddr_in6 *)&peer)->sin6_port), - ((bio_dgram_data *)bio->ptr)->connected ? "" : "not "); - } - - } - } - } - } -} - -/** Creates a hash value from the first num bytes of s, taking init as - * initialization value. */ -static inline unsigned long -_hash(unsigned long init, const char *s, int num) { - int c; - - while (num--) - while ( (c = *s++) ) { - init = ((init << 7) + init) + c; - } - - return init; -} - -static inline unsigned long -hash_peer(const struct sockaddr *peer, int ifindex) { - unsigned long h; - - /* initialize hash value to interface index */ - h = _hash(0, (char *)&ifindex, sizeof(int)); - -#define CAST(TYPE,VAR) ((TYPE)VAR) - - assert(peer); - switch (peer->sa_family) { - case AF_INET: - return ntohs(CAST(const struct sockaddr_in *, peer)->sin_port); - h = _hash(h, (char *) &CAST(const struct sockaddr_in *, peer)->sin_addr, - sizeof(struct in_addr)); - h = _hash(h, (char *) &CAST(const struct sockaddr_in *, peer)->sin_port, - sizeof(in_port_t)); - break; - case AF_INET6: - return ntohs(CAST(const struct sockaddr_in6 *, peer)->sin6_port); - h = _hash(h, - (char *) &CAST(const struct sockaddr_in6 *, peer)->sin6_addr, - sizeof(struct in6_addr)); - h = _hash(h, - (char *) &CAST(const struct sockaddr_in6 *, peer)->sin6_port, - sizeof(in_port_t)); - break; - default: - /* last resort */ - h = _hash(h, (char *)peer, sizeof(struct sockaddr)); - } - - return 42; - return h; -} - -/* Returns index of peer object for specified address/ifindex pair. */ -int -get_index_of_peer(const struct sockaddr *peer, int ifindex) { - unsigned long h; - int idx; -#ifndef NDEBUG - char addr[INET6_ADDRSTRLEN]; - char port[6]; -#endif - - if (!peer) - return -1; - - h = hash_peer(peer,ifindex); - - for (idx = 0; idx < MAX_SSL_PEERS; idx++) { - if (ssl_peer_storage[idx] && ssl_peer_storage[idx]->h == h) { -#ifndef NDEBUG - getnameinfo((struct sockaddr *)peer, sizeof(struct sockaddr_in6), - addr, sizeof(addr), port, sizeof(port), - NI_NUMERICHOST | NI_NUMERICSERV); - - fprintf(stderr, "get_index_of_peer: [%s]:%s => %lu\n", - addr, port, h); -#endif - return idx; - } - } - return -1; -} - -SSL * -get_ssl(SSL_CTX *ctx, int sockfd, struct sockaddr *src, int ifindex) { - int idx; - BIO *bio; - SSL *ssl; -#ifndef NDEBUG - struct sockaddr_storage peer; - char addr[INET6_ADDRSTRLEN]; - char port[6]; - int i; -#endif - - idx = get_index_of_peer(src,ifindex); - if (idx >= 0) { - fprintf(stderr,"found peer %d ",idx); - switch (ssl_peer_storage[idx]->state) { - case PEER_ST_ESTABLISHED: fprintf(stderr,"established\n"); break; - case PEER_ST_PENDING: fprintf(stderr,"pending\n"); break; - case PEER_ST_CLOSED: fprintf(stderr,"closed\n"); break; - default: - OPENSSL_assert(0); - } - -#ifndef NDEBUG - memset(&peer, 0, sizeof(peer)); - (void) BIO_dgram_get_peer(SSL_get_rbio(ssl_peer_storage[idx]->ssl), &peer); - - getnameinfo((struct sockaddr *)&peer, sizeof(peer), - addr, sizeof(addr), port, sizeof(port), - NI_NUMERICHOST | NI_NUMERICSERV); - - fprintf(stderr," [%s]:%s \n", addr, port); -#endif - return ssl_peer_storage[idx]->ssl; - } - - /* none found, create new if sufficient space available */ - if (pending < MAX_SSL_PENDING) { - for (idx = 0; idx < MAX_SSL_PEERS; idx++) { - if (ssl_peer_storage[idx] == NULL) { /* found space */ - ssl = SSL_new(ctx); - - if (ssl) { - bio = BIO_new_dgram(sockfd, BIO_NOCLOSE); - if (!bio) { - SSL_free(ssl); - return NULL; - } - - SSL_set_bio(ssl, bio, bio); - SSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE); - - SSL_set_accept_state(ssl); - ssl_peer_storage[idx] = (ssl_peer_t *) malloc(sizeof(ssl_peer_t)); - if (!ssl_peer_storage[idx]) { - SSL_free(ssl); - return NULL; - } - ssl_peer_storage[idx]->state = PEER_ST_PENDING; - ssl_peer_storage[idx]->h = hash_peer(src,ifindex); - ssl_peer_storage[idx]->ssl = ssl; - - pending++; - - fprintf(stderr, - "created new SSL peer %d for ssl object %p (storage: %p)\n", - idx, ssl, ssl_peer_storage[idx]); -#ifndef NDEBUG - if (getnameinfo((struct sockaddr *)&src, sizeof(src), - addr, sizeof(addr), port, sizeof(port), - NI_NUMERICHOST | NI_NUMERICSERV) != 0) { - perror("getnameinfo"); - fprintf(stderr, "port was %u\n", ntohs(((struct sockaddr_in6 *)src)->sin6_port)); - } else { - fprintf(stderr," [%s]:%s \n", addr, port); - } -#endif - OPENSSL_assert(ssl_peer_storage[idx]->ssl == ssl); - fprintf(stderr,"%d objects pending\n", pending); - check_peers(); - return ssl; - } - } - } - } else { - fprintf(stderr, "too many pending SSL objects\n"); - return NULL; - } - - fprintf(stderr, "too many peers\n"); - return NULL; -} - -/** Deletes peer stored at index idx and frees allocated memory. */ -static inline void -delete_peer(int idx) { - if (idx < 0 || !ssl_peer_storage[idx]) - return; - - if (ssl_peer_storage[idx]->state == PEER_ST_PENDING) - pending--; - - OPENSSL_assert(ssl_peer_storage[idx]->ssl); - SSL_free(ssl_peer_storage[idx]->ssl); - - free(ssl_peer_storage[idx]); - ssl_peer_storage[idx] = NULL; - - printf("deleted peer %d\n",idx); -} - -/** Deletes all closed objects from ssl_peer_storage. */ -void -remove_closed() { - int idx; - - for (idx = 0; idx < MAX_SSL_PEERS; idx++) - if (ssl_peer_storage[idx] - && ssl_peer_storage[idx]->state == PEER_ST_CLOSED) - delete_peer(idx); -} - -#define min(a,b) ((a) < (b) ? (a) : (b)) - -unsigned int -psk_server_callback(SSL *ssl, const char *identity, - unsigned char *psk, unsigned int max_psk_len) { - static char keybuf[] = "secretPSK"; - - printf("psk_server_callback: check identity of client %s\n", identity); - memcpy(psk, keybuf, min(strlen(keybuf), max_psk_len)); - - return min(strlen(keybuf), max_psk_len); -} - -#endif - -#ifdef WITH_DTLS -/** - * This function tracks the status changes from libssl to manage local - * object state. - */ -void -info_callback(const SSL *ssl, int where, int ret) { - int idx, i; - struct sockaddr_storage peer; - struct sockaddr_storage peer2; - char addr[INET6_ADDRSTRLEN]; - char port[6]; - - if (where & SSL_CB_LOOP) /* do not care for intermediary states */ - return; - - memset(&peer, 0, sizeof(peer)); - (void) BIO_dgram_get_peer(SSL_get_rbio(ssl), &peer); - - /* lookup SSL object */ /* FIXME: need to get the ifindex */ - idx = get_index_of_peer((struct sockaddr *)&peer, 0); - - if (idx >= 0) - fprintf(stderr, "info_callback: assert: %d < 0 || %p == %p (storage: %p)\n", - idx, ssl, ssl_peer_storage[idx]->ssl, ssl_peer_storage[idx]); - if (idx >= 0 && ssl != ssl_peer_storage[idx]->ssl) { - getnameinfo((struct sockaddr *)&peer, sizeof(peer), - addr, sizeof(addr), port, sizeof(port), - NI_NUMERICHOST | NI_NUMERICSERV); - - fprintf(stderr," ssl: [%s]:%s ", addr, port); - - (void) BIO_dgram_get_peer(SSL_get_rbio(ssl_peer_storage[idx]->ssl), &peer2); - getnameinfo((struct sockaddr *)&peer2, sizeof(peer2), - addr, sizeof(addr), port, sizeof(port), - NI_NUMERICHOST | NI_NUMERICSERV); - - fprintf(stderr," ssl_peer_storage[idx]->ssl: [%s]:%s\n", addr, port); - - fprintf(stderr, " hash:%lu h: %lu\n", - hash_peer((const struct sockaddr *)&peer, 0), - ssl_peer_storage[idx]->h); - - for (i = 0; i < MAX_SSL_PEERS; i++) { - if (ssl_peer_storage[i]) { - fprintf(stderr, "%02d: %p ssl: %p ", - i, ssl_peer_storage[i] ,ssl_peer_storage[i]->ssl); - - (void) BIO_dgram_get_peer(SSL_get_rbio(ssl_peer_storage[i]->ssl), &peer2); - getnameinfo((struct sockaddr *)&peer2, sizeof(peer2), - addr, sizeof(addr), port, sizeof(port), - NI_NUMERICHOST | NI_NUMERICSERV); - - fprintf(stderr," peer: [%s]:%s h: %lu\n", addr, port, ssl_peer_storage[i]->h); - } - } - fprintf(stderr, "***** ASSERT FAILED ******\n"); - - memset(&peer, 0, sizeof(peer)); - (void) BIO_dgram_get_peer(SSL_get_wbio(ssl), &peer); - - idx = get_index_of_peer((struct sockaddr *)&peer, 0); - fprintf(stderr, " get_index_of_peer for wbio returns %d, type is %04x\n", - idx, where); - } -#if 1 - check_peers(); - OPENSSL_assert((idx < 0) || (ssl == ssl_peer_storage[idx]->ssl)); -#endif - - if (where & SSL_CB_ALERT) { -#ifndef NDEBUG - if (ret != 0) - fprintf(stderr,"%s:%s:%s\n", SSL_alert_type_string(ret), - SSL_alert_desc_string(ret), SSL_alert_desc_string_long(ret)); -#endif - - /* examine alert type */ - switch (*SSL_alert_type_string(ret)) { - case 'F': - /* move SSL object from pending to close */ - if (idx >= 0) { - ssl_peer_storage[idx]->state = PEER_ST_CLOSED; - pending--; - } - break; - case 'W': - if ((ret & 0xff) == SSL_AD_CLOSE_NOTIFY) { - if (where == SSL_CB_WRITE_ALERT) - fprintf(stderr,"sent CLOSE_NOTIFY\n"); - else /* received CN */ - fprintf(stderr,"received CLOSE_NOTIFY\n"); - } - break; - default: /* handle unknown alert types */ -#ifndef NDEBUG - printf("not handled!\n"); -#endif - } - } - - if (where & SSL_CB_HANDSHAKE_DONE) { - /* move SSL object from pending to established */ - printf("HANDSHAKE_DONE "); - if (idx >= 0) { - - if (ssl_peer_storage[idx]->state == PEER_ST_PENDING) { - ssl_peer_storage[idx]->state = PEER_ST_ESTABLISHED; - pending--; - printf("moved SSL object %d to ESTABLISHED\n", idx); - printf("%d objects pending\n", pending); - } else { -#ifndef NDEBUG - printf("huh, object %d was not pending? (%d)\n", idx, - ssl_peer_storage[idx]->state); -#endif - } - return; - } - return; - } - - return; -} -#endif - -#ifdef WITH_DTLS -/* checks if ssl object was closed and can be removed */ -int -check_close(SSL *ssl) { - int res, err, idx; - struct sockaddr_storage peer; - - memset(&peer, 0, sizeof(peer)); - (void)BIO_dgram_get_peer(SSL_get_rbio(ssl), &peer); - - res = 0; - if (SSL_get_shutdown(ssl) & SSL_RECEIVED_SHUTDOWN) { - printf("SSL_RECEIVED_SHUTDOWN\n"); - res = SSL_shutdown(ssl); - if (res == 0) { - printf("must call SSL_shutdown again\n"); - res = SSL_shutdown(ssl); - } - if (res < 0) { - err = SSL_get_error(ssl,res); - fprintf(stderr, "shutdown: SSL error %d: %s\n", err, - ERR_error_string(err, NULL)); - } - - /* we can close the SSL object anyway */ - /* FIXME: need to get ifindex from somewhere */ - idx = get_index_of_peer((struct sockaddr *)&peer, 0); - OPENSSL_assert(idx < 0 || ssl == ssl_peer_storage[idx]->ssl); - if (idx >= 0) { - ssl_peer_storage[idx]->state = PEER_ST_CLOSED; - printf("moved SSL object %d to CLOSED\n",idx); - } - } - - return res; -} - -int -check_timeout() { - int i, result, err; - - for (i = 0; i < MAX_SSL_PEERS; i++) { - if (ssl_peer_storage[i]) { - OPENSSL_assert(ssl_peer_storage[i]->ssl); - result = DTLSv1_handle_timeout(ssl_peer_storage[i]->ssl); - if (result < 0) { - err = SSL_get_error(ssl_peer_storage[i]->ssl,result); - fprintf(stderr, "dtls1_handle_timeout (%d): %s\n", - err, ERR_error_string(err, NULL)); - } - } - } - - /* remove outdated obbjects? */ - - return 0; -} -#endif /* WITH_DTLS */ - -int -_read(SSL_CTX *ctx, int sockfd) { - char buf[2000]; - struct sockaddr_in6 src; - int len, ifindex, i; - char addr[INET6_ADDRSTRLEN]; - char port[6]; - socklen_t sz = sizeof(struct sockaddr_in6); -#ifdef WITH_DTLS - SSL *ssl; - int err; -#endif - - /* Retrieve remote address and interface index as well as the first - few bytes of the message to demultiplex protocols. */ - memset(&src, 0, sizeof(struct sockaddr_in6)); - len = check_connect(sockfd, buf, 4, (struct sockaddr *)&src, &ifindex); - - if (len < 0) /* error */ - return len; - -#ifndef NDEBUG - fprintf(stderr,"received packet"); - - if (getnameinfo((struct sockaddr *)&src, sizeof(src), - addr, sizeof(addr), port, sizeof(port), - NI_NUMERICHOST | NI_NUMERICSERV) == 0) - fprintf(stderr," from [%s]:%s", addr, port); - - fprintf(stderr," on interface %d\n", ifindex); -#endif - - switch (demux_protocol(buf, len)) { -#ifdef WITH_DTLS - case DTLS : - ssl = get_ssl(ctx, sockfd, (struct sockaddr *)&src, ifindex); - if (!ssl) { - fprintf(stderr, "cannot create new SSL object\n"); - /* return recv(sockfd, buf, sizeof(buf), MSG_DONTWAIT);*/ - len = recvfrom(sockfd, buf, sizeof(buf), MSG_DONTWAIT, - (struct sockaddr *)&src, &sz); - getnameinfo((struct sockaddr *)&src, sz, - addr, sizeof(addr), port, sizeof(port), - NI_NUMERICHOST | NI_NUMERICSERV); - printf("discarded %d bytes from [%s]:%s\n", len, addr, port); - return len; - } - len = SSL_read(ssl, buf, sizeof(buf)); - break; -#endif - case UNKNOWN: - default : - len = recv(sockfd, buf, sizeof(buf), MSG_DONTWAIT); - } - - if (len > 0) { - printf("here is the data:\n"); - for (i=0; i<len; i++) - printf("%c",buf[i]); - } if (len == 0) { /* session closed? */ -#ifdef WITH_DTLS - if (check_close(ssl) <= 0) { - fprintf(stderr, "not closed\n"); - } -#endif - } else { -#ifdef WITH_DTLS - err = SSL_get_error(ssl,len); - switch (err) { - case SSL_ERROR_WANT_READ: - fprintf(stderr, "SSL_ERROR_WANT_READ\n"); - return 0; - case SSL_ERROR_WANT_WRITE: - fprintf(stderr, "SSL_ERROR_WANT_WRITE\n"); - return 0; - default: - fprintf(stderr, "read: SSL error %d: %s\n", err, - ERR_error_string(err, NULL)); - return 0; - } -#else - perror("recv"); -#endif - } - - return len; -} - -int -_write(SSL_CTX *ctx, int sockfd) { - int res = 0; -#ifdef WITH_DTLS - SSL *ssl; - int err; - - ssl = get_ssl(ctx, sockfd, NULL, 1); - if (!ssl) { - fprintf(stderr, "no SSL object for writing"); - return 0; - } - res = SSL_write(ssl, NULL, 0); - if (res < 0) { - /* - if (SSL_want_write(ssl)) - return 0; - */ - /* FIXME: check SSL_want_read(ssl) */ - - err = SSL_get_error(ssl,res); - fprintf(stderr,"SSL_write returned %d (%s)\n", err, ERR_error_string(err, NULL)); - } else { - printf("SSL_write successful\n"); - } -#else -#endif - - return res; -} - - -int -generate_cookie(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len) { - /* FIXME: generate secure client-specific cookie */ -#define DUMMYSTR "ABCDEFGHIJKLMNOP" - *cookie_len = strlen(DUMMYSTR); - memcpy(cookie, DUMMYSTR, *cookie_len); - - return 1; -} - -int -verify_cookie(SSL *ssl, unsigned char *cookie, unsigned int cookie_len) { - /* FIXME */ - return 1; -} - -enum { READ, WRITE }; - -int -main(int argc, char **argv) { - int sockfd = 0; - int on = 1; - struct sockaddr_in6 listen_addr = { AF_INET6, htons(20220), 0, IN6ADDR_ANY_INIT, 0 }; - size_t addr_size = sizeof(struct sockaddr_in6); - fd_set fds[2]; - int result, flags; - int idx, res = 0; - struct timeval timeout; - struct sigaction act, oact; - -#ifdef WITH_DTLS - SSL_CTX *ctx; - - memset(ssl_peer_storage, 0, sizeof(ssl_peer_storage)); - - SSL_load_error_strings(); - SSL_library_init(); - ctx = SSL_CTX_new(DTLSv1_server_method()); - - SSL_CTX_set_cipher_list(ctx, "ALL"); - SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); - - res = SSL_CTX_use_certificate_file(ctx, SERVER_CERT_PEM, SSL_FILETYPE_PEM); - if (res != 1) { - fprintf(stderr, "cannot read server certificate from file '%s' (%s)\n", - SERVER_CERT_PEM, ERR_error_string(res,NULL)); - goto end; - } - - res = SSL_CTX_use_PrivateKey_file(ctx, SERVER_KEY_PEM, SSL_FILETYPE_PEM); - if (res != 1) { - fprintf(stderr, "cannot read server key from file '%s' (%s)\n", - SERVER_KEY_PEM, ERR_error_string(res,NULL)); - goto end; - } - - res = SSL_CTX_check_private_key (ctx); - if (res != 1) { - fprintf(stderr, "invalid private key\n"); - goto end; - } - - res = SSL_CTX_load_verify_locations(ctx, CA_CERT_PEM, NULL); - if (res != 1) { - fprintf(stderr, "cannot read ca file '%s'\n", CA_CERT_PEM); - goto end; - } - - /* Client has to authenticate */ - - /* Client has to authenticate */ - SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, NULL); - - SSL_CTX_set_read_ahead(ctx, 1); /* disable read-ahead */ - SSL_CTX_set_cookie_generate_cb(ctx, generate_cookie); - SSL_CTX_set_cookie_verify_cb(ctx, verify_cookie); - - SSL_CTX_use_psk_identity_hint(ctx, "Enter password for CoAP-Gateway"); - SSL_CTX_set_psk_server_callback(ctx, psk_server_callback); - - SSL_CTX_set_info_callback(ctx, info_callback); -#endif - - sockfd = socket(listen_addr.sin6_family, SOCK_DGRAM, 0); - if ( sockfd < 0 ) { - perror("socket"); - return -1; - } - - if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) ) < 0) - perror("setsockopt SO_REUSEADDR"); - - flags = fcntl(sockfd, F_GETFL, 0); - if (flags < 0 || fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) < 0) { - perror("fcntl"); - return -1; - } - - on = 1; - if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on) ) < 0) { - perror("setsockopt IPV6_PKTINFO"); - } - - if (bind (sockfd, (const struct sockaddr *)&listen_addr, addr_size) < 0) { - perror("bind"); - res = -2; - goto end; - } - - act.sa_handler = handle_sigint; - sigemptyset(&act.sa_mask); - act.sa_flags = 0; - sigaction(SIGINT, &act, &oact); - - while (!quit) { - FD_ZERO(&fds[READ]); - FD_ZERO(&fds[WRITE]); - FD_SET(sockfd, &fds[READ]); - - timeout.tv_sec = 1; - timeout.tv_usec = 0; - result = select( FD_SETSIZE, &fds[READ], &fds[WRITE], 0, &timeout); - - if (result < 0) { /* error */ - if (errno != EINTR) - perror("select"); - } else if (result > 0) { /* read from socket */ - if ( FD_ISSET( sockfd, &fds[READ]) ) { - _read(ctx, sockfd); /* read received data */ - } else if ( FD_ISSET( sockfd, &fds[WRITE]) ) { /* write to socket */ - _write(ctx, sockfd); /* write data */ - } - } else { /* timeout */ - check_timeout(); - } - remove_closed(); - } - - end: -#ifdef WITH_DTLS - for (idx = 0; idx < MAX_SSL_PEERS; idx++) { - if (ssl_peer_storage[idx] && ssl_peer_storage[idx]->ssl) { - if (ssl_peer_storage[idx]->state == PEER_ST_ESTABLISHED) - SSL_shutdown(ssl_peer_storage[idx]->ssl); - SSL_free(ssl_peer_storage[idx]->ssl); - } - } - - SSL_CTX_free(ctx); -#endif - close(sockfd); /* don't care if we close stdin at this point */ - return res; -}