diff -ruN netcat-0.7.1/src/Makefile.in netcat-0.7.1.new/src/Makefile.in --- netcat-0.7.1/src/Makefile.in 2004-01-11 17:46:31.000000000 -0300 +++ netcat-0.7.1.new/src/Makefile.in 2004-02-24 13:04:11.000000000 -0300 @@ -56,7 +56,7 @@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ -DEFS = -DLOCALEDIR=\"\$(localedir)\" @DEFS@ +DEFS = -DLOCALEDIR=\"\$(localedir)\" @DEFS@ -DHAVE_TLS DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ @@ -75,7 +75,7 @@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ +LIBS = @LIBS@ -lssl -lcrypto LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ @@ -157,6 +157,7 @@ netcat.c \ network.c \ telnet.c \ + sslutils.c \ udphelper.c @@ -178,7 +179,7 @@ am_netcat_OBJECTS = core.$(OBJEXT) flagset.$(OBJEXT) misc.$(OBJEXT) \ netcat.$(OBJEXT) network.$(OBJEXT) telnet.$(OBJEXT) \ - udphelper.$(OBJEXT) + udphelper.$(OBJEXT) sslutils.$(OBJEXT) netcat_OBJECTS = $(am_netcat_OBJECTS) netcat_DEPENDENCIES = netcat_LDFLAGS = diff -ruN netcat-0.7.1/src/misc.c netcat-0.7.1.new/src/misc.c --- netcat-0.7.1/src/misc.c 2004-01-03 13:42:07.000000000 -0300 +++ netcat-0.7.1.new/src/misc.c 2004-02-23 00:30:50.000000000 -0300 @@ -325,6 +325,15 @@ " -p, --local-port=NUM local port number\n" " -r, --randomize randomize local and remote ports\n" " -s, --source=ADDRESS local source address (ip or hostname)\n")); +#ifdef HAVE_TLS +printf(_("" +" -E, --tls use tls\n" +" -f, --cafile=FILE CA certificate file to auth the peer\n" +" -F, --capath=PATH CA certificate dir to auth the peer\n" +" -K, --dontcheckhost don't check hostname with certificate data\n" +" -R, --cert=FILE use certificate file (listen mode)\n" +" -k, --key=FILE use private key (listen mode)\n")); +#endif #ifndef USE_OLD_COMPAT printf(_("" " -t, --tcp TCP mode (default)\n" diff -ruN netcat-0.7.1/src/netcat.c netcat-0.7.1.new/src/netcat.c --- netcat-0.7.1/src/netcat.c 2003-08-28 14:20:25.000000000 -0300 +++ netcat-0.7.1.new/src/netcat.c 2004-02-23 00:29:55.000000000 -0300 @@ -30,6 +30,9 @@ #include #include #include /* time(2) used as random seed */ +#ifdef HAVE_TLS +#include +#endif /* int gatesidx = 0; */ /* LSRR hop count */ /* int gatesptr = 4; */ /* initial LSRR pointer, settable */ @@ -50,6 +53,14 @@ bool opt_numeric = FALSE; /* don't resolve hostnames */ bool opt_random = FALSE; /* use random ports */ bool opt_udpmode = FALSE; /* use udp protocol instead of tcp */ +#ifdef HAVE_TLS +bool opt_tls = FALSE; /* use tls */ +bool opt_dontcheckhost = FALSE; /* don't check host */ +char *opt_cafile = NULL; /* CA chain file */ +char *opt_capath = NULL; /* CA chain dir */ +char *opt_keyfile = NULL; /* key file */ +char *opt_certfile = NULL; /* certificate file */ +#endif bool opt_telnet = FALSE; /* answer in telnet mode */ bool opt_hexdump = FALSE; /* hexdump traffic */ bool opt_zero = FALSE; /* zero I/O mode (don't expect anything) */ @@ -101,20 +112,20 @@ /* Execute an external file making its stdin/stdout/stderr the actual socket */ -static void ncexec(nc_sock_t *ncsock) +static void ncexec(int readfd, int writefd) { int saved_stderr; char *p; - assert(ncsock && (ncsock->fd >= 0)); + assert((writefd >= 0) && (readfd >= 0)); /* save the stderr fd because we may need it later */ saved_stderr = dup(STDERR_FILENO); /* duplicate the socket for the child program */ - dup2(ncsock->fd, STDIN_FILENO); /* the precise order of fiddlage */ - close(ncsock->fd); /* is apparently crucial; this is */ - dup2(STDIN_FILENO, STDOUT_FILENO); /* swiped directly out of "inetd". */ - dup2(STDIN_FILENO, STDERR_FILENO); /* also duplicate the stderr channel */ + dup2(readfd, STDIN_FILENO); /* the precise order of fiddlage */ + //close(readfd); /* is apparently crucial; this is */ + dup2(writefd, STDOUT_FILENO); /* swiped directly out of "inetd". */ + dup2(writefd, STDERR_FILENO); /* also duplicate the stderr channel */ /* change the label for the executed program */ if ((p = strrchr(opt_exec, '/'))) @@ -146,6 +157,11 @@ nc_sock_t listen_sock; nc_sock_t connect_sock; nc_sock_t stdio_sock; +#ifdef HAVE_TLS + SSL_CTX *ctx; + SSL *ssl; +#endif + char *host = NULL; memset(&local_port, 0, sizeof(local_port)); memset(&local_host, 0, sizeof(local_host)); @@ -200,6 +216,14 @@ { "randomize", no_argument, NULL, 'r' }, { "source", required_argument, NULL, 's' }, { "tunnel-source", required_argument, NULL, 'S' }, +#ifdef HAVE_TLS + { "tls", no_argument, NULL, 'E' }, + { "cafile", required_argument, NULL, 'f' }, + { "capath", required_argument, NULL, 'F' }, + { "dontcheckhost", no_argument, NULL, 'K' }, + { "cert", required_argument, NULL, 'R' }, + { "key", required_argument, NULL, 'k' }, +#endif #ifndef USE_OLD_COMPAT { "tcp", no_argument, NULL, 't' }, { "telnet", no_argument, NULL, 'T' }, @@ -216,7 +240,11 @@ { 0, 0, 0, 0 } }; - c = getopt_long(argc, argv, "cde:g:G:hi:lL:no:p:P:rs:S:tTuvVxw:z", + c = getopt_long(argc, argv, "cde:g:G:hi:lL:no:p:P:rs:S:" +#ifdef HAVE_TLS + "Ef:F:R:k:" +#endif + "tTuvVxw:z", long_options, &option_index); if (c == -1) break; @@ -234,6 +262,38 @@ _("Cannot specify `-e' option double")); opt_exec = strdup(optarg); break; +#ifdef HAVE_TLS + case 'E': + opt_tls = 1; + break; + case 'f': + if (opt_cafile) + ncprint(NCPRINT_ERROR | NCPRINT_EXIT, + _("Cannot specify `-f' option double")); + opt_cafile = strdup(optarg); + break; + case 'F': + if (opt_capath) + ncprint(NCPRINT_ERROR | NCPRINT_EXIT, + _("Cannot specify `-F' option double")); + opt_capath = strdup(optarg); + break; + case 'R': + if (opt_certfile) + ncprint(NCPRINT_ERROR | NCPRINT_EXIT, + _("Cannot specify `-R' option double")); + opt_certfile = strdup(optarg); + break; + case 'k': + if (opt_keyfile) + ncprint(NCPRINT_ERROR | NCPRINT_EXIT, + _("Cannot specify `-k' option double")); + opt_keyfile = strdup(optarg); + break; + case 'K': + opt_dontcheckhost = 1; + break; +#endif case 'G': /* srcrt gateways pointer val */ break; case 'g': /* srcroute hop[s] */ @@ -357,6 +417,9 @@ if (opt_zero && opt_exec) ncprint(NCPRINT_ERROR | NCPRINT_EXIT, _("`-e' and `-z' options are incompatible")); + if (opt_tls && (opt_proto == NETCAT_PROTO_UDP) ) + ncprint(NCPRINT_ERROR | NCPRINT_EXIT, + _("`-u' and `-E' options are incompatible")); /* initialize the flag buffer to keep track of the specified ports */ netcat_flag_init(65535); @@ -392,10 +455,10 @@ /* try to get an hostname parameter */ if (optind < argc) { - char *myhost = argv[optind++]; - if (!netcat_resolvehost(&remote_host, myhost)) + host = argv[optind++]; + if (!netcat_resolvehost(&remote_host, host)) ncprint(NCPRINT_ERROR | NCPRINT_EXIT, _("Couldn't resolve host \"%s\""), - myhost); + host); } /* now loop all the other (maybe optional) parameters for port-ranges */ @@ -492,11 +555,46 @@ otherwise now it's the time to connect to the target host and tunnel them together (which means passing to the next section. */ if (netcat_mode == NETCAT_LISTEN) { +#ifdef HAVE_TLS + if (opt_tls) { + if (ssl_server_init(&ssl, &ctx, opt_certfile, opt_keyfile)) + ncprint(NCPRINT_ERROR | NCPRINT_EXIT, _("ssl_server_init failed\n")); + if (ssl_server_handshake(ssl, listen_sock.fd)) + ncprint(NCPRINT_ERROR | NCPRINT_EXIT, _("ssl_server_handshake failed\n")); + } + if (opt_exec && !opt_tls) { +#else if (opt_exec) { +#endif ncprint(NCPRINT_VERB2, _("Passing control to the specified program")); - ncexec(&listen_sock); /* this won't return */ + ncexec(listen_sock.fd, listen_sock.fd); /* this won't return */ + } +#ifdef HAVE_TLS + if (opt_tls) { + int p_read[2], p_write[2]; + int pid; + + if (opt_exec) { + if (pipe(p_read) < 0) + ncprint(NCPRINT_ERROR | NCPRINT_EXIT, _("%s\n"), strerror(errno)); + if (pipe(p_write) < 0) + ncprint(NCPRINT_ERROR | NCPRINT_EXIT, _("%s\n"), strerror(errno)); + signal(SIGCHLD, SIG_IGN); + if ((pid = fork()) == -1) + ncprint(NCPRINT_ERROR | NCPRINT_EXIT, _("%s\n"), strerror(errno)); + if (pid == 0) { + ncexec(p_write[0], p_read[1]); /* this won't return */ + } + close(p_write[0]); + close(p_read[1]); + ssl_read_write(ssl, p_read[0], p_write[1], listen_sock.fd); + } else + ssl_read_write(ssl, stdio_sock.fd, STDOUT_FILENO, listen_sock.fd); + ssl_shutdown(&ctx, &ssl); } - core_readwrite(&listen_sock, &stdio_sock); + else +#endif + core_readwrite(&listen_sock, &stdio_sock); debug_dv(("Listen: EXIT")); } else { @@ -583,6 +681,18 @@ continue; /* go with next port */ } +#ifdef HAVE_TLS + if (opt_tls) { + if (ssl_client_init (&ssl, &ctx, opt_cafile, opt_capath) < 0) + ncprint(NCPRINT_ERROR | NCPRINT_EXIT, _("ssl_client_init failed\n")); + if (ssl_client_handshake(ssl, connect_sock.fd)< 0) + ncprint(NCPRINT_ERROR | NCPRINT_EXIT, _("ssl_client_handshake failed\n")); + if (!opt_dontcheckhost) + if (ssl_check_hostname(ssl, host) < 0) + ncprint(NCPRINT_ERROR | NCPRINT_EXIT, _("ssl_check_hostname failed\n")); + } +#endif + /* when portscanning (or checking a single port) we are happy if AT LEAST ONE port is available. */ glob_ret = EXIT_SUCCESS; @@ -594,9 +704,16 @@ else { if (opt_exec) { ncprint(NCPRINT_VERB2, _("Passing control to the specified program")); - ncexec(&connect_sock); /* this won't return */ + ncexec(connect_sock.fd, connect_sock.fd); /* this won't return */ } - core_readwrite(&connect_sock, &stdio_sock); +#ifdef HAVE_TLS + if (opt_tls) { + ssl_read_write( ssl, stdio_sock.fd, 1, connect_sock.fd); + ssl_shutdown(&ctx, &ssl); + } + else +#endif + core_readwrite(&connect_sock, &stdio_sock); /* FIXME: add a small delay */ debug_v(("Connect: EXIT")); diff -ruN netcat-0.7.1/src/sslutils.c netcat-0.7.1.new/src/sslutils.c --- netcat-0.7.1/src/sslutils.c 1969-12-31 21:00:00.000000000 -0300 +++ netcat-0.7.1.new/src/sslutils.c 2004-02-22 19:04:47.000000000 -0300 @@ -0,0 +1,395 @@ + +#include +#include +#include +#include +#include + +#include "sslutils.h" +#include +#include + +static int tls_verify_cb( int ok, X509_STORE_CTX *ctx ); + +/* initialization for a SSL client */ +int ssl_client_init (SSL **ssl, SSL_CTX **ctx, char *CAfile, char *CApath) +{ + /* loads errors string messages */ + SSL_load_error_strings(); + + /* init library */ + if (SSL_library_init() != 1) { + fprintf(stderr, "could not initialice SSL library\n"); + return(-1); + } + + /* create SSL context */ + if((*ctx = SSL_CTX_new (SSLv23_client_method())) == NULL) { + fprintf (stderr, "could not initialize SSL_CTX structure\n"); + return (-1); + } + SSL_CTX_set_mode(*ctx, SSL_MODE_AUTO_RETRY); + + /* loads certs to authenticate the peer */ + if (CAfile || CApath) { + SSL_CTX_set_verify(*ctx, (SSL_VERIFY_PEER | SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT), tls_verify_cb); + if (!SSL_CTX_load_verify_locations(*ctx, CAfile, CApath)) + fprintf(stderr, "could not initialize CA file/path"); + } + + /* create SSL structure */ + if(( *ssl = SSL_new (*ctx)) == NULL ) { + fprintf (stderr, "could not initialize SSL structure\n"); + return (-1); + } + + return(0); +} + +/* initialization for a SSL server */ +int ssl_server_init(SSL **ssl, SSL_CTX **ctx, char *certfile, char *keyfile) +{ + /* loads errors string messages */ + SSL_load_error_strings(); + + /* init library */ + if (SSL_library_init() != 1) { + fprintf(stderr, "could not initialice SSL library\n"); + return(-1); + } + + + /* create SSL context */ + if((*ctx = SSL_CTX_new (SSLv23_server_method())) == NULL) { + fprintf (stderr, "could not initialize SSL_CTX structure\n"); + return (-1); + } + + SSL_CTX_set_quiet_shutdown (*ctx,1); + SSL_CTX_set_session_cache_mode (*ctx,SSL_SESS_CACHE_OFF); + + if (certfile && keyfile) { + if ( (SSL_CTX_use_certificate_file(*ctx, certfile, SSL_FILETYPE_PEM)) != 1) { + fprintf(stderr, "Error loading certificate file\n"); + return(-1); + } + if ( (SSL_CTX_use_PrivateKey_file(*ctx, keyfile, SSL_FILETYPE_PEM)) != 1) { + fprintf(stderr, "Error loading private key file\n"); + return(-1); + } +if (!SSL_CTX_check_private_key (*ctx)) + { + fprintf(stderr, "private key from [%s] is not valid\n", keyfile); + return (-1); + } + + } + + /* create SSL structure */ + if(( *ssl = SSL_new (*ctx)) == NULL ) { + fprintf (stderr, "could not initialize SSL structure\n"); + return (-1); + } + return(0); +} + +int ssl_client_handshake2(SSL *ssl, int socket) { + int ret; + + if ( (ret = SSL_set_fd (ssl, socket)) != 1) { + fprintf(stderr, "ERROR SSL_set_fd\n"); + return(-1); + } + + SSL_set_connect_state (ssl); + + fprintf(stderr, "mode: %ld\n", SSL_get_mode(ssl)); + ret = SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); + fprintf(stderr, "mode: %ld\n", SSL_get_mode(ssl)); + + if ( (ret = SSL_do_handshake(ssl)) != 1 ) { + ret = ERR_get_error(); + fprintf(stderr, "ERR in SSL_do_handshake (%d)\n", ret); + fprintf(stderr, "\t%s\n", ERR_error_string(ret, NULL)); + return(-1); + } + + return(0); +} + +int ssl_client_handshake(SSL *ssl, int socket) +{ + int oldflags = 0, ret; + + if ( (ret = SSL_set_fd (ssl, socket)) != 1) { + fprintf(stderr, "ERROR SSL_set_fd\n"); + return(-1); + } + + SSL_set_connect_state (ssl); + + if ( (oldflags = set_nonblocking_mode (socket)) < 0) + return (-1); + + /* on local connections, SSL_do_handshake may finish */ + ret = SSL_do_handshake(ssl); + + if ( (unset_nonblocking_mode (socket, oldflags)) < 0) + return (-1); + + /* on remote connections, wait for handshake answer and finish ssl connect */ + if (!SSL_is_init_finished (ssl)) { + //if (data_available (socket, timeout) < 0) + //return (-1); + ret = SSL_connect(ssl); + } + switch (ret) { + default: + case (-1): + fprintf (stderr, "TLS/SSL handshake failed.\n"); + return (-1); + case (0): + fprintf (stderr, "TLS/SSL handshake failed cleanly.\n"); + return (-1); + case (1): + return (0); + } +} + +int ssl_server_handshake(SSL *ssl, int sock) { + int ret; + + if ( (ret = SSL_set_fd(ssl, sock)) != 1) { + fprintf(stderr, "ERROR SSL_set_fd\n"); + return(-1); + } + + SSL_set_accept_state(ssl); + SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); + + if ( (ret = SSL_accept(ssl)) == -1) { + ret = SSL_get_error(ssl, ret); + fprintf(stderr, "%s\n", ERR_error_string(ret, NULL)); + return (-1); + } + return(0); +} + +int set_nonblocking_mode (int fd) { + int sockflag; + sockflag = fcntl (fd, F_GETFL, 0); + + if (fcntl (fd, F_SETFL, sockflag | O_NONBLOCK) == -1) { + fprintf(stderr, "could not set O_NONBLOCK on socket\n"); + return (-1); + } + return (sockflag); +} + +int unset_nonblocking_mode (int fd, int oldflags) { + if (fcntl (fd, F_SETFL, oldflags&(~O_NONBLOCK)) == -1) { + fprintf(stderr, "could not unset O_NONBLOCK on socket\n"); + return (-1); + } + return (0); +} + +void ssl_shutdown(SSL_CTX **ctx, SSL **ssl) { + if (*ssl) { + SSL_shutdown(*ssl); + SSL_free(*ssl); + *ssl = NULL; + } + if (*ctx) { + SSL_CTX_free(*ctx); + *ctx = NULL; + } +} + +int ssl_read_write(SSL *ssl, int sockin, int sockprint, int sockout) { + int num, nw, fdhigh, inclose = 0; + unsigned char buf[4096]; + fd_set fdread; + + fdhigh = (sockin <= sockout) ? sockout : sockin; + + while (1) { + /* empty the buffer */ + if (SSL_pending (ssl)) { + num = SSL_read (ssl, buf, sizeof (buf)); + if (num <= 0) { + fprintf(stderr, "SSL_read returns %d\n", num); + return -1; + } + for (nw = 0; num; num -= nw) + if ((nw = write (sockin, buf, num)) < 0) { + err(1, "file descriptor %d", sockin); + return -1; + } + } + + FD_ZERO (&fdread); + FD_SET (sockout, &fdread); + if (!inclose) { + FD_SET (sockin, &fdread); + fdhigh = (sockin <= sockout) ? sockout : sockin; + } else + fdhigh = sockout; + + select (fdhigh+1, &fdread, NULL, NULL, NULL); + if ( FD_ISSET (sockout, &fdread) ) { + num = SSL_read (ssl, buf, sizeof (buf)); + if (num <= 0) + return -1; + for (nw = 0; num; num -= nw) + if ((nw = write (sockprint, buf, num)) < 0) { + err(1, "file descriptor %d", sockprint); + return -1; + } + } + + if ( FD_ISSET (sockin, &fdread) ) { + num = read (sockin, buf, sizeof (buf)); + if (num <= 0) + if (sockin == STDIN_FILENO) + inclose = 1; + else + return -1; + else { + num = SSL_write (ssl, buf, num); + if (num <= 0) + return -1; + } + } + + } /* while */ + return 0; +} + +/* verify_callback based on libldap (openldap) library */ +static int +tls_verify_cb( int ok, X509_STORE_CTX *ctx ) +{ + X509 *cert; + int errnum; + int errdepth; + X509_NAME *subject; + X509_NAME *issuer; + char *sname; + char *iname; + + if (!ok) { + cert = X509_STORE_CTX_get_current_cert( ctx ); + errnum = X509_STORE_CTX_get_error( ctx ); + errdepth = X509_STORE_CTX_get_error_depth( ctx ); + + /* + * X509_get_*_name return pointers to the internal copies of + * those things requested. So do not free them. + */ + subject = X509_get_subject_name( cert ); + issuer = X509_get_issuer_name( cert ); + /* X509_NAME_oneline, if passed a NULL buf, allocate memomry */ + sname = X509_NAME_oneline( subject, NULL, 0 ); + iname = X509_NAME_oneline( issuer, NULL, 0 ); + fprintf(stderr, + "TLS certificate verification: depth: %d, subject: %s, issuer: %s, error: %s\n", + errdepth, + sname ? sname : "-unknown-", + iname ? iname : "-unknown-", + X509_verify_cert_error_string(errnum)); + if ( sname ) + CRYPTO_free ( sname ); + if ( iname ) + CRYPTO_free ( iname ); + } + return ok; +} + + +int ssl_check_hostname(SSL *ssl, char *host) +{ + X509 *cert; + X509_NAME *subj; + char data[256]; + int extcount; + int ok = 0; + + /* Checking the return from SSL_get_peer_certificate here is not strictly + * necessary. With our example programs, it is not possible for it to return + * NULL. However, it is good form to check the return since it can return NULL + * if the examples are modified to enable anonymous ciphers or for the server + * to not require a client certificate. + */ + if (!(cert = SSL_get_peer_certificate(ssl)) || !host) { + fprintf(stderr, "%s\n", X509_verify_cert_error_string(X509_V_ERR_APPLICATION_VERIFICATION)); + return -1; + } + if ((extcount = X509_get_ext_count(cert)) > 0) + { + int i; + + for (i = 0; i < extcount; i++) + { + const char *extstr; + X509_EXTENSION *ext; + + ext = X509_get_ext(cert, i); + extstr = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext))); + + if (!strcmp(extstr, "subjectAltName")) + { + int j; + unsigned char *data; + STACK_OF(CONF_VALUE) *val; + CONF_VALUE *nval; + X509V3_EXT_METHOD *meth; + void *ext_str = NULL; + + if (!(meth = X509V3_EXT_get(ext))) + break; + data = ext->value->data; + +#if (OPENSSL_VERSION_NUMBER > 0x00907000L) + if (meth->it) + ext_str = ASN1_item_d2i(NULL, &data, ext->value->length, + ASN1_ITEM_ptr(meth->it)); + else + ext_str = meth->d2i(NULL, &data, ext->value->length); +#else + ext_str = meth->d2i(NULL, &data, ext->value->length); +#endif + val = meth->i2v(meth, ext_str, NULL); + for (j = 0; j < sk_CONF_VALUE_num(val); j++) + { + nval = sk_CONF_VALUE_value(val, j); + if (!strcmp(nval->name, "DNS") && !strcmp(nval->value, host)) + { + ok = 1; + break; + } + } + } + if (ok) + break; + } + } + + if (!ok && (subj = X509_get_subject_name(cert)) && + X509_NAME_get_text_by_NID(subj, NID_commonName, data, 256) > 0) + { + data[255] = 0; + if (strcasecmp(data, host) == 0) + ok = 1; + } + + if (cert) + X509_free(cert); + + if (ok) + return 1; + else { + fprintf(stderr, "FQDN (%s) verification failed\n", host); + return -1; + } +} diff -ruN netcat-0.7.1/src/sslutils.h netcat-0.7.1.new/src/sslutils.h --- netcat-0.7.1/src/sslutils.h 1969-12-31 21:00:00.000000000 -0300 +++ netcat-0.7.1.new/src/sslutils.h 2004-02-22 15:34:14.000000000 -0300 @@ -0,0 +1,15 @@ +#ifndef SSLUT_H +#define SSLUT_H + +#include "openssl/ssl.h" + +int ssl_client_init (SSL **ssl, SSL_CTX **ctx, char *CAfile, char *CApath); +int ssl_server_init (SSL **ssl, SSL_CTX **ctx, char *certfile, char *keyfile); +int ssl_client_handshake(SSL *ssl, int socket); +int ssl_server_handshake(SSL *ssl, int socket); +int ssl_read_write(SSL *ssl, int sockin, int sockprint, int sockout); +int ssl_check_hostname(SSL *ssl, char *host); +void ssl_shutdown(SSL_CTX **ctx, SSL **ssl); + +#endif +