/*
- * Copyright (c) 1995-2003, Index Data
+ * Copyright (C) 1995-2005, Index Data ApS
* See the file LICENSE for details.
*
- * $Id: tcpip.c,v 1.1 2003-10-27 12:21:35 adam Exp $
+ * $Id: tcpip.c,v 1.14 2005-01-16 21:51:50 adam Exp $
+ */
+/**
+ * \file tcpip.c
+ * \brief Implements TCP/IP + SSL COMSTACK.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
#ifdef WIN32
+#include <winsock.h>
#else
-#include <unistd.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <netinet/tcp.h>
+#endif
+
+#if HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#if HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#if HAVE_SYS_WAIT_H
+#include <sys/wait.h>
#endif
-#include <errno.h>
-#include <fcntl.h>
-#include <signal.h>
#if HAVE_OPENSSL_SSL_H
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <yaz/comstack.h>
#include <yaz/tcpip.h>
-#include <yaz/log.h>
#include <yaz/nmem.h>
-#ifdef WIN32
-#else
-#include <netinet/tcp.h>
-#endif
-
static int tcpip_close(COMSTACK h);
static int tcpip_put(COMSTACK h, char *buf, int size);
static int tcpip_get(COMSTACK h, char **buf, int *bufsize);
struct sockaddr_in addr; /* returned by cs_straddr */
char buf[128]; /* returned by cs_addrstr */
#if HAVE_OPENSSL_SSL_H
- SSL_CTX *ctx;
- SSL_CTX *ctx_alloc;
+ SSL_CTX *ctx; /* current CTX. */
+ SSL_CTX *ctx_alloc; /* If =ctx it is owned by CS. If 0 it is not owned */
SSL *ssl;
+ char cert_fname[256];
#endif
} tcpip_state;
COMSTACK tcpip_type(int s, int blocking, int protocol, void *vp)
{
COMSTACK p;
- tcpip_state *state;
+ tcpip_state *sp;
int new_socket;
#ifdef WIN32
unsigned long tru = 1;
new_socket = 0;
if (!(p = (struct comstack *)xmalloc(sizeof(struct comstack))))
return 0;
- if (!(state = (struct tcpip_state *)(p->cprivate =
+ if (!(sp = (struct tcpip_state *)(p->cprivate =
xmalloc(sizeof(tcpip_state)))))
return 0;
p->stackerr = 0;
#if HAVE_OPENSSL_SSL_H
- state->ctx = state->ctx_alloc = 0;
- state->ssl = 0;
+ sp->ctx = sp->ctx_alloc = 0;
+ sp->ssl = 0;
+ strcpy(sp->cert_fname, "yaz.pem");
#endif
- state->altbuf = 0;
- state->altsize = state->altlen = 0;
- state->towrite = state->written = -1;
+ sp->altbuf = 0;
+ sp->altsize = sp->altlen = 0;
+ sp->towrite = sp->written = -1;
if (protocol == PROTO_WAIS)
- state->complete = completeWAIS;
+ sp->complete = completeWAIS;
else
- state->complete = cs_complete_auto;
+ sp->complete = cs_complete_auto;
p->timeout = COMSTACK_DEFAULT_TIMEOUT;
TRC(fprintf(stderr, "Created new TCPIP comstack\n"));
COMSTACK ssl_type(int s, int blocking, int protocol, void *vp)
{
- tcpip_state *state;
+ tcpip_state *sp;
COMSTACK p;
- yaz_log(LOG_LOG, "ssl_type begin");
p = tcpip_type (s, blocking, protocol, 0);
if (!p)
p->f_get = ssl_get;
p->f_put = ssl_put;
p->type = ssl_type;
- state = (tcpip_state *) p->cprivate;
- if (vp)
- state->ctx = vp;
- else
- {
- SSL_load_error_strings();
- SSLeay_add_all_algorithms();
+ sp = (tcpip_state *) p->cprivate;
+
+ sp->ctx = (SSL_CTX *) vp; /* may be NULL */
- state->ctx = state->ctx_alloc = SSL_CTX_new (SSLv23_method());
- if (!state->ctx)
- {
- tcpip_close(p);
- return 0;
- }
- }
/* note: we don't handle already opened socket in SSL mode - yet */
- yaz_log(LOG_LOG, "ssl_type end");
return p;
}
#endif
int tcpip_connect(COMSTACK h, void *address)
{
struct sockaddr_in *add = (struct sockaddr_in *)address;
-#if HAVE_OPENSSL_SSL_H
- tcpip_state *sp = (tcpip_state *)h->cprivate;
-#endif
int r;
#ifdef __sun__
int recbuflen;
return -1;
}
#if HAVE_OPENSSL_SSL_H
+ if (h->type == ssl_type && !sp->ctx)
+ {
+ SSL_load_error_strings();
+ SSLeay_add_all_algorithms();
+
+ sp->ctx = sp->ctx_alloc = SSL_CTX_new (SSLv23_method());
+ if (!sp->ctx)
+ {
+ h->cerrno = CSERRORSSL;
+ return -1;
+ }
+ }
if (sp->ctx)
{
int res;
#if HAVE_OPENSSL_SSL_H
tcpip_state *sp = (tcpip_state *)h->cprivate;
+ if (h->type == ssl_type && !sp->ctx)
+ {
+ SSL_load_error_strings();
+ SSLeay_add_all_algorithms();
+
+ sp->ctx = sp->ctx_alloc = SSL_CTX_new (SSLv23_method());
+ if (!sp->ctx)
+ {
+ h->cerrno = CSERRORSSL;
+ return -1;
+ }
+ }
if (sp->ctx)
{
if (sp->ctx_alloc)
{
int res;
- res = SSL_CTX_use_certificate_file (sp->ctx, CERTF,
+ res = SSL_CTX_use_certificate_file (sp->ctx, sp->cert_fname,
SSL_FILETYPE_PEM);
if (res <= 0)
{
ERR_print_errors_fp(stderr);
exit (2);
}
- res = SSL_CTX_use_PrivateKey_file (sp->ctx, KEYF,
+ res = SSL_CTX_use_PrivateKey_file (sp->ctx, sp->cert_fname,
SSL_FILETYPE_PEM);
if (res <= 0)
{
#endif
}
else if (!res)
- return 0;
+ return hasread;
hasread += res;
}
TRC (fprintf (stderr, " Out of read loop with hasread=%d, berlen=%d\n",
p->blocking = blocking;
return 1;
}
+
+#if HAVE_OPENSSL_SSL_H
+int cs_set_ssl_ctx(COMSTACK cs, void *ctx)
+{
+ struct tcpip_state *sp;
+ if (!cs || cs->type != ssl_type)
+ return 0;
+ sp = (struct tcpip_state *) cs->cprivate;
+ if (sp->ctx_alloc)
+ return 0;
+ sp->ctx = (SSL_CTX *) ctx;
+ return 1;
+}
+
+void *cs_get_ssl(COMSTACK cs)
+{
+ struct tcpip_state *sp;
+ if (!cs || cs->type != ssl_type)
+ return 0;
+ sp = (struct tcpip_state *) cs->cprivate;
+ return sp->ssl;
+}
+
+int cs_set_ssl_certificate_file(COMSTACK cs, const char *fname)
+{
+ struct tcpip_state *sp;
+ if (!cs || cs->type != ssl_type)
+ return 0;
+ sp = (struct tcpip_state *) cs->cprivate;
+ strncpy(sp->cert_fname, fname, sizeof(sp->cert_fname)-1);
+ sp->cert_fname[sizeof(sp->cert_fname)-1] = '\0';
+ return 1;
+}
+
+int cs_get_peer_certificate_x509(COMSTACK cs, char **buf, int *len)
+{
+ SSL *ssl = (SSL *) cs_get_ssl(cs);
+ if (ssl)
+ {
+ X509 *server_cert = SSL_get_peer_certificate (ssl);
+ if (server_cert)
+ {
+ BIO *bio = BIO_new(BIO_s_mem());
+ char *pem_buf;
+ /* get PEM buffer in memory */
+ PEM_write_bio_X509(bio, server_cert);
+ *len = BIO_get_mem_data(bio, &pem_buf);
+ *buf = (char *) xmalloc(*len);
+ memcpy(*buf, pem_buf, *len);
+ BIO_free(bio);
+ return 1;
+ }
+ }
+ return 0;
+}
+#else
+int cs_set_ssl_ctx(COMSTACK cs, void *ctx)
+{
+ return 0;
+}
+
+void *cs_get_ssl(COMSTACK cs)
+{
+ return 0;
+}
+
+int cs_get_peer_certificate_x509(COMSTACK cs, char **buf, int *len)
+{
+ return 0;
+}
+
+int cs_set_ssl_certificate_file(COMSTACK cs, const char *fname)
+{
+ return 0;
+}
+#endif
+