]> The Tcpdump Group git mirrors - libpcap/commitdiff
TLS for rpcap: also encrypt the control socket
authorCedric Cellier <[email protected]>
Fri, 25 May 2018 17:22:47 +0000 (19:22 +0200)
committerCedric Cellier <[email protected]>
Thu, 13 Sep 2018 06:26:46 +0000 (08:26 +0200)
This patch also encode the control sockets in adition to the data
socket. Clients performs a TLS handshake when the scheme is rpcaps://
rather than rpcap://. Both active and passive modes are supported, but
transfert via UDP is not (yet) supported (the lib returns an error in
that case).

I did some adaptation to the windows code but couldn't tested so for all
I know it may not even compile.

Also tried to fix the indentation.

13 files changed:
pcap-int.h
pcap-rpcap.c
pcap.c
pcap/pcap.h
rpcap-protocol.c
rpcap-protocol.h
rpcapd/daemon.c
rpcapd/daemon.h
rpcapd/rpcapd.c
sockutils.c
sockutils.h
sslutils.c
sslutils.h

index 99e7af789289a0a2c265d3108828be60a559d053..243e7831429148f2a9bbd6fe24439332c34919cc 100644 (file)
@@ -526,6 +526,13 @@ int        install_bpf_program(pcap_t *, struct bpf_program *);
 
 int    pcap_strcasecmp(const char *, const char *);
 
+/*
+ * Internal interface for pcap_parsesrcstr with the additional bit of
+ * information regarding SSL support (rpcap:// vs rpcaps://)
+ */
+int pcap_parsesrcstr_ex(const char *source, int *type, char *host, char *port,
+                        char *name, unsigned char *uses_ssl, char *errbuf);
+
 #ifdef YYDEBUG
 extern int pcap_debug;
 #endif
index 48376e4034ca565bc1c71db03b5b897ef0451297..83af582b590f7bb2744709ee89df4fdb1f2b1fe9 100644 (file)
@@ -87,6 +87,7 @@ struct activehosts
 {
        struct sockaddr_storage host;
        SOCKET sockctrl;
+       SSL *ssl;
        uint8 protocol_version;
        struct activehosts *next;
 };
@@ -115,14 +116,13 @@ struct pcap_rpcap {
 
        SOCKET rmt_sockctrl;            /* socket ID of the socket used for the control connection */
        SOCKET rmt_sockdata;            /* socket ID of the socket used for the data connection */
-#ifdef HAVE_OPENSSL
-       SSL *ssl;                       /* To transport rmt_sockdata via TLS */
-#endif
+       SSL *ctrl_ssl, *data_ssl;       /* optional transport of rmt_sockctrl and rmt_sockdata via TLS */
        int rmt_flags;                  /* we have to save flags, since they are passed by the pcap_open_live(), but they are used by the pcap_startcapture() */
        int rmt_capstarted;             /* 'true' if the capture is already started (needed to knoe if we have to call the pcap_startcapture() */
        char *currentfilter;            /* Pointer to a buffer (allocated at run-time) that stores the current filter. Needed when flag PCAP_OPENFLAG_NOCAPTURE_RPCAP is turned on. */
 
        uint8 protocol_version;         /* negotiated protocol version */
+       uint8 uses_ssl;                         /* User asked for rpcaps scheme */
 
        unsigned int TotNetDrops;       /* keeps the number of packets that have been dropped by the network */
 
@@ -162,14 +162,14 @@ static void pcap_save_current_filter_rpcap(pcap_t *fp, const char *filter);
 static int pcap_setfilter_rpcap(pcap_t *fp, struct bpf_program *prog);
 static int pcap_setsampling_remote(pcap_t *fp);
 static int pcap_startcapture_remote(pcap_t *fp);
-static int rpcap_sendauth(SOCKET sock, uint8 *ver, struct pcap_rmtauth *auth, char *errbuf);
-static int rpcap_recv_msg_header(SOCKET sock, struct rpcap_header *header, char *errbuf);
-static int rpcap_check_msg_ver(SOCKET sock, uint8 expected_ver, struct rpcap_header *header, char *errbuf);
-static int rpcap_check_msg_type(SOCKET sock, uint8 request_type, struct rpcap_header *header, uint16 *errcode, char *errbuf);
-static int rpcap_process_msg_header(SOCKET sock, uint8 ver, uint8 request_type, struct rpcap_header *header, char *errbuf);
-static int rpcap_recv(SOCKET sock, void *buffer, size_t toread, uint32 *plen, char *errbuf);
-static void rpcap_msg_err(SOCKET sockctrl, uint32 plen, char *remote_errbuf);
-static int rpcap_discard(SOCKET sock, uint32 len, char *errbuf);
+static int rpcap_sendauth(SOCKET sock, SSL *, uint8 *ver, struct pcap_rmtauth *auth, char *errbuf);
+static int rpcap_recv_msg_header(SOCKET sock, SSL *, struct rpcap_header *header, char *errbuf);
+static int rpcap_check_msg_ver(SOCKET sock, SSL *, uint8 expected_ver, struct rpcap_header *header, char *errbuf);
+static int rpcap_check_msg_type(SOCKET sock, SSL *, uint8 request_type, struct rpcap_header *header, uint16 *errcode, char *errbuf);
+static int rpcap_process_msg_header(SOCKET sock, SSL *, uint8 ver, uint8 request_type, struct rpcap_header *header, char *errbuf);
+static int rpcap_recv(SOCKET sock, SSL *, void *buffer, size_t toread, uint32 *plen, char *errbuf);
+static void rpcap_msg_err(SOCKET sockctrl, SSL *, uint32 plen, char *remote_errbuf);
+static int rpcap_discard(SOCKET sock, SSL *, uint32 len, char *errbuf);
 static int rpcap_read_packet_msg(struct pcap_rpcap const *, pcap_t *p, size_t size);
 
 /****************************************************
@@ -383,7 +383,7 @@ static int pcap_read_nocb_remote(pcap_t *p, struct pcap_pkthdr *pkt_header, u_ch
        struct rpcap_pkthdr *net_pkt_header;    /* header of the packet, from the message */
        u_char *net_pkt_data;                   /* packet data from the message */
        uint32 plen;
-       int retval;                             /* generic return value */
+       int retval = 0;                         /* generic return value */
        int msglen;
 
        /* Structures needed for the select() call */
@@ -400,7 +400,7 @@ static int pcap_read_nocb_remote(pcap_t *p, struct pcap_pkthdr *pkt_header, u_ch
 #ifdef HAVE_OPENSSL
        /* Check if we still have bytes available in the last decoded TLS record.
         * If that's the case, we know SSL_read will not block. */
-       retval = pr->ssl && SSL_pending(pr->ssl) > 0;
+       retval = pr->data_ssl && SSL_pending(pr->data_ssl) > 0;
 #endif
        if (! retval)
        {
@@ -444,7 +444,7 @@ static int pcap_read_nocb_remote(pcap_t *p, struct pcap_pkthdr *pkt_header, u_ch
        if (pr->rmt_flags & PCAP_OPENFLAG_DATATX_UDP)
        {
                /* Read the entire message from the network */
-               msglen = sock_recv_dgram(pr->rmt_sockdata, p->buffer,
+               msglen = sock_recv_dgram(pr->rmt_sockdata, pr->data_ssl, p->buffer,
                    p->bufsize, p->errbuf, PCAP_ERRBUF_SIZE);
                if (msglen == -1)
                {
@@ -549,7 +549,7 @@ static int pcap_read_nocb_remote(pcap_t *p, struct pcap_pkthdr *pkt_header, u_ch
        /*
         * Did the server specify the version we negotiated?
         */
-       if (rpcap_check_msg_ver(pr->rmt_sockdata, pr->protocol_version,
+       if (rpcap_check_msg_ver(pr->rmt_sockdata, pr->data_ssl, pr->protocol_version,
            header, p->errbuf) == -1)
        {
                return 0;       /* Return 'no packets received' */
@@ -729,7 +729,7 @@ static void pcap_cleanup_rpcap(pcap_t *fp)
                 * we're closing this pcap_t, and have no place to report
                 * the error.  No reply is sent to this message.
                 */
-               (void)sock_send(pr->rmt_sockctrl, (char *)&header,
+               (void)sock_send(pr->rmt_sockctrl, pr->ctrl_ssl, (char *)&header,
                    sizeof(struct rpcap_header), NULL, 0);
        }
        else
@@ -742,7 +742,7 @@ static void pcap_cleanup_rpcap(pcap_t *fp)
                 * as we're closing this pcap_t, and have no place to
                 * report the error.
                 */
-               if (sock_send(pr->rmt_sockctrl, (char *)&header,
+               if (sock_send(pr->rmt_sockctrl, pr->ctrl_ssl, (char *)&header,
                    sizeof(struct rpcap_header), NULL, 0) == 0)
                {
                        /*
@@ -750,11 +750,11 @@ static void pcap_cleanup_rpcap(pcap_t *fp)
                         * as we're closing this pcap_t, and have no
                         * place to report the error.
                         */
-                       if (rpcap_process_msg_header(pr->rmt_sockctrl,
+                       if (rpcap_process_msg_header(pr->rmt_sockctrl, pr->ctrl_ssl,
                            pr->protocol_version, RPCAP_MSG_ENDCAP_REQ,
                            &header, NULL) == 0)
                        {
-                               (void)rpcap_discard(pr->rmt_sockctrl,
+                               (void)rpcap_discard(pr->rmt_sockctrl, pr->ctrl_ssl,
                                    header.plen, NULL);
                        }
                }
@@ -762,14 +762,31 @@ static void pcap_cleanup_rpcap(pcap_t *fp)
 
        if (pr->rmt_sockdata)
        {
+#ifdef HAVE_OPENSSL
+               if (pr->data_ssl)
+               {
+                       SSL_free(pr->data_ssl); // Has to be done before the socket is closed
+                       pr->data_ssl = NULL;
+               }
+#endif
                sock_close(pr->rmt_sockdata, NULL, 0);
                pr->rmt_sockdata = 0;
        }
 
        if ((!active) && (pr->rmt_sockctrl))
+       {
+#ifdef HAVE_OPENSSL
+               if (pr->ctrl_ssl)
+               {
+                       SSL_free(pr->ctrl_ssl);
+                       pr->ctrl_ssl = NULL;
+               }
+#endif
                sock_close(pr->rmt_sockctrl, NULL, 0);
+       }
 
        pr->rmt_sockctrl = 0;
+       pr->ctrl_ssl = NULL;
 
        if (pr->currentfilter)
        {
@@ -892,19 +909,19 @@ static struct pcap_stat *rpcap_stats_rpcap(pcap_t *p, struct pcap_stat *ps, int
            RPCAP_MSG_STATS_REQ, 0, 0);
 
        /* Send the PCAP_STATS command */
-       if (sock_send(pr->rmt_sockctrl, (char *)&header,
+       if (sock_send(pr->rmt_sockctrl, pr->ctrl_ssl, (char *)&header,
            sizeof(struct rpcap_header), p->errbuf, PCAP_ERRBUF_SIZE) < 0)
                return NULL;            /* Unrecoverable network error */
 
        /* Receive and process the reply message header. */
-       if (rpcap_process_msg_header(pr->rmt_sockctrl, pr->protocol_version,
+       if (rpcap_process_msg_header(pr->rmt_sockctrl, pr->ctrl_ssl, pr->protocol_version,
            RPCAP_MSG_STATS_REQ, &header, p->errbuf) == -1)
                return NULL;            /* Error */
 
        plen = header.plen;
 
        /* Read the reply body */
-       if (rpcap_recv(pr->rmt_sockctrl, (char *)&netstats,
+       if (rpcap_recv(pr->rmt_sockctrl, pr->ctrl_ssl, (char *)&netstats,
            sizeof(struct rpcap_stats), &plen, p->errbuf) == -1)
                goto error;
 
@@ -921,7 +938,7 @@ static struct pcap_stat *rpcap_stats_rpcap(pcap_t *p, struct pcap_stat *ps, int
 #endif /* _WIN32 */
 
        /* Discard the rest of the message. */
-       if (rpcap_discard(pr->rmt_sockctrl, plen, p->errbuf) == -1)
+       if (rpcap_discard(pr->rmt_sockctrl, pr->ctrl_ssl, plen, p->errbuf) == -1)
                goto error_nodiscard;
 
        return ps;
@@ -932,7 +949,7 @@ error:
         * We already reported an error; if this gets an error, just
         * drive on.
         */
-       (void)rpcap_discard(pr->rmt_sockctrl, plen, NULL);
+       (void)rpcap_discard(pr->rmt_sockctrl, pr->ctrl_ssl, plen, NULL);
 
 error_nodiscard:
        return NULL;
@@ -1052,11 +1069,9 @@ static int pcap_startcapture_remote(pcap_t *fp)
        int sockbufsize = 0;
        uint32 server_sockbufsize;
 
-#ifdef HAVE_OPENSSL
-       // Take the opportunity to clear pr->ssl before any goto error,
+       // Take the opportunity to clear pr->data_ssl before any goto error,
        // as it seems pr->priv is not zeroed after its malloced.
-       pr->ssl = NULL;
-#endif
+       pr->data_ssl = NULL;
 
        /*
         * Let's check if sampling has been required.
@@ -1197,18 +1212,18 @@ static int pcap_startcapture_remote(pcap_t *fp)
        if (pcap_pack_bpffilter(fp, &sendbuf[sendbufidx], &sendbufidx, &fp->fcode))
                goto error_nodiscard;
 
-       if (sock_send(pr->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf,
+       if (sock_send(pr->rmt_sockctrl, pr->ctrl_ssl, sendbuf, sendbufidx, fp->errbuf,
            PCAP_ERRBUF_SIZE) < 0)
                goto error_nodiscard;
 
        /* Receive and process the reply message header. */
-       if (rpcap_process_msg_header(pr->rmt_sockctrl, pr->protocol_version,
+       if (rpcap_process_msg_header(pr->rmt_sockctrl, pr->ctrl_ssl, pr->protocol_version,
            RPCAP_MSG_STARTCAP_REQ, &header, fp->errbuf) == -1)
                goto error_nodiscard;
 
        plen = header.plen;
 
-       if (rpcap_recv(pr->rmt_sockctrl, (char *)&startcapreply,
+       if (rpcap_recv(pr->rmt_sockctrl, pr->ctrl_ssl, (char *)&startcapreply,
            sizeof(struct rpcap_startcapreply), &plen, fp->errbuf) == -1)
                goto error;
 
@@ -1268,9 +1283,10 @@ static int pcap_startcapture_remote(pcap_t *fp)
        pr->rmt_sockdata = sockdata;
 
 #ifdef HAVE_OPENSSL
-       if (startcapreply.ssl) {
-               pr->ssl = ssl_promotion(0, sockdata, fp->errbuf, PCAP_ERRBUF_SIZE);
-               if (! pr->ssl) goto error;
+       if (pr->uses_ssl)
+       {
+               pr->data_ssl = ssl_promotion(0, sockdata, fp->errbuf, PCAP_ERRBUF_SIZE);
+               if (! pr->data_ssl) goto error;
        }
 #endif
 
@@ -1361,7 +1377,7 @@ static int pcap_startcapture_remote(pcap_t *fp)
        fp->cc = 0;
 
        /* Discard the rest of the message. */
-       if (rpcap_discard(pr->rmt_sockctrl, plen, fp->errbuf) == -1)
+       if (rpcap_discard(pr->rmt_sockctrl, pr->ctrl_ssl, plen, fp->errbuf) == -1)
                goto error_nodiscard;
 
        /*
@@ -1401,13 +1417,14 @@ error:
         * We already reported an error; if this gets an error, just
         * drive on.
         */
-       (void)rpcap_discard(pr->rmt_sockctrl, plen, NULL);
+       (void)rpcap_discard(pr->rmt_sockctrl, pr->ctrl_ssl, plen, NULL);
 
 error_nodiscard:
 #ifdef HAVE_OPENSSL
-       if (pr->ssl) {
-               SSL_free(pr->ssl);  // Have to be done before the socket is closed
-               pr->ssl = NULL;
+       if (pr->data_ssl)
+       {
+               SSL_free(pr->data_ssl);  // Have to be done before the socket is closed
+               pr->data_ssl = NULL;
        }
 #endif
 
@@ -1415,7 +1432,16 @@ error_nodiscard:
                sock_close(sockdata, NULL, 0);
 
        if (!active)
+       {
+#ifdef HAVE_OPENSSL
+               if (pr->ctrl_ssl)
+               {
+                       SSL_free(pr->ctrl_ssl);
+                       pr->ctrl_ssl = NULL;
+               }
+#endif
                sock_close(pr->rmt_sockctrl, NULL, 0);
+       }
 
        if (addrinfo != NULL)
                freeaddrinfo(addrinfo);
@@ -1548,19 +1574,19 @@ static int pcap_updatefilter_remote(pcap_t *fp, struct bpf_program *prog)
        if (pcap_pack_bpffilter(fp, &sendbuf[sendbufidx], &sendbufidx, prog))
                return -1;
 
-       if (sock_send(pr->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf,
+       if (sock_send(pr->rmt_sockctrl, pr->ctrl_ssl, sendbuf, sendbufidx, fp->errbuf,
            PCAP_ERRBUF_SIZE) < 0)
                return -1;
 
        /* Receive and process the reply message header. */
-       if (rpcap_process_msg_header(pr->rmt_sockctrl, pr->protocol_version,
+       if (rpcap_process_msg_header(pr->rmt_sockctrl, pr->ctrl_ssl, pr->protocol_version,
            RPCAP_MSG_UPDATEFILTER_REQ, &header, fp->errbuf) == -1)
                return -1;
 
        /*
         * It shouldn't have any contents; discard it if it does.
         */
-       if (rpcap_discard(pr->rmt_sockctrl, header.plen, fp->errbuf) == -1)
+       if (rpcap_discard(pr->rmt_sockctrl, pr->ctrl_ssl, header.plen, fp->errbuf) == -1)
                return -1;
 
        return 0;
@@ -1793,19 +1819,19 @@ static int pcap_setsampling_remote(pcap_t *fp)
        sampling_pars->method = (uint8)fp->rmt_samp.method;
        sampling_pars->value = (uint16)htonl(fp->rmt_samp.value);
 
-       if (sock_send(pr->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf,
+       if (sock_send(pr->rmt_sockctrl, pr->ctrl_ssl, sendbuf, sendbufidx, fp->errbuf,
            PCAP_ERRBUF_SIZE) < 0)
                return -1;
 
        /* Receive and process the reply message header. */
-       if (rpcap_process_msg_header(pr->rmt_sockctrl, pr->protocol_version,
+       if (rpcap_process_msg_header(pr->rmt_sockctrl, pr->ctrl_ssl, pr->protocol_version,
            RPCAP_MSG_SETSAMPLING_REQ, &header, fp->errbuf) == -1)
                return -1;
 
        /*
         * It shouldn't have any contents; discard it if it does.
         */
-       if (rpcap_discard(pr->rmt_sockctrl, header.plen, fp->errbuf) == -1)
+       if (rpcap_discard(pr->rmt_sockctrl, pr->ctrl_ssl, header.plen, fp->errbuf) == -1)
                return -1;
 
        return 0;
@@ -1840,7 +1866,7 @@ static int pcap_setsampling_remote(pcap_t *fp)
  * \return '0' if everything is fine, '-1' for an error.  For errors,
  * an error message string is returned in the 'errbuf' variable.
  */
-static int rpcap_doauth(SOCKET sockctrl, uint8 *ver, struct pcap_rmtauth *auth, char *errbuf)
+static int rpcap_doauth(SOCKET sockctrl, SSL *ssl, uint8 *ver, struct pcap_rmtauth *auth, char *errbuf)
 {
        int status;
 
@@ -1850,7 +1876,7 @@ static int rpcap_doauth(SOCKET sockctrl, uint8 *ver, struct pcap_rmtauth *auth,
         * First try with the maximum version number we support.
         */
        *ver = RPCAP_MAX_VERSION;
-       status = rpcap_sendauth(sockctrl, ver, auth, errbuf);
+       status = rpcap_sendauth(sockctrl, ssl, ver, auth, errbuf);
        if (status == 0)
        {
                //
@@ -1871,7 +1897,7 @@ static int rpcap_doauth(SOCKET sockctrl, uint8 *ver, struct pcap_rmtauth *auth,
         * support that version.  *ver has been set to that version; try
         * authenticating again with that version.
         */
-       status = rpcap_sendauth(sockctrl, ver, auth, errbuf);
+       status = rpcap_sendauth(sockctrl, ssl, ver, auth, errbuf);
        if (status == 0)
        {
                //
@@ -1921,7 +1947,7 @@ static int rpcap_doauth(SOCKET sockctrl, uint8 *ver, struct pcap_rmtauth *auth,
  * support, or '-1' for other errors.  For errors, an error message string
  * is returned in the 'errbuf' variable.
  */
-static int rpcap_sendauth(SOCKET sock, uint8 *ver, struct pcap_rmtauth *auth, char *errbuf)
+static int rpcap_sendauth(SOCKET sock, SSL *ssl, uint8 *ver, struct pcap_rmtauth *auth, char *errbuf)
 {
        char sendbuf[RPCAP_NETBUF_SIZE];        /* temporary buffer in which data that has to be sent is buffered */
        int sendbufidx = 0;                     /* index which keeps the number of bytes currently buffered */
@@ -2019,14 +2045,14 @@ static int rpcap_sendauth(SOCKET sock, uint8 *ver, struct pcap_rmtauth *auth, ch
                rpauth->slen2 = htons(rpauth->slen2);
        }
 
-       if (sock_send(sock, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) < 0)
+       if (sock_send(sock, ssl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) < 0)
                return -1;
 
        /* Receive the reply */
-       if (rpcap_recv_msg_header(sock, &header, errbuf) == -1)
+       if (rpcap_recv_msg_header(sock, ssl, &header, errbuf) == -1)
                return -1;
 
-       if (rpcap_check_msg_type(sock, RPCAP_MSG_AUTH_REQ, &header,
+       if (rpcap_check_msg_type(sock, ssl, RPCAP_MSG_AUTH_REQ, &header,
            &errcode, errbuf) == -1)
        {
                /* Error message - or something else, which is a protocol error. */
@@ -2071,7 +2097,7 @@ static int rpcap_sendauth(SOCKET sock, uint8 *ver, struct pcap_rmtauth *auth, ch
         *
         * Discard the rest of it.
         */
-       if (rpcap_discard(sock, header.plen, errbuf) == -1)
+       if (rpcap_discard(sock, ssl, header.plen, errbuf) == -1)
                return -1;
 
        return 0;
@@ -2142,6 +2168,7 @@ pcap_t *pcap_open_rpcap(const char *source, int snaplen, int flags, int read_tim
        struct activehosts *activeconn;         /* active connection, if there is one */
        int error;                              /* '1' if rpcap_remoteact_getsock returned an error */
        SOCKET sockctrl;
+       SSL *ssl = NULL;
        uint8 protocol_version;                 /* negotiated protocol version */
        int active;
        uint32 plen;
@@ -2190,7 +2217,7 @@ pcap_t *pcap_open_rpcap(const char *source, int snaplen, int flags, int read_tim
         * You must have a valid source string even if we're in active mode, because otherwise
         * the call to the following function will fail.
         */
-       if (pcap_parsesrcstr(fp->opt.device, &retval, host, ctrlport, iface, errbuf) == -1)
+       if (pcap_parsesrcstr_ex(fp->opt.device, &retval, host, ctrlport, iface, &pr->uses_ssl, errbuf) == -1)
        {
                pcap_close(fp);
                return NULL;
@@ -2217,12 +2244,14 @@ pcap_t *pcap_open_rpcap(const char *source, int snaplen, int flags, int read_tim
        activeconn = rpcap_remoteact_getsock(host, &error, errbuf);
        if (activeconn != NULL)
        {
+               active = 1;
                sockctrl = activeconn->sockctrl;
+               ssl = activeconn->ssl;
                protocol_version = activeconn->protocol_version;
-               active = 1;
        }
        else
        {
+               active = 0;  // Must be set before jumping to error
                struct addrinfo hints;                  /* temp, needed to open a socket connection */
                struct addrinfo *addrinfo;              /* temp, needed to open a socket connection */
 
@@ -2271,13 +2300,24 @@ pcap_t *pcap_open_rpcap(const char *source, int snaplen, int flags, int read_tim
                /* addrinfo is no longer used */
                freeaddrinfo(addrinfo);
 
-               if (rpcap_doauth(sockctrl, &protocol_version, auth, errbuf) == -1)
+               if (pr->uses_ssl)
                {
-                       sock_close(sockctrl, NULL, 0);
+#ifdef HAVE_OPENSSL
+                       ssl = ssl_promotion(0, sockctrl, errbuf, PCAP_ERRBUF_SIZE);
+                       if (! ssl)
+                       {
+                               pcap_close(fp);
+                               return NULL;
+                       }
+#else
+                       pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "No TLS support");
                        pcap_close(fp);
                        return NULL;
+#endif
                }
-               active = 0;
+
+               if (rpcap_doauth(sockctrl, ssl, &protocol_version, auth, errbuf) == -1)
+                       goto error_nodiscard;
        }
 
        /*
@@ -2295,28 +2335,29 @@ pcap_t *pcap_open_rpcap(const char *source, int snaplen, int flags, int read_tim
                RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE))
                goto error_nodiscard;
 
-       if (sock_send(sockctrl, sendbuf, sendbufidx, errbuf,
+       if (sock_send(sockctrl, ssl, sendbuf, sendbufidx, errbuf,
            PCAP_ERRBUF_SIZE) < 0)
                goto error_nodiscard;
 
        /* Receive and process the reply message header. */
-       if (rpcap_process_msg_header(sockctrl, protocol_version,
+       if (rpcap_process_msg_header(sockctrl, ssl, protocol_version,
            RPCAP_MSG_OPEN_REQ, &header, errbuf) == -1)
                goto error_nodiscard;
        plen = header.plen;
 
        /* Read the reply body */
-       if (rpcap_recv(sockctrl, (char *)&openreply,
+       if (rpcap_recv(sockctrl, ssl, (char *)&openreply,
            sizeof(struct rpcap_openreply), &plen, errbuf) == -1)
                goto error;
 
        /* Discard the rest of the message, if there is any. */
-       if (rpcap_discard(sockctrl, plen, errbuf) == -1)
+       if (rpcap_discard(sockctrl, ssl, plen, errbuf) == -1)
                goto error_nodiscard;
 
        /* Set proper fields into the pcap_t struct */
        fp->linktype = ntohl(openreply.linktype);
        pr->rmt_sockctrl = sockctrl;
+       pr->ctrl_ssl = ssl;
        pr->protocol_version = protocol_version;
        pr->rmt_clientside = 1;
 
@@ -2348,11 +2389,16 @@ error:
         * We already reported an error; if this gets an error, just
         * drive on.
         */
-       (void)rpcap_discard(sockctrl, plen, NULL);
+       (void)rpcap_discard(sockctrl, pr->ctrl_ssl, plen, NULL);
 
 error_nodiscard:
        if (!active)
+       {
+#ifdef HAVE_OPENSSL
+               if (ssl) SSL_free(ssl);  // Have to be done before the socket is closed
+#endif
                sock_close(sockctrl, NULL, 0);
+       }
 
        pcap_close(fp);
        return NULL;
@@ -2380,6 +2426,7 @@ pcap_findalldevs_ex_remote(char *source, struct pcap_rmtauth *auth, pcap_if_t **
        int error;                      /* '1' if rpcap_remoteact_getsock returned an error */
        uint8 protocol_version;         /* protocol version */
        SOCKET sockctrl;                /* socket descriptor of the control connection */
+       SSL *ssl = NULL;                /* optional SSL handler for sockctrl */
        uint32 plen;
        struct rpcap_header header;     /* structure that keeps the general header of the rpcap protocol */
        int i, j;               /* temp variables */
@@ -2387,6 +2434,7 @@ pcap_findalldevs_ex_remote(char *source, struct pcap_rmtauth *auth, pcap_if_t **
        int active;                     /* 'true' if we the other end-party is in active mode */
        int type;
        char host[PCAP_BUF_SIZE], port[PCAP_BUF_SIZE];
+       uint8 uses_ssl;
        char tmpstring[PCAP_BUF_SIZE + 1];              /* Needed to convert names and descriptions from 'old' syntax to the 'new' one */
        pcap_if_t *lastdev;     /* Last device in the pcap_if_t list */
        pcap_if_t *dev;         /* Device we're adding to the pcap_if_t list */
@@ -2396,7 +2444,7 @@ pcap_findalldevs_ex_remote(char *source, struct pcap_rmtauth *auth, pcap_if_t **
        lastdev = NULL;
 
        /* Retrieve the needed data for getting adapter list */
-       if (pcap_parsesrcstr(source, &type, host, port, NULL, errbuf) == -1)
+       if (pcap_parsesrcstr_ex(source, &type, host, port, NULL, &uses_ssl, errbuf) == -1)
                return -1;
 
        /* Warning: this call can be the first one called by the user. */
@@ -2408,12 +2456,14 @@ pcap_findalldevs_ex_remote(char *source, struct pcap_rmtauth *auth, pcap_if_t **
        activeconn = rpcap_remoteact_getsock(host, &error, errbuf);
        if (activeconn != NULL)
        {
+               active = 1;
                sockctrl = activeconn->sockctrl;
+               ssl = activeconn->ssl;
                protocol_version = activeconn->protocol_version;
-               active = 1;
        }
        else
        {
+               active = 0;
                struct addrinfo hints;          /* temp variable needed to resolve hostnames into to socket representation */
                struct addrinfo *addrinfo;      /* temp variable needed to resolve hostnames into to socket representation */
 
@@ -2455,24 +2505,42 @@ pcap_findalldevs_ex_remote(char *source, struct pcap_rmtauth *auth, pcap_if_t **
                freeaddrinfo(addrinfo);
                addrinfo = NULL;
 
-               if (rpcap_doauth(sockctrl, &protocol_version, auth, errbuf) == -1)
+               if (uses_ssl)
                {
+#ifdef HAVE_OPENSSL
+                       ssl = ssl_promotion(0, sockctrl, errbuf, PCAP_ERRBUF_SIZE);
+                       if (! ssl)
+                       {
+                               sock_close(sockctrl, NULL, 0);
+                               return -1;
+                       }
+#else
+                       pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "No TLS support");
+                       sock_close(sockctrl, NULL, 0);;
+                       return -1;
+#endif
+               }
+
+               if (rpcap_doauth(sockctrl, ssl, &protocol_version, auth, errbuf) == -1)
+               {
+#ifdef HAVE_OPENSSL
+                       if (ssl) SSL_free(ssl); // Must be done before the socket is closed
+#endif
                        sock_close(sockctrl, NULL, 0);
                        return -1;
                }
-               active = 0;
        }
 
        /* RPCAP findalldevs command */
        rpcap_createhdr(&header, protocol_version, RPCAP_MSG_FINDALLIF_REQ,
            0, 0);
 
-       if (sock_send(sockctrl, (char *)&header, sizeof(struct rpcap_header),
+       if (sock_send(sockctrl, ssl, (char *)&header, sizeof(struct rpcap_header),
            errbuf, PCAP_ERRBUF_SIZE) < 0)
                goto error_nodiscard;
 
        /* Receive and process the reply message header. */
-       if (rpcap_process_msg_header(sockctrl, protocol_version,
+       if (rpcap_process_msg_header(sockctrl, ssl, protocol_version,
            RPCAP_MSG_FINDALLIF_REQ, &header, errbuf) == -1)
                goto error_nodiscard;
 
@@ -2492,7 +2560,7 @@ pcap_findalldevs_ex_remote(char *source, struct pcap_rmtauth *auth, pcap_if_t **
                tmpstring2[PCAP_BUF_SIZE] = 0;
 
                /* receive the findalldevs structure from remote host */
-               if (rpcap_recv(sockctrl, (char *)&findalldevs_if,
+               if (rpcap_recv(sockctrl, ssl, (char *)&findalldevs_if,
                    sizeof(struct rpcap_findalldevs_if), &plen, errbuf) == -1)
                        goto error;
 
@@ -2541,7 +2609,7 @@ pcap_findalldevs_ex_remote(char *source, struct pcap_rmtauth *auth, pcap_if_t **
                        }
 
                        /* Retrieve adapter name */
-                       if (rpcap_recv(sockctrl, tmpstring,
+                       if (rpcap_recv(sockctrl, ssl, tmpstring,
                            findalldevs_if.namelen, &plen, errbuf) == -1)
                                goto error;
 
@@ -2574,7 +2642,7 @@ pcap_findalldevs_ex_remote(char *source, struct pcap_rmtauth *auth, pcap_if_t **
                        }
 
                        /* Retrieve adapter description */
-                       if (rpcap_recv(sockctrl, tmpstring,
+                       if (rpcap_recv(sockctrl, ssl, tmpstring,
                            findalldevs_if.desclen, &plen, errbuf) == -1)
                                goto error;
 
@@ -2607,7 +2675,7 @@ pcap_findalldevs_ex_remote(char *source, struct pcap_rmtauth *auth, pcap_if_t **
                        struct rpcap_findalldevs_ifaddr ifaddr;
 
                        /* Retrieve the interface addresses */
-                       if (rpcap_recv(sockctrl, (char *)&ifaddr,
+                       if (rpcap_recv(sockctrl, ssl, (char *)&ifaddr,
                            sizeof(struct rpcap_findalldevs_ifaddr),
                            &plen, errbuf) == -1)
                                goto error;
@@ -2681,13 +2749,16 @@ pcap_findalldevs_ex_remote(char *source, struct pcap_rmtauth *auth, pcap_if_t **
        }
 
        /* Discard the rest of the message. */
-       if (rpcap_discard(sockctrl, plen, errbuf) == 1)
+       if (rpcap_discard(sockctrl, ssl, plen, errbuf) == 1)
                goto error_nodiscard;
 
        /* Control connection has to be closed only in case the remote machine is in passive mode */
        if (!active)
        {
                /* DO not send RPCAP_CLOSE, since we did not open a pcap_t; no need to free resources */
+#ifdef HAVE_OPENSSL
+               if (ssl) SSL_free(ssl); // Has to be done before the socket is closed
+#endif
                if (sock_close(sockctrl, errbuf, PCAP_ERRBUF_SIZE))
                        return -1;
        }
@@ -2711,12 +2782,17 @@ error:
         *
         * Checks if all the data has been read; if not, discard the data in excess
         */
-       (void) rpcap_discard(sockctrl, plen, NULL);
+       (void) rpcap_discard(sockctrl, ssl, plen, NULL);
 
 error_nodiscard:
        /* Control connection has to be closed only in case the remote machine is in passive mode */
        if (!active)
+       {
+#ifdef HAVE_OPENSSL
+               if (ssl) SSL_free(ssl); // Has to be done before the socket is closed
+#endif
                sock_close(sockctrl, NULL, 0);
+       }
 
        /* To avoid inconsistencies in the number of sock_init() */
        sock_cleanup();
@@ -2742,10 +2818,12 @@ SOCKET pcap_remoteact_accept(const char *address, const char *port, const char *
        struct sockaddr_storage from;   /* generic sockaddr_storage variable */
        socklen_t fromlen;                              /* keeps the length of the sockaddr_storage variable */
        SOCKET sockctrl;                                /* keeps the main socket identifier */
+       SSL *ssl = NULL;       /* Optional SSL handler for sockctrl */
        uint8 protocol_version;                 /* negotiated protocol version */
        struct activehosts *temp, *prev;        /* temp var needed to scan he host list chain */
 
        *connectinghost = 0;            /* just in case */
+       uint8 uses_ssl = 0;  // TODO: how to get this info and how to return the SSL*?
 
        /* Prepare to open a new server socket */
        memset(&hints, 0, sizeof(struct addrinfo));
@@ -2802,11 +2880,31 @@ SOCKET pcap_remoteact_accept(const char *address, const char *port, const char *
                return (SOCKET)-2;
        }
 
+       /* Promote to SSL early before any error message may be sent */
+       if (uses_ssl)
+       {
+#ifdef HAVE_OPENSSL
+               ssl = ssl_promotion(0, sockctrl, errbuf, PCAP_ERRBUF_SIZE);
+               if (! ssl)
+               {
+                       sock_close(sockctrl, NULL, 0);
+                       return (SOCKET)-1;
+               }
+#else
+               pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "No TLS support");
+               sock_close(sockctrl, NULL, 0);
+               return (SOCKET)-1;
+#endif
+       }
+
        /* Get the numeric for of the name of the connecting host */
        if (getnameinfo((struct sockaddr *) &from, fromlen, connectinghost, RPCAP_HOSTLIST_SIZE, NULL, 0, NI_NUMERICHOST))
        {
                sock_geterror("getnameinfo(): ", errbuf, PCAP_ERRBUF_SIZE);
-               rpcap_senderror(sockctrl, 0, PCAP_ERR_REMOTEACCEPT, errbuf, NULL);
+               rpcap_senderror(sockctrl, ssl, 0, PCAP_ERR_REMOTEACCEPT, errbuf, NULL);
+#ifdef HAVE_OPENSSL
+               if (ssl) SSL_free(ssl);
+#endif
                sock_close(sockctrl, NULL, 0);
                return (SOCKET)-1;
        }
@@ -2814,7 +2912,10 @@ SOCKET pcap_remoteact_accept(const char *address, const char *port, const char *
        /* checks if the connecting host is among the ones allowed */
        if (sock_check_hostlist((char *)hostlist, RPCAP_HOSTLIST_SEP, &from, errbuf, PCAP_ERRBUF_SIZE) < 0)
        {
-               rpcap_senderror(sockctrl, 0, PCAP_ERR_REMOTEACCEPT, errbuf, NULL);
+               rpcap_senderror(sockctrl, ssl, 0, PCAP_ERR_REMOTEACCEPT, errbuf, NULL);
+#ifdef HAVE_OPENSSL
+               if (ssl) SSL_free(ssl);
+#endif
                sock_close(sockctrl, NULL, 0);
                return (SOCKET)-1;
        }
@@ -2822,10 +2923,13 @@ SOCKET pcap_remoteact_accept(const char *address, const char *port, const char *
        /*
         * Send authentication to the remote machine.
         */
-       if (rpcap_doauth(sockctrl, &protocol_version, auth, errbuf) == -1)
+       if (rpcap_doauth(sockctrl, ssl, &protocol_version, auth, errbuf) == -1)
        {
                /* Unrecoverable error. */
-               rpcap_senderror(sockctrl, 0, PCAP_ERR_REMOTEACCEPT, errbuf, NULL);
+               rpcap_senderror(sockctrl, ssl, 0, PCAP_ERR_REMOTEACCEPT, errbuf, NULL);
+#ifdef HAVE_OPENSSL
+               if (ssl) SSL_free(ssl);
+#endif
                sock_close(sockctrl, NULL, 0);
                return (SOCKET)-3;
        }
@@ -2862,13 +2966,17 @@ SOCKET pcap_remoteact_accept(const char *address, const char *port, const char *
        {
                pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
                    errno, "malloc() failed");
-               rpcap_senderror(sockctrl, protocol_version, PCAP_ERR_REMOTEACCEPT, errbuf, NULL);
+               rpcap_senderror(sockctrl, ssl, protocol_version, PCAP_ERR_REMOTEACCEPT, errbuf, NULL);
+#ifdef HAVE_OPENSSL
+               if (ssl) SSL_free(ssl);
+#endif
                sock_close(sockctrl, NULL, 0);
                return (SOCKET)-1;
        }
 
        memcpy(&temp->host, &from, fromlen);
        temp->sockctrl = sockctrl;
+       temp->ssl = ssl;
        temp->protocol_version = protocol_version;
        temp->next = NULL;
 
@@ -2915,7 +3023,7 @@ int pcap_remoteact_close(const char *host, char *errbuf)
                                 * Don't check for errors, since we're
                                 * just cleaning up.
                                 */
-                               if (sock_send(temp->sockctrl,
+                               if (sock_send(temp->sockctrl, temp->ssl,
                                    (char *)&header,
                                    sizeof(struct rpcap_header), errbuf,
                                    PCAP_ERRBUF_SIZE) < 0)
@@ -2924,12 +3032,18 @@ int pcap_remoteact_close(const char *host, char *errbuf)
                                         * Let that error be the one we
                                         * report.
                                         */
+#ifdef HAVE_OPENSSL
+                                       if (temp->ssl) SSL_free(temp->ssl);
+#endif
                                        (void)sock_close(temp->sockctrl, NULL,
                                           0);
                                        status = -1;
                                }
                                else
                                {
+#ifdef HAVE_OPENSSL
+                                       if (temp->ssl) SSL_free(temp->ssl);
+#endif
                                        if (sock_close(temp->sockctrl, errbuf,
                                           PCAP_ERRBUF_SIZE) == -1)
                                                status = -1;
@@ -3030,11 +3144,11 @@ int pcap_remoteact_list(char *hostlist, char sep, int size, char *errbuf)
 /*
  * Receive the header of a message.
  */
-static int rpcap_recv_msg_header(SOCKET sock, struct rpcap_header *header, char *errbuf)
+static int rpcap_recv_msg_header(SOCKET sock, SSL *ssl, struct rpcap_header *header, char *errbuf)
 {
        int nrecv;
 
-       nrecv = sock_recv(sock, (char *) header, sizeof(struct rpcap_header),
+       nrecv = sock_recv(sock, ssl, (char *) header, sizeof(struct rpcap_header),
            SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf,
            PCAP_ERRBUF_SIZE);
        if (nrecv == -1)
@@ -3050,7 +3164,7 @@ static int rpcap_recv_msg_header(SOCKET sock, struct rpcap_header *header, char
  * Make sure the protocol version of a received message is what we were
  * expecting.
  */
-static int rpcap_check_msg_ver(SOCKET sock, uint8 expected_ver, struct rpcap_header *header, char *errbuf)
+static int rpcap_check_msg_ver(SOCKET sock, SSL *ssl, uint8 expected_ver, struct rpcap_header *header, char *errbuf)
 {
        /*
         * Did the server specify the version we negotiated?
@@ -3060,7 +3174,7 @@ static int rpcap_check_msg_ver(SOCKET sock, uint8 expected_ver, struct rpcap_hea
                /*
                 * Discard the rest of the message.
                 */
-               if (rpcap_discard(sock, header->plen, errbuf) == -1)
+               if (rpcap_discard(sock, ssl, header->plen, errbuf) == -1)
                        return -1;
 
                /*
@@ -3081,7 +3195,7 @@ static int rpcap_check_msg_ver(SOCKET sock, uint8 expected_ver, struct rpcap_hea
  * Check the message type of a received message, which should either be
  * the expected message type or RPCAP_MSG_ERROR.
  */
-static int rpcap_check_msg_type(SOCKET sock, uint8 request_type, struct rpcap_header *header, uint16 *errcode, char *errbuf)
+static int rpcap_check_msg_type(SOCKET sock, SSL *ssl, uint8 request_type, struct rpcap_header *header, uint16 *errcode, char *errbuf)
 {
        const char *request_type_string;
        const char *msg_type_string;
@@ -3096,7 +3210,7 @@ static int rpcap_check_msg_type(SOCKET sock, uint8 request_type, struct rpcap_he
                 * Hand that error back to our caller.
                 */
                *errcode = ntohs(header->value);
-               rpcap_msg_err(sock, header->plen, errbuf);
+               rpcap_msg_err(sock, ssl, header->plen, errbuf);
                return -1;
        }
 
@@ -3115,7 +3229,7 @@ static int rpcap_check_msg_type(SOCKET sock, uint8 request_type, struct rpcap_he
                /*
                 * Discard the rest of the message.
                 */
-               if (rpcap_discard(sock, header->plen, errbuf) == -1)
+               if (rpcap_discard(sock, ssl, header->plen, errbuf) == -1)
                        return -1;
 
                /*
@@ -3151,11 +3265,11 @@ static int rpcap_check_msg_type(SOCKET sock, uint8 request_type, struct rpcap_he
 /*
  * Receive and process the header of a message.
  */
-static int rpcap_process_msg_header(SOCKET sock, uint8 expected_ver, uint8 request_type, struct rpcap_header *header, char *errbuf)
+static int rpcap_process_msg_header(SOCKET sock, SSL *ssl, uint8 expected_ver, uint8 request_type, struct rpcap_header *header, char *errbuf)
 {
        uint16 errcode;
 
-       if (rpcap_recv_msg_header(sock, header, errbuf) == -1)
+       if (rpcap_recv_msg_header(sock, ssl, header, errbuf) == -1)
        {
                /* Network error. */
                return -1;
@@ -3164,13 +3278,13 @@ static int rpcap_process_msg_header(SOCKET sock, uint8 expected_ver, uint8 reque
        /*
         * Did the server specify the version we negotiated?
         */
-       if (rpcap_check_msg_ver(sock, expected_ver, header, errbuf) == -1)
+       if (rpcap_check_msg_ver(sock, ssl, expected_ver, header, errbuf) == -1)
                return -1;
 
        /*
         * Check the message type.
         */
-       return rpcap_check_msg_type(sock, request_type, header,
+       return rpcap_check_msg_type(sock, ssl, request_type, header,
            &errcode, errbuf);
 }
 
@@ -3183,7 +3297,7 @@ static int rpcap_process_msg_header(SOCKET sock, uint8 expected_ver, uint8 reque
  * Returns 0 on success, logs a message and returns -1 on a network
  * error.
  */
-static int rpcap_recv(SOCKET sock, void *buffer, size_t toread, uint32 *plen, char *errbuf)
+static int rpcap_recv(SOCKET sock, SSL *ssl, void *buffer, size_t toread, uint32 *plen, char *errbuf)
 {
        int nread;
 
@@ -3193,7 +3307,7 @@ static int rpcap_recv(SOCKET sock, void *buffer, size_t toread, uint32 *plen, ch
                pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Message payload is too short");
                return -1;
        }
-       nread = sock_recv(sock, buffer, toread,
+       nread = sock_recv(sock, ssl, buffer, toread,
            SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf, PCAP_ERRBUF_SIZE);
        if (nread == -1)
        {
@@ -3206,7 +3320,7 @@ static int rpcap_recv(SOCKET sock, void *buffer, size_t toread, uint32 *plen, ch
 /*
  * This handles the RPCAP_MSG_ERROR message.
  */
-static void rpcap_msg_err(SOCKET sockctrl, uint32 plen, char *remote_errbuf)
+static void rpcap_msg_err(SOCKET sockctrl, SSL *ssl, uint32 plen, char *remote_errbuf)
 {
        char errbuf[PCAP_ERRBUF_SIZE];
 
@@ -3216,7 +3330,7 @@ static void rpcap_msg_err(SOCKET sockctrl, uint32 plen, char *remote_errbuf)
                 * Message is too long; just read as much of it as we
                 * can into the buffer provided, and discard the rest.
                 */
-               if (sock_recv(sockctrl, remote_errbuf, PCAP_ERRBUF_SIZE - 1,
+               if (sock_recv(sockctrl, ssl, remote_errbuf, PCAP_ERRBUF_SIZE - 1,
                    SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf,
                    PCAP_ERRBUF_SIZE) == -1)
                {
@@ -3233,7 +3347,7 @@ static void rpcap_msg_err(SOCKET sockctrl, uint32 plen, char *remote_errbuf)
                /*
                 * Throw away the rest.
                 */
-               (void)rpcap_discard(sockctrl, plen - (PCAP_ERRBUF_SIZE - 1), remote_errbuf);
+               (void)rpcap_discard(sockctrl, ssl, plen - (PCAP_ERRBUF_SIZE - 1), remote_errbuf);
        }
        else if (plen == 0)
        {
@@ -3242,7 +3356,7 @@ static void rpcap_msg_err(SOCKET sockctrl, uint32 plen, char *remote_errbuf)
        }
        else
        {
-               if (sock_recv(sockctrl, remote_errbuf, plen,
+               if (sock_recv(sockctrl, ssl, remote_errbuf, plen,
                    SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf,
                    PCAP_ERRBUF_SIZE) == -1)
                {
@@ -3264,11 +3378,11 @@ static void rpcap_msg_err(SOCKET sockctrl, uint32 plen, char *remote_errbuf)
  * Returns 0 on success, logs a message and returns -1 on a network
  * error.
  */
-static int rpcap_discard(SOCKET sock, uint32 len, char *errbuf)
+static int rpcap_discard(SOCKET sock, SSL *ssl, uint32 len, char *errbuf)
 {
        if (len != 0)
        {
-               if (sock_discard(sock, len, errbuf, PCAP_ERRBUF_SIZE) == -1)
+               if (sock_discard(sock, ssl, len, errbuf, PCAP_ERRBUF_SIZE) == -1)
                {
                        // Network error.
                        return -1;
@@ -3300,18 +3414,9 @@ static int rpcap_read_packet_msg(struct pcap_rpcap const *rp, pcap_t *p, size_t
                 * We haven't read all of the packet header yet.
                 * Read what remains, which could be all of it.
                 */
-#ifdef HAVE_OPENSSL
-               if (rp->ssl)
-               {
-                       bytes_read = ssl_recv(rp->ssl, bp, size - cc, p->errbuf, PCAP_ERRBUF_SIZE);
-               }
-               else
-#endif
-               {
-                       bytes_read = sock_recv(rp->rmt_sockdata, bp, size - cc,
-                                       SOCK_RECEIVEALL_NO|SOCK_EOF_IS_ERROR, p->errbuf,
-                                       PCAP_ERRBUF_SIZE);
-               }
+               bytes_read = sock_recv(rp->rmt_sockdata, rp->data_ssl, bp, size - cc,
+                   SOCK_RECEIVEALL_NO|SOCK_EOF_IS_ERROR, p->errbuf,
+                   PCAP_ERRBUF_SIZE);
 
                if (bytes_read == -1)
                {
diff --git a/pcap.c b/pcap.c
index 0bc1b1ea09dccaf9ef340b162482870bfe1392a3..c4aba74bb3928e325d72c83f53f605b229bdd79b 100644 (file)
--- a/pcap.c
+++ b/pcap.c
@@ -1589,7 +1589,8 @@ pcap_parse_source(const char *source, char **schemep, char **userinfop,
         *
         * XXX - %-escaping?
         */
-       if (pcap_strcasecmp(scheme, "rpcap") == 0 &&
+       if ((pcap_strcasecmp(scheme, "rpcap") == 0 ||
+           pcap_strcasecmp(scheme, "rpcaps") == 0) &&
            strchr(colonp + 3, '/') == NULL) {
                /*
                 * Local device.
@@ -1859,8 +1860,8 @@ pcap_createsrcstr(char *source, int type, const char *host, const char *port,
 }
 
 int
-pcap_parsesrcstr(const char *source, int *type, char *host, char *port,
-    char *name, char *errbuf)
+pcap_parsesrcstr_ex(const char *source, int *type, char *host, char *port,
+    char *name, unsigned char *uses_ssl, char *errbuf)
 {
        char *scheme, *tmpuserinfo, *tmphost, *tmpport, *tmppath;
 
@@ -1871,6 +1872,8 @@ pcap_parsesrcstr(const char *source, int *type, char *host, char *port,
                *port = '\0';
        if (name)
                *name = '\0';
+       if (uses_ssl)
+               *uses_ssl = 0;
 
        /* Parse the source string */
        if (pcap_parse_source(source, &scheme, &tmpuserinfo, &tmphost,
@@ -1896,12 +1899,20 @@ pcap_parsesrcstr(const char *source, int *type, char *host, char *port,
                return (0);
        }
 
-       if (strcmp(scheme, "rpcap") == 0) {
+       int is_rpcap = 0;
+       if (strcmp(scheme, "rpcaps") == 0) {
+               is_rpcap = 1;
+               if (uses_ssl) *uses_ssl = 1;
+       } else if (strcmp(scheme, "rpcap") == 0) {
+               is_rpcap = 1;
+       }
+
+       if (is_rpcap) {
                /*
-                * rpcap://
+                * rpcap[s]://
                 *
                 * pcap_parse_source() has already handled the case of
-                * rpcap://device
+                * rpcap[s]://device
                 */
                if (host && tmphost) {
                        if (tmpuserinfo)
@@ -1955,6 +1966,13 @@ pcap_parsesrcstr(const char *source, int *type, char *host, char *port,
        free(scheme);
        return (0);
 }
+
+int
+pcap_parsesrcstr(const char *source, int *type, char *host, char *port,
+    char *name, char *errbuf)
+{
+  return pcap_parsesrcstr_ex(source, type, host, port, name, NULL, errbuf);
+}
 #endif
 
 pcap_t *
index e13e7ee2f7996a2d2adb36de4405676ced41b7e8..8ad79b61ea2181fd61ef01795d73ae7a00116941 100644 (file)
@@ -631,6 +631,9 @@ PCAP_API const char *pcap_lib_version(void);
  * - rpcap:// [lists all local adapters]
  * - rpcap://host:port/ [lists the devices available on a remote host]
  *
+ * In all the above, "rpcaps://" can be substituted for "rpcap://" to enable
+ * SSL (if it has been compiled in).
+ *
  * Referring to the 'host' and 'port' parameters, they can be either numeric or literal. Since
  * IPv6 is fully supported, these are the allowed formats:
  *
index 692f7c5c0d6bc6d9facf15ab1c62df525174f945..0cdc0ba323b7f0c2011a8257c0be593ae214fceb 100644 (file)
@@ -61,6 +61,8 @@
  *
  * \param sock: the socket we are currently using.
  *
+ * \param ssl: if compiled with openssl, the optional ssl handler to use with the above socket.
+ *
  * \param ver: the protocol version we want to put in the reply.
  *
  * \param errcode: a integer which tells the other party the type of error
@@ -78,7 +80,7 @@
  * error message is returned in the 'errbuf' variable.
  */
 int
-rpcap_senderror(SOCKET sock, uint8 ver, unsigned short errcode, const char *error, char *errbuf)
+rpcap_senderror(SOCKET sock, SSL *ssl, uint8 ver, unsigned short errcode, const char *error, char *errbuf)
 {
        char sendbuf[RPCAP_NETBUF_SIZE];        /* temporary buffer in which data to be sent is buffered */
        int sendbufidx = 0;                     /* index which keeps the number of bytes currently buffered */
@@ -99,7 +101,7 @@ rpcap_senderror(SOCKET sock, uint8 ver, unsigned short errcode, const char *erro
                RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE))
                return -1;
 
-       if (sock_send(sock, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) < 0)
+       if (sock_send(sock, ssl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) < 0)
                return -1;
 
        return 0;
index 30c8a218ceba5e6af7322eb7754cac6df7abafbb..ad66b755c5193d24396959f1d87547672fd2004f 100644 (file)
@@ -316,7 +316,6 @@ struct rpcap_startcapreply
        int32 bufsize;          /* Size of the user buffer allocated by WinPcap; it can be different from the one we chose */
        uint16 portdata;        /* Network port on which the server is waiting at (passive mode only) */
        uint16 dummy;           /* Must be zero */
-       uint8 ssl:1;    /* Only known flag so far: client must connect with TLS */
 };
 
 /*
@@ -446,9 +445,10 @@ struct rpcap_sampling
  *********************************************************/
 
 #include "sockutils.h"
+#include "sslutils.h"
 
 extern void rpcap_createhdr(struct rpcap_header *header, uint8 ver, uint8 type, uint16 value, uint32 length);
 extern const char *rpcap_msg_type_string(uint8 type);
-extern int rpcap_senderror(SOCKET sock, uint8 ver, uint16 errcode, const char *error, char *errbuf);
+extern int rpcap_senderror(SOCKET sock, SSL *ssl, uint8 ver, uint16 errcode, const char *error, char *errbuf);
 
 #endif
index b4ce20b3cd7b1c7b59b53fd3c8294cd03f13ba3d..3cf829267d45d665329b3e9981a24b29a8177663 100644 (file)
@@ -78,6 +78,7 @@ struct daemon_slpars
 {
        SOCKET sockctrl_in;     //!< SOCKET ID of the input side of the control connection
        SOCKET sockctrl_out;    //!< SOCKET ID of the output side of the control connection
+       SSL *ssl;               //!< Optional SSL handler for the controlling sockets
        uint8 protocol_version; //!< negotiated protocol version
        int isactive;           //!< Not null if the daemon has to run in active mode
        int nullAuthAllowed;    //!< '1' if we permit NULL authentication, '0' otherwise
@@ -89,9 +90,7 @@ struct daemon_slpars
 struct session {
        SOCKET sockctrl_out;
        SOCKET sockdata;
-#ifdef HAVE_OPENSSL
-       SSL *ssl;               // optional SSL handler for the data transported in sockdata
-#endif
+       SSL *ctrl_ssl, *data_ssl; // optional SSL handlers for sockctrl_out and sockdata.
        uint8 protocol_version;
        pcap_t *fp;
        unsigned int TotCapt;
@@ -115,18 +114,18 @@ struct thread_handle {
 };
 
 // Locally defined functions
-static int daemon_msg_err(SOCKET sockctrl_in, uint32 plen);
+static int daemon_msg_err(SOCKET sockctrl_in, SSL *, uint32 plen);
 static int daemon_msg_auth_req(struct daemon_slpars *pars, uint32 plen);
 static int daemon_AuthUserPwd(char *username, char *password, char *errbuf);
 
 static int daemon_msg_findallif_req(struct daemon_slpars *pars, uint32 plen);
 
 static int daemon_msg_open_req(struct daemon_slpars *pars, uint32 plen, char *source, size_t sourcelen);
-static int daemon_msg_startcap_req(struct daemon_slpars *pars, uint32 plen, struct thread_handle *threaddata, char *source, struct session **sessionp, struct rpcap_sampling *samp_param);
+static int daemon_msg_startcap_req(struct daemon_slpars *pars, uint32 plen, struct thread_handle *threaddata, char *source, struct session **sessionp, struct rpcap_sampling *samp_param, int uses_ssl);
 static int daemon_msg_endcap_req(struct daemon_slpars *pars, struct session *session, struct thread_handle *threaddata);
 
 static int daemon_msg_updatefilter_req(struct daemon_slpars *pars, struct session *session, uint32 plen);
-static int daemon_unpackapplyfilter(SOCKET sockctrl_in, struct session *session, uint32 *plenp, char *errbuf);
+static int daemon_unpackapplyfilter(SOCKET sockctrl_in, SSL *, struct session *session, uint32 *plenp, char *errbuf);
 
 static int daemon_msg_stats_req(struct daemon_slpars *pars, struct session *session, uint32 plen, struct pcap_stat *stats, unsigned int svrcapt);
 
@@ -139,14 +138,13 @@ static unsigned __stdcall daemon_thrdatamain(void *ptr);
 static void *daemon_thrdatamain(void *ptr);
 #endif
 
-static int rpcapd_recv_msg_header(SOCKET sock, struct rpcap_header *headerp);
-static int rpcapd_recv(SOCKET sock, char *buffer, size_t toread, uint32 *plen, char *errmsgbuf);
-static int rpcapd_discard(SOCKET sock, uint32 len);
+static int rpcapd_recv_msg_header(SOCKET sock, SSL *, struct rpcap_header *headerp);
+static int rpcapd_recv(SOCKET sock, SSL *, char *buffer, size_t toread, uint32 *plen, char *errmsgbuf);
+static int rpcapd_discard(SOCKET sock, SSL *, uint32 len);
 static void session_close(struct session *);
-static int session_send_data(struct session const *, const char *, size_t, char *, size_t);
 
 int
-daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, int nullAuthAllowed)
+daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, SSL *ssl, int isactive, int nullAuthAllowed, int uses_ssl)
 {
        struct daemon_slpars pars;              // service loop parameters
        char errbuf[PCAP_ERRBUF_SIZE + 1];      // keeps the error string, prior to be printed
@@ -177,6 +175,7 @@ daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, int nu
        // Set parameters structure
        pars.sockctrl_in = sockctrl_in;
        pars.sockctrl_out = sockctrl_out;
+       pars.ssl = ssl;
        pars.protocol_version = 0;              // not yet known
        pars.isactive = isactive;               // active mode
        pars.nullAuthAllowed = nullAuthAllowed;
@@ -227,7 +226,7 @@ daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, int nu
                        if (retval == -1)
                        {
                                sock_geterror("select failed: ", errmsgbuf, PCAP_ERRBUF_SIZE);
-                               if (rpcap_senderror(pars.sockctrl_out, 0, PCAP_ERR_NETW, errmsgbuf, errbuf) == -1)
+                               if (rpcap_senderror(pars.sockctrl_out, pars.ssl, 0, PCAP_ERR_NETW, errmsgbuf, errbuf) == -1)
                                        rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
                                goto end;
                        }
@@ -236,7 +235,7 @@ daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, int nu
                        // So, this was a fake connection. Drop it down
                        if (retval == 0)
                        {
-                               if (rpcap_senderror(pars.sockctrl_out, 0, PCAP_ERR_INITTIMEOUT, "The RPCAP initial timeout has expired", errbuf) == -1)
+                               if (rpcap_senderror(pars.sockctrl_out, pars.ssl, 0, PCAP_ERR_INITTIMEOUT, "The RPCAP initial timeout has expired", errbuf) == -1)
                                        rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
                                goto end;
                        }
@@ -245,7 +244,7 @@ daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, int nu
                //
                // Read the message header from the client.
                //
-               nrecv = rpcapd_recv_msg_header(pars.sockctrl_in, &header);
+               nrecv = rpcapd_recv_msg_header(pars.sockctrl_in, pars.ssl, &header);
                if (nrecv == -1)
                {
                        // Fatal error.
@@ -301,7 +300,7 @@ daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, int nu
                                //
                                reply_version = RPCAP_MAX_VERSION;
                        }
-                       if (rpcap_senderror(pars.sockctrl_out, reply_version,
+                       if (rpcap_senderror(pars.sockctrl_out, pars.ssl, reply_version,
                            PCAP_ERR_WRONGVER, "RPCAP version number mismatch",
                            errbuf) == -1)
                        {
@@ -311,7 +310,7 @@ daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, int nu
                        }
 
                        // Discard the rest of the message.
-                       if (rpcapd_discard(pars.sockctrl_in, plen) == -1)
+                       if (rpcapd_discard(pars.sockctrl_in, pars.ssl, plen) == -1)
                        {
                                // Network error.
                                goto end;
@@ -355,7 +354,7 @@ daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, int nu
                                // Discard the rest of the message, if
                                // there is anything more.
                                //
-                               (void)rpcapd_discard(pars.sockctrl_in, plen);
+                               (void)rpcapd_discard(pars.sockctrl_in, pars.ssl, plen);
                                // We're done with this client.
                                goto end;
 
@@ -367,7 +366,7 @@ daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, int nu
                                // an error message rather than a "let
                                // me log in" message, indicating that
                                // we're not allowed to connect to them?
-                               (void)daemon_msg_err(pars.sockctrl_in, plen);
+                               (void)daemon_msg_err(pars.sockctrl_in, pars.ssl, plen);
                                goto end;
 
                        case RPCAP_MSG_FINDALLIF_REQ:
@@ -390,7 +389,7 @@ daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, int nu
                                {
                                        pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Message of type %u sent before authentication was completed", header.type);
                                }
-                               if (rpcap_senderror(pars.sockctrl_out,
+                               if (rpcap_senderror(pars.sockctrl_out, pars.ssl,
                                    pars.protocol_version, PCAP_ERR_WRONGMSG,
                                    errmsgbuf, errbuf) == -1)
                                {
@@ -398,7 +397,7 @@ daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, int nu
                                        goto end;
                                }
                                // Discard the rest of the message.
-                               if (rpcapd_discard(pars.sockctrl_in, plen) == -1)
+                               if (rpcapd_discard(pars.sockctrl_in, pars.ssl, plen) == -1)
                                {
                                        // Network error.
                                        goto end;
@@ -426,7 +425,7 @@ daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, int nu
                                {
                                        pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Server-to-client message of type %u received from client", header.type);
                                }
-                               if (rpcap_senderror(pars.sockctrl_out,
+                               if (rpcap_senderror(pars.sockctrl_out, pars.ssl,
                                    pars.protocol_version, PCAP_ERR_WRONGMSG,
                                    errmsgbuf, errbuf) == -1)
                                {
@@ -434,7 +433,7 @@ daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, int nu
                                        goto end;
                                }
                                // Discard the rest of the message.
-                               if (rpcapd_discard(pars.sockctrl_in, plen) == -1)
+                               if (rpcapd_discard(pars.sockctrl_in, pars.ssl, plen) == -1)
                                {
                                        // Fatal error.
                                        goto end;
@@ -446,7 +445,7 @@ daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, int nu
                                // Unknown message type.
                                //
                                pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Unknown message type %u", header.type);
-                               if (rpcap_senderror(pars.sockctrl_out,
+                               if (rpcap_senderror(pars.sockctrl_out, pars.ssl,
                                    pars.protocol_version, PCAP_ERR_WRONGMSG,
                                    errmsgbuf, errbuf) == -1)
                                {
@@ -454,7 +453,7 @@ daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, int nu
                                        goto end;
                                }
                                // Discard the rest of the message.
-                               if (rpcapd_discard(pars.sockctrl_in, plen) == -1)
+                               if (rpcapd_discard(pars.sockctrl_in, pars.ssl, plen) == -1)
                                {
                                        // Fatal error.
                                        goto end;
@@ -506,7 +505,7 @@ daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, int nu
                        if (retval == -1)
                        {
                                sock_geterror("select failed: ", errmsgbuf, PCAP_ERRBUF_SIZE);
-                               if (rpcap_senderror(pars.sockctrl_out,
+                               if (rpcap_senderror(pars.sockctrl_out, pars.ssl,
                                    pars.protocol_version, PCAP_ERR_NETW,
                                    errmsgbuf, errbuf) == -1)
                                        rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
@@ -517,7 +516,7 @@ daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, int nu
                        // So, this was a fake connection. Drop it down
                        if (retval == 0)
                        {
-                               if (rpcap_senderror(pars.sockctrl_out,
+                               if (rpcap_senderror(pars.sockctrl_out, pars.ssl,
                                    pars.protocol_version,
                                    PCAP_ERR_INITTIMEOUT,
                                    "The RPCAP initial timeout has expired",
@@ -530,7 +529,7 @@ daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, int nu
                //
                // Read the message header from the client.
                //
-               nrecv = rpcapd_recv_msg_header(pars.sockctrl_in, &header);
+               nrecv = rpcapd_recv_msg_header(pars.sockctrl_in, pars.ssl, &header);
                if (nrecv == -1)
                {
                        // Fatal error.
@@ -557,7 +556,7 @@ daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, int nu
                        // so they don't reject it as having the wrong
                        // version.
                        //
-                       if (rpcap_senderror(pars.sockctrl_out,
+                       if (rpcap_senderror(pars.sockctrl_out, pars.ssl,
                            header.ver, PCAP_ERR_WRONGVER,
                            "RPCAP version in message isn't the negotiated version",
                            errbuf) == -1)
@@ -568,7 +567,7 @@ daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, int nu
                        }
 
                        // Discard the rest of the message.
-                       (void)rpcapd_discard(pars.sockctrl_in, plen);
+                       (void)rpcapd_discard(pars.sockctrl_in, pars.ssl, plen);
                        // Give up on them.
                        goto end;
                }
@@ -577,7 +576,7 @@ daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, int nu
                {
                        case RPCAP_MSG_ERROR:           // The other endpoint reported an error
                        {
-                               (void)daemon_msg_err(pars.sockctrl_in, plen);
+                               (void)daemon_msg_err(pars.sockctrl_in, pars.ssl, plen);
                                // Do nothing; just exit; the error code is already into the errbuf
                                // XXX - actually exit....
                                break;
@@ -622,7 +621,7 @@ daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, int nu
                                {
                                        // They never told us what device
                                        // to capture on!
-                                       if (rpcap_senderror(pars.sockctrl_out,
+                                       if (rpcap_senderror(pars.sockctrl_out, pars.ssl,
                                            pars.protocol_version,
                                            PCAP_ERR_STARTCAPTURE,
                                            "No capture device was specified",
@@ -633,14 +632,14 @@ daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, int nu
                                                rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
                                                goto end;
                                        }
-                                       if (rpcapd_discard(pars.sockctrl_in, plen) == -1)
+                                       if (rpcapd_discard(pars.sockctrl_in, pars.ssl, plen) == -1)
                                        {
                                                goto end;
                                        }
                                        break;
                                }
 
-                               if (daemon_msg_startcap_req(&pars, plen, &threaddata, source, &session, &samp_param) == -1)
+                               if (daemon_msg_startcap_req(&pars, plen, &threaddata, source, &session, &samp_param, uses_ssl) == -1)
                                {
                                        // Fatal error; a message has
                                        // been logged, so just give up.
@@ -662,7 +661,7 @@ daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, int nu
                                }
                                else
                                {
-                                       if (rpcap_senderror(pars.sockctrl_out,
+                                       if (rpcap_senderror(pars.sockctrl_out, pars.ssl,
                                            pars.protocol_version,
                                            PCAP_ERR_UPDATEFILTER,
                                            "Device not opened. Cannot update filter",
@@ -729,7 +728,7 @@ daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, int nu
                                }
                                else
                                {
-                                       rpcap_senderror(pars.sockctrl_out,
+                                       rpcap_senderror(pars.sockctrl_out, pars.ssl,
                                            pars.protocol_version,
                                            PCAP_ERR_ENDCAPTURE,
                                            "Device not opened. Cannot close the capture",
@@ -756,7 +755,7 @@ daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, int nu
                                // get to reauthenticate.
                                //
                                rpcapd_log(LOGPRIO_INFO, "The client sent an RPCAP_MSG_AUTH_REQ message after authentication was completed");
-                               if (rpcap_senderror(pars.sockctrl_out,
+                               if (rpcap_senderror(pars.sockctrl_out, pars.ssl,
                                    pars.protocol_version,
                                    PCAP_ERR_WRONGMSG,
                                    "RPCAP_MSG_AUTH_REQ request sent after authentication was completed",
@@ -766,7 +765,7 @@ daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, int nu
                                        goto end;
                                }
                                // Discard the rest of the message.
-                               if (rpcapd_discard(pars.sockctrl_in, plen) == -1)
+                               if (rpcapd_discard(pars.sockctrl_in, pars.ssl, plen) == -1)
                                {
                                        // Fatal error.
                                        goto end;
@@ -796,7 +795,7 @@ daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, int nu
                                        rpcapd_log(LOGPRIO_INFO, "The client sent a server-to-client message of type %u", header.type);
                                        pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Server-to-client message of type %u received from client", header.type);
                                }
-                               if (rpcap_senderror(pars.sockctrl_out,
+                               if (rpcap_senderror(pars.sockctrl_out, pars.ssl,
                                    pars.protocol_version, PCAP_ERR_WRONGMSG,
                                    errmsgbuf, errbuf) == -1)
                                {
@@ -804,7 +803,7 @@ daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, int nu
                                        goto end;
                                }
                                // Discard the rest of the message.
-                               if (rpcapd_discard(pars.sockctrl_in, plen) == -1)
+                               if (rpcapd_discard(pars.sockctrl_in, pars.ssl, plen) == -1)
                                {
                                        // Fatal error.
                                        goto end;
@@ -817,7 +816,7 @@ daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, int nu
                                //
                                rpcapd_log(LOGPRIO_INFO, "The client sent a message of type %u", header.type);
                                pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Unknown message type %u", header.type);
-                               if (rpcap_senderror(pars.sockctrl_out,
+                               if (rpcap_senderror(pars.sockctrl_out, pars.ssl,
                                    pars.protocol_version, PCAP_ERR_WRONGMSG,
                                    errbuf, errmsgbuf) == -1)
                                {
@@ -825,7 +824,7 @@ daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive, int nu
                                        goto end;
                                }
                                // Discard the rest of the message.
-                               if (rpcapd_discard(pars.sockctrl_in, plen) == -1)
+                               if (rpcapd_discard(pars.sockctrl_in, pars.ssl, plen) == -1)
                                {
                                        // Fatal error.
                                        goto end;
@@ -892,7 +891,7 @@ end:
  * This handles the RPCAP_MSG_ERR message.
  */
 static int
-daemon_msg_err(SOCKET sockctrl_in, uint32 plen)
+daemon_msg_err(SOCKET sockctrl_in, SSL *ssl, uint32 plen)
 {
        char errbuf[PCAP_ERRBUF_SIZE];
        char remote_errbuf[PCAP_ERRBUF_SIZE];
@@ -903,7 +902,7 @@ daemon_msg_err(SOCKET sockctrl_in, uint32 plen)
                 * Message is too long; just read as much of it as we
                 * can into the buffer provided, and discard the rest.
                 */
-               if (sock_recv(sockctrl_in, remote_errbuf, PCAP_ERRBUF_SIZE - 1,
+               if (sock_recv(sockctrl_in, ssl, remote_errbuf, PCAP_ERRBUF_SIZE - 1,
                    SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf,
                    PCAP_ERRBUF_SIZE) == -1)
                {
@@ -911,7 +910,7 @@ daemon_msg_err(SOCKET sockctrl_in, uint32 plen)
                        rpcapd_log(LOGPRIO_ERROR, "Read from client failed: %s", errbuf);
                        return -1;
                }
-               if (rpcapd_discard(sockctrl_in, plen - (PCAP_ERRBUF_SIZE - 1)) == -1)
+               if (rpcapd_discard(sockctrl_in, ssl, plen - (PCAP_ERRBUF_SIZE - 1)) == -1)
                {
                        // Network error.
                        return -1;
@@ -929,7 +928,7 @@ daemon_msg_err(SOCKET sockctrl_in, uint32 plen)
        }
        else
        {
-               if (sock_recv(sockctrl_in, remote_errbuf, plen,
+               if (sock_recv(sockctrl_in, ssl, remote_errbuf, plen,
                    SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf,
                    PCAP_ERRBUF_SIZE) == -1)
                {
@@ -979,7 +978,7 @@ daemon_msg_auth_req(struct daemon_slpars *pars, uint32 plen)
        int status;
        struct rpcap_auth auth;                 // RPCAP authentication header
 
-       status = rpcapd_recv(pars->sockctrl_in, (char *) &auth, sizeof(struct rpcap_auth), &plen, errmsgbuf);
+       status = rpcapd_recv(pars->sockctrl_in, pars->ssl, (char *) &auth, sizeof(struct rpcap_auth), &plen, errmsgbuf);
        if (status == -1)
        {
                return -1;
@@ -1015,7 +1014,7 @@ daemon_msg_auth_req(struct daemon_slpars *pars, uint32 plen)
                                    PCAP_ERRBUF_SIZE, errno, "malloc() failed");
                                goto error;
                        }
-                       status = rpcapd_recv(pars->sockctrl_in, username, usernamelen, &plen, errmsgbuf);
+                       status = rpcapd_recv(pars->sockctrl_in, pars->ssl, username, usernamelen, &plen, errmsgbuf);
                        if (status == -1)
                        {
                                free(username);
@@ -1037,7 +1036,7 @@ daemon_msg_auth_req(struct daemon_slpars *pars, uint32 plen)
                                free(username);
                                goto error;
                        }
-                       status = rpcapd_recv(pars->sockctrl_in, passwd, passwdlen, &plen, errmsgbuf);
+                       status = rpcapd_recv(pars->sockctrl_in, pars->ssl, passwd, passwdlen, &plen, errmsgbuf);
                        if (status == -1)
                        {
                                free(username);
@@ -1060,7 +1059,7 @@ daemon_msg_auth_req(struct daemon_slpars *pars, uint32 plen)
                                //
                                free(username);
                                free(passwd);
-                               if (rpcap_senderror(pars->sockctrl_out,
+                               if (rpcap_senderror(pars->sockctrl_out, pars->ssl,
                                    pars->protocol_version,
                                    PCAP_ERR_AUTH, errmsgbuf, errbuf) == -1)
                                {
@@ -1097,7 +1096,7 @@ daemon_msg_auth_req(struct daemon_slpars *pars, uint32 plen)
        rpcap_createhdr(&header, pars->protocol_version, RPCAP_MSG_AUTH_REPLY, 0, 0);
 
        // Send the ok message back
-       if (sock_send(pars->sockctrl_out, (char *) &header, sizeof (struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1)
+       if (sock_send(pars->sockctrl_out, pars->ssl, (char *) &header, sizeof (struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1)
        {
                // That failed; log a messsage and give up.
                rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
@@ -1105,7 +1104,7 @@ daemon_msg_auth_req(struct daemon_slpars *pars, uint32 plen)
        }
 
        // Check if all the data has been read; if not, discard the data in excess
-       if (rpcapd_discard(pars->sockctrl_in, plen) == -1)
+       if (rpcapd_discard(pars->sockctrl_in, pars->ssl, plen) == -1)
        {
                return -1;
        }
@@ -1113,7 +1112,7 @@ daemon_msg_auth_req(struct daemon_slpars *pars, uint32 plen)
        return 0;
 
 error:
-       if (rpcap_senderror(pars->sockctrl_out, pars->protocol_version,
+       if (rpcap_senderror(pars->sockctrl_out, pars->ssl, pars->protocol_version,
            PCAP_ERR_AUTH, errmsgbuf, errbuf) == -1)
        {
                // That failed; log a message and give up.
@@ -1123,7 +1122,7 @@ error:
 
 error_noreply:
        // Check if all the data has been read; if not, discard the data in excess
-       if (rpcapd_discard(pars->sockctrl_in, plen) == -1)
+       if (rpcapd_discard(pars->sockctrl_in, pars->ssl, plen) == -1)
        {
                return -1;
        }
@@ -1268,7 +1267,7 @@ daemon_msg_findallif_req(struct daemon_slpars *pars, uint32 plen)
        uint16 nif = 0;                         // counts the number of interface listed
 
        // Discard the rest of the message; there shouldn't be any payload.
-       if (rpcapd_discard(pars->sockctrl_in, plen) == -1)
+       if (rpcapd_discard(pars->sockctrl_in, pars->ssl, plen) == -1)
        {
                // Network error.
                return -1;
@@ -1280,7 +1279,7 @@ daemon_msg_findallif_req(struct daemon_slpars *pars, uint32 plen)
 
        if (alldevs == NULL)
        {
-               if (rpcap_senderror(pars->sockctrl_out, pars->protocol_version,
+               if (rpcap_senderror(pars->sockctrl_out, pars->ssl, pars->protocol_version,
                        PCAP_ERR_NOREMOTEIF,
                        "No interfaces found! Make sure libpcap/WinPcap is properly installed"
                        " and you have the right to access to the remote device.",
@@ -1434,7 +1433,7 @@ daemon_msg_findallif_req(struct daemon_slpars *pars, uint32 plen)
        pcap_freealldevs(alldevs);
 
        // Send a final command that says "now send it!"
-       if (sock_send(pars->sockctrl_out, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
+       if (sock_send(pars->sockctrl_out, pars->ssl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
        {
                rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
                return -1;
@@ -1446,7 +1445,7 @@ error:
        if (alldevs)
                pcap_freealldevs(alldevs);
 
-       if (rpcap_senderror(pars->sockctrl_out, pars->protocol_version,
+       if (rpcap_senderror(pars->sockctrl_out, pars->ssl, pars->protocol_version,
            PCAP_ERR_FINDALLIF, errmsgbuf, errbuf) == -1)
        {
                rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
@@ -1476,7 +1475,7 @@ daemon_msg_open_req(struct daemon_slpars *pars, uint32 plen, char *source, size_
                goto error;
        }
 
-       nread = sock_recv(pars->sockctrl_in, source, plen,
+       nread = sock_recv(pars->sockctrl_in, pars->ssl, source, plen,
            SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf, PCAP_ERRBUF_SIZE);
        if (nread == -1)
        {
@@ -1519,7 +1518,7 @@ daemon_msg_open_req(struct daemon_slpars *pars, uint32 plen, char *source, size_
        pcap_close(fp);
 
        // Send the reply.
-       if (sock_send(pars->sockctrl_out, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
+       if (sock_send(pars->sockctrl_out, pars->ssl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
        {
                rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
                return -1;
@@ -1527,7 +1526,7 @@ daemon_msg_open_req(struct daemon_slpars *pars, uint32 plen, char *source, size_
        return 0;
 
 error:
-       if (rpcap_senderror(pars->sockctrl_out, pars->protocol_version,
+       if (rpcap_senderror(pars->sockctrl_out, pars->ssl, pars->protocol_version,
            PCAP_ERR_OPEN, errmsgbuf, errbuf) == -1)
        {
                // That failed; log a message and give up.
@@ -1536,7 +1535,7 @@ error:
        }
 
        // Check if all the data has been read; if not, discard the data in excess
-       if (rpcapd_discard(pars->sockctrl_in, plen) == -1)
+       if (rpcapd_discard(pars->sockctrl_in, pars->ssl, plen) == -1)
        {
                return -1;
        }
@@ -1548,7 +1547,7 @@ error:
        to discard excess data in the message, if present)
 */
 static int
-daemon_msg_startcap_req(struct daemon_slpars *pars, uint32 plen, struct thread_handle *threaddata, char *source, struct session **sessionp, struct rpcap_sampling *samp_param _U_)
+daemon_msg_startcap_req(struct daemon_slpars *pars, uint32 plen, struct thread_handle *threaddata, char *source, struct session **sessionp, struct rpcap_sampling *samp_param _U_, int uses_ssl)
 {
        char errbuf[PCAP_ERRBUF_SIZE];          // buffer for network errors
        char errmsgbuf[PCAP_ERRBUF_SIZE];       // buffer for errors to send to the client
@@ -1578,7 +1577,7 @@ daemon_msg_startcap_req(struct daemon_slpars *pars, uint32 plen, struct thread_h
 
        addrinfo = NULL;
 
-       status = rpcapd_recv(pars->sockctrl_in, (char *) &startcapreq,
+       status = rpcapd_recv(pars->sockctrl_in, pars->ssl, (char *) &startcapreq,
            sizeof(struct rpcap_startcapreq), &plen, errmsgbuf);
        if (status == -1)
        {
@@ -1599,9 +1598,7 @@ daemon_msg_startcap_req(struct daemon_slpars *pars, uint32 plen, struct thread_h
                goto error;
        }
 
-#ifdef HAVE_OPENSSL
-       session->ssl = NULL;
-#endif
+       session->ctrl_ssl = session->data_ssl = NULL;
 
        // Open the selected device
        if ((session->fp = pcap_open_live(source,
@@ -1697,10 +1694,11 @@ daemon_msg_startcap_req(struct daemon_slpars *pars, uint32 plen, struct thread_h
 
        // Needed to send an error on the ctrl connection
        session->sockctrl_out = pars->sockctrl_out;
+       session->ctrl_ssl = pars->ssl;
        session->protocol_version = pars->protocol_version;
 
        // Now I can set the filter
-       ret = daemon_unpackapplyfilter(pars->sockctrl_in, session, &plen, errmsgbuf);
+       ret = daemon_unpackapplyfilter(pars->sockctrl_in, pars->ssl, session, &plen, errmsgbuf);
        if (ret == -1)
        {
                // Fatal error.  A message has been logged; just give up.
@@ -1735,11 +1733,7 @@ daemon_msg_startcap_req(struct daemon_slpars *pars, uint32 plen, struct thread_h
                startcapreply->portdata = htons(port);
        }
 
-#ifdef HAVE_OPENSSL
-       startcapreply->ssl = !!uses_ssl;
-#endif
-
-       if (sock_send(pars->sockctrl_out, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
+       if (sock_send(pars->sockctrl_out, pars->ssl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
        {
                // That failed; log a message and give up.
                rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
@@ -1768,22 +1762,20 @@ daemon_msg_startcap_req(struct daemon_slpars *pars, uint32 plen, struct thread_h
                sockdata = socktemp;
        }
 
+       SSL *ssl = NULL;
+       if (uses_ssl) {
 #ifdef HAVE_OPENSSL
-       if (uses_ssl)
-       {
                /* In both active or passive cases, wait for the client to initiate the
                 * TLS handshake. Yes during that time the control socket will not be
                 * served, but the same was true from the above call to accept(). */
-               SSL *ssl = ssl_promotion(1, sockdata, errbuf, PCAP_ERRBUF_SIZE);
-               if (! ssl)
-               {
+               ssl = ssl_promotion(1, sockdata, errbuf, PCAP_ERRBUF_SIZE);
+               if (! ssl) {
                        rpcapd_log(LOGPRIO_ERROR, "TLS handshake failed: %s", errbuf);
                        goto error;
                }
-               session->ssl = ssl;
-       }
 #endif
-
+       }
+       session->data_ssl = ssl;
        session->sockdata = sockdata;
 
        // Now we have to create a new thread to receive packets
@@ -1814,7 +1806,7 @@ daemon_msg_startcap_req(struct daemon_slpars *pars, uint32 plen, struct thread_h
        threaddata->have_thread = 1;
 
        // Check if all the data has been read; if not, discard the data in excess
-       if (rpcapd_discard(pars->sockctrl_in, plen) == -1)
+       if (rpcapd_discard(pars->sockctrl_in, pars->ssl, plen) == -1)
                goto fatal_error;
 
        *sessionp = session;
@@ -1853,13 +1845,15 @@ error:
                if (session->fp)
                        pcap_close(session->fp);
 #ifdef HAVE_OPENSSL
-               if (session->ssl)
-                       SSL_free(session->ssl);
+               if (session->ctrl_ssl)
+                       SSL_free(session->ctrl_ssl);
+               if (session->data_ssl)
+                       SSL_free(session->data_ssl);
 #endif
                free(session);
        }
 
-       if (rpcap_senderror(pars->sockctrl_out, pars->protocol_version,
+       if (rpcap_senderror(pars->sockctrl_out, pars->ssl, pars->protocol_version,
            PCAP_ERR_STARTCAPTURE, errmsgbuf, errbuf) == -1)
        {
                // That failed; log a message and give up.
@@ -1868,7 +1862,7 @@ error:
        }
 
        // Check if all the data has been read; if not, discard the data in excess
-       if (rpcapd_discard(pars->sockctrl_in, plen) == -1)
+       if (rpcapd_discard(pars->sockctrl_in, pars->ssl, plen) == -1)
        {
                // Network error.
                return -1;
@@ -1929,8 +1923,10 @@ fatal_error:
                if (session->fp)
                        pcap_close(session->fp);
 #ifdef HAVE_OPENSSL
-               if (session->ssl)
-                       SSL_free(session->ssl);
+               if (session->ctrl_ssl)
+                       SSL_free(session->ctrl_ssl);
+               if (session->data_ssl)
+                       SSL_free(session->data_ssl);
 #endif
                free(session);
        }
@@ -1979,12 +1975,12 @@ daemon_msg_endcap_req(struct daemon_slpars *pars, struct session *session, struc
                threaddata->have_thread = 0;
        }
 
-  session_close(session);
+       session_close(session);
 
        rpcap_createhdr(&header, pars->protocol_version,
            RPCAP_MSG_ENDCAP_REPLY, 0, 0);
 
-       if (sock_send(pars->sockctrl_out, (char *) &header, sizeof(struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1)
+       if (sock_send(pars->sockctrl_out, pars->ssl, (char *) &header, sizeof(struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1)
        {
                // That failed; log a message and give up.
                rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
@@ -1995,7 +1991,7 @@ daemon_msg_endcap_req(struct daemon_slpars *pars, struct session *session, struc
 }
 
 static int
-daemon_unpackapplyfilter(SOCKET sockctrl_in, struct session *session, uint32 *plenp, char *errmsgbuf)
+daemon_unpackapplyfilter(SOCKET sockctrl_in, SSL *ctrl_ssl, struct session *session, uint32 *plenp, char *errmsgbuf)
 {
        int status;
        struct rpcap_filter filter;
@@ -2004,7 +2000,7 @@ daemon_unpackapplyfilter(SOCKET sockctrl_in, struct session *session, uint32 *pl
        struct bpf_program bf_prog;
        unsigned int i;
 
-       status = rpcapd_recv(sockctrl_in, (char *) &filter,
+       status = rpcapd_recv(sockctrl_in, ctrl_ssl, (char *) &filter,
            sizeof(struct rpcap_filter), plenp, errmsgbuf);
        if (status == -1)
        {
@@ -2035,7 +2031,7 @@ daemon_unpackapplyfilter(SOCKET sockctrl_in, struct session *session, uint32 *pl
 
        for (i = 0; i < bf_prog.bf_len; i++)
        {
-               status = rpcapd_recv(sockctrl_in, (char *) &insn,
+               status = rpcapd_recv(sockctrl_in, ctrl_ssl, (char *) &insn,
                    sizeof(struct rpcap_filterbpf_insn), plenp, errmsgbuf);
                if (status == -1)
                {
@@ -2080,7 +2076,7 @@ daemon_msg_updatefilter_req(struct daemon_slpars *pars, struct session *session,
        int ret;                                // status of daemon_unpackapplyfilter()
        struct rpcap_header header;             // keeps the answer to the updatefilter command
 
-       ret = daemon_unpackapplyfilter(pars->sockctrl_in, session, &plen, errmsgbuf);
+       ret = daemon_unpackapplyfilter(pars->sockctrl_in, pars->ssl, session, &plen, errmsgbuf);
        if (ret == -1)
        {
                // Fatal error.  A message has been logged; just give up.
@@ -2093,7 +2089,7 @@ daemon_msg_updatefilter_req(struct daemon_slpars *pars, struct session *session,
        }
 
        // Check if all the data has been read; if not, discard the data in excess
-       if (rpcapd_discard(pars->sockctrl_in, plen) == -1)
+       if (rpcapd_discard(pars->sockctrl_in, pars->ssl, plen) == -1)
        {
                // Network error.
                return -1;
@@ -2103,7 +2099,7 @@ daemon_msg_updatefilter_req(struct daemon_slpars *pars, struct session *session,
        rpcap_createhdr(&header, pars->protocol_version,
            RPCAP_MSG_UPDATEFILTER_REPLY, 0, 0);
 
-       if (sock_send(pars->sockctrl_out, (char *) &header, sizeof (struct rpcap_header), pcap_geterr(session->fp), PCAP_ERRBUF_SIZE))
+       if (sock_send(pars->sockctrl_out, pars->ssl, (char *) &header, sizeof (struct rpcap_header), pcap_geterr(session->fp), PCAP_ERRBUF_SIZE))
        {
                // That failed; log a messsage and give up.
                rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
@@ -2113,11 +2109,11 @@ daemon_msg_updatefilter_req(struct daemon_slpars *pars, struct session *session,
        return 0;
 
 error:
-       if (rpcapd_discard(pars->sockctrl_in, plen) == -1)
+       if (rpcapd_discard(pars->sockctrl_in, pars->ssl, plen) == -1)
        {
                return -1;
        }
-       rpcap_senderror(pars->sockctrl_out, pars->protocol_version,
+       rpcap_senderror(pars->sockctrl_out, pars->ssl, pars->protocol_version,
            PCAP_ERR_UPDATEFILTER, errmsgbuf, NULL);
 
        return 0;
@@ -2135,7 +2131,7 @@ daemon_msg_setsampling_req(struct daemon_slpars *pars, uint32 plen, struct rpcap
        struct rpcap_sampling rpcap_samp;
        int status;
 
-       status = rpcapd_recv(pars->sockctrl_in, (char *) &rpcap_samp, sizeof(struct rpcap_sampling), &plen, errmsgbuf);
+       status = rpcapd_recv(pars->sockctrl_in, pars->ssl, (char *) &rpcap_samp, sizeof(struct rpcap_sampling), &plen, errmsgbuf);
        if (status == -1)
        {
                return -1;
@@ -2153,14 +2149,14 @@ daemon_msg_setsampling_req(struct daemon_slpars *pars, uint32 plen, struct rpcap
        rpcap_createhdr(&header, pars->protocol_version,
            RPCAP_MSG_SETSAMPLING_REPLY, 0, 0);
 
-       if (sock_send(pars->sockctrl_out, (char *) &header, sizeof (struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1)
+       if (sock_send(pars->sockctrl_out, pars->ssl, (char *) &header, sizeof (struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1)
        {
                // That failed; log a messsage and give up.
                rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
                return -1;
        }
 
-       if (rpcapd_discard(pars->sockctrl_in, plen) == -1)
+       if (rpcapd_discard(pars->sockctrl_in, pars->ssl, plen) == -1)
        {
                return -1;
        }
@@ -2168,7 +2164,7 @@ daemon_msg_setsampling_req(struct daemon_slpars *pars, uint32 plen, struct rpcap
        return 0;
 
 error:
-       if (rpcap_senderror(pars->sockctrl_out, pars->protocol_version,
+       if (rpcap_senderror(pars->sockctrl_out, pars->ssl, pars->protocol_version,
            PCAP_ERR_AUTH, errmsgbuf, errbuf) == -1)
        {
                // That failed; log a message and give up.
@@ -2177,7 +2173,7 @@ error:
        }
 
        // Check if all the data has been read; if not, discard the data in excess
-       if (rpcapd_discard(pars->sockctrl_in, plen) == -1)
+       if (rpcapd_discard(pars->sockctrl_in, pars->ssl, plen) == -1)
        {
                return -1;
        }
@@ -2195,7 +2191,7 @@ daemon_msg_stats_req(struct daemon_slpars *pars, struct session *session, uint32
        struct rpcap_stats *netstats;           // statistics sent on the network
 
        // Checks that the header does not contain other data; if so, discard it
-       if (rpcapd_discard(pars->sockctrl_in, plen) == -1)
+       if (rpcapd_discard(pars->sockctrl_in, pars->ssl, plen) == -1)
        {
                // Network error.
                return -1;
@@ -2239,7 +2235,7 @@ daemon_msg_stats_req(struct daemon_slpars *pars, struct session *session, uint32
        }
 
        // Send the packet
-       if (sock_send(pars->sockctrl_out, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
+       if (sock_send(pars->sockctrl_out, pars->ssl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
        {
                rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
                return -1;
@@ -2248,7 +2244,7 @@ daemon_msg_stats_req(struct daemon_slpars *pars, struct session *session, uint32
        return 0;
 
 error:
-       rpcap_senderror(pars->sockctrl_out, pars->protocol_version,
+       rpcap_senderror(pars->sockctrl_out, pars->ssl, pars->protocol_version,
            PCAP_ERR_GETSTATS, errmsgbuf, NULL);
        return 0;
 }
@@ -2409,7 +2405,7 @@ daemon_thrdatamain(void *ptr)
                // Send the packet
                // If the client dropped the connection, don't report an
                // error, just quit.
-               status = session_send_data(session, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE);
+               status = sock_send(session->sockdata, session->data_ssl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE);
                if (status < 0)
                {
                        if (status == -1)
@@ -2434,13 +2430,13 @@ daemon_thrdatamain(void *ptr)
        if (retval == -1)
        {
                pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error reading the packets: %s", pcap_geterr(session->fp));
-               rpcap_senderror(session->sockctrl_out, session->protocol_version,
+               rpcap_senderror(session->sockctrl_out, session->ctrl_ssl, session->protocol_version,
                    PCAP_ERR_READEX, errbuf, NULL);
                goto error;
        }
 
 error:
-  session_close(session);
+       session_close(session);
 
        free(sendbuf);
 
@@ -2529,12 +2525,12 @@ void sleep_secs(int secs)
  * Read the header of a message.
  */
 static int
-rpcapd_recv_msg_header(SOCKET sock, struct rpcap_header *headerp)
+rpcapd_recv_msg_header(SOCKET sock, SSL *ssl, struct rpcap_header *headerp)
 {
        int nread;
        char errbuf[PCAP_ERRBUF_SIZE];          // buffer for network errors
 
-       nread = sock_recv(sock, (char *) headerp, sizeof(struct rpcap_header),
+       nread = sock_recv(sock, ssl, (char *) headerp, sizeof(struct rpcap_header),
            SOCK_RECEIVEALL_YES|SOCK_EOF_ISNT_ERROR, errbuf, PCAP_ERRBUF_SIZE);
        if (nread == -1)
        {
@@ -2561,7 +2557,7 @@ rpcapd_recv_msg_header(SOCKET sock, struct rpcap_header *headerp)
  * error.
  */
 static int
-rpcapd_recv(SOCKET sock, char *buffer, size_t toread, uint32 *plen, char *errmsgbuf)
+rpcapd_recv(SOCKET sock, SSL *ssl, char *buffer, size_t toread, uint32 *plen, char *errmsgbuf)
 {
        int nread;
        char errbuf[PCAP_ERRBUF_SIZE];          // buffer for network errors
@@ -2572,7 +2568,7 @@ rpcapd_recv(SOCKET sock, char *buffer, size_t toread, uint32 *plen, char *errmsg
                pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Message payload is too short");
                return -2;
        }
-       nread = sock_recv(sock, buffer, toread,
+       nread = sock_recv(sock, ssl, buffer, toread,
            SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf, PCAP_ERRBUF_SIZE);
        if (nread == -1)
        {
@@ -2590,13 +2586,13 @@ rpcapd_recv(SOCKET sock, char *buffer, size_t toread, uint32 *plen, char *errmsg
  * error.
  */
 static int
-rpcapd_discard(SOCKET sock, uint32 len)
+rpcapd_discard(SOCKET sock, SSL *ssl, uint32 len)
 {
        char errbuf[PCAP_ERRBUF_SIZE + 1];      // keeps the error string, prior to be printed
 
        if (len != 0)
        {
-               if (sock_discard(sock, len, errbuf, PCAP_ERRBUF_SIZE) == -1)
+               if (sock_discard(sock, ssl, len, errbuf, PCAP_ERRBUF_SIZE) == -1)
                {
                        // Network error.
                        rpcapd_log(LOGPRIO_ERROR, "Read from client failed: %s", errbuf);
@@ -2608,15 +2604,16 @@ rpcapd_discard(SOCKET sock, uint32 len)
 
 /*
  * Close the socket associated with the session, the optional SSL handle,
- * and the underlying packet capture handle.
+ * and the underlying packet capture handle. We of course do not touch
+ * the controlling socket that's also copied into the session.
  */
 static void session_close(struct session *session)
 {
 #ifdef HAVE_OPENSSL
-       if (session->ssl)
+       if (session->data_ssl)
        {
-               SSL_free(session->ssl); // Must happen *before* the socket is closed
-               session->ssl = NULL;
+               SSL_free(session->data_ssl); // Must happen *before* the socket is closed
+               session->data_ssl = NULL;
        }
 #endif
 
@@ -2628,17 +2625,3 @@ static void session_close(struct session *session)
 
        pcap_close(session->fp);
 }
-
-static int session_send_data(struct session const *session, const char *buffer, size_t size, char *errbuf, size_t errbuflen)
-{
-#ifdef HAVE_OPENSSL
-       if (session->ssl)
-       {
-               return ssl_send(session->ssl, buffer, size, errbuf, errbuflen);
-       }
-       else
-#endif
-       {
-               return sock_send(session->sockdata, buffer, size, errbuf, errbuflen);
-       }
-}
index bd240b8055d1fa7a35b496957f8c93ba6eb6a7fd..83901e77737bdcdf3d6ac514074778d8176d8590 100644 (file)
 #ifndef __DAEMON_H__
 #define __DAEMON_H__
 
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "sslutils.h"
+
 //
 // Returns 1 if the client closed the control connection explicitly, 0
 // otherwise; used in active mode only.
 //
-int daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, int isactive,
-    int nullAuthAllowed);
+int daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, SSL *ssl,
+    int isactive, int nullAuthAllowed, int uses_ssl);
 
 void sleep_secs(int secs);
 
index 12a71ab4a7a8d2cc7b40643bf206ccbbf132447b..76e676c5afc74a6f43565c868303a15779a15bf1 100644 (file)
@@ -90,6 +90,7 @@ static HANDLE state_change_event;             //!< event to signal that a state change shou
 #endif
 static volatile sig_atomic_t shutdown_server;  //!< '1' if the server is to shut down
 static volatile sig_atomic_t reread_config;    //!< '1' if the server is to re-read its configuration
+static int uses_ssl; //!< '1' to use TLS over the data socket
 
 extern char *optarg;   // for getopt()
 
@@ -147,6 +148,11 @@ static void printusage(void)
        "                  the service is started from the control panel\n\n"
 #ifndef _WIN32
        "  -i              run in inetd mode (UNIX only)\n\n"
+#endif
+#ifdef HAVE_OPENSSL
+       "  -S              encrypt all communication with SSL (implements rpcaps://)\n"
+       "  -K <pem_file>   uses the SSL private key in this file (default: key.pem)\n"
+       "  -C <pem_file>   uses the certificate from this file (default: cert.pem)\n"
 #endif
        "  -s <config_file> save the current configuration to file\n\n"
        "  -f <config_file> load the current configuration from file; all switches\n"
@@ -354,10 +360,11 @@ int main(int argc, char *argv[])
        signal(SIGPIPE, SIG_IGN);
 #endif
 
-#ifndef _WIN32
 # ifdef HAVE_OPENSSL
        if (uses_ssl) init_ssl_or_die(1);
 # endif
+
+#ifndef _WIN32
        if (isrunbyinetd)
        {
                //
@@ -407,13 +414,26 @@ int main(int argc, char *argv[])
                        close(devnull_fd);
                }
 
+               SSL *ssl = NULL;
+#ifdef HAVE_OPENSSL
+               if (uses_ssl)
+               {
+                       ssl = ssl_promotion_rw(1, sockctrl_in, sockctrl_out, errbuf, PCAP_ERRBUF_SIZE);
+                       if (! ssl)
+                       {
+                               rpcapd_log(LOGPRIO_ERROR, "TLS handshake on control connection failed: %s",
+                                   errbuf);
+                               exit(2);
+                       }
+               }
+#endif
                //
                // Handle this client.
                // This is passive mode, so we don't care whether we were
                // told by the client to close.
                //
-               (void)daemon_serviceloop(sockctrl_in, sockctrl_out, 0,
-                   nullAuthAllowed);
+               (void)daemon_serviceloop(sockctrl_in, sockctrl_out, ssl, 0,
+                   nullAuthAllowed, uses_ssl);
 
                //
                // Nothing more to do.
@@ -1059,6 +1079,22 @@ accept_connections(void)
        sock_cleanup();
 }
 
+#ifdef _WIN32
+//
+// A structure to hold the parameter to the windows thread
+// (on unix there is no need for this explicit copy since the
+// fork "inherits" the parent stack)
+//
+struct sock_copy {
+       SOCKET sockctrl;
+#      ifdef HAVE_OPENSSL
+       SSL *ssl;
+#      else
+       void *ssl;
+#      endif
+};
+#endif
+
 //
 // Accept a connection and start a worker thread, on Windows, or a
 // worker process, on UN*X, to handle the connection.
@@ -1071,10 +1107,12 @@ accept_connection(SOCKET listen_sock)
        struct sockaddr_storage from;           // generic sockaddr_storage variable
        socklen_t fromlen;                      // keeps the length of the sockaddr_storage variable
 
+       SSL *ssl = NULL;
+
 #ifdef _WIN32
        HANDLE threadId;                        // handle for the subthread
        u_long off = 0;
-       SOCKET *sockctrl_temp;
+       struct sock_copy *sock_copy = NULL;
 #else
        pid_t pid;
 #endif
@@ -1113,15 +1151,29 @@ accept_connection(SOCKET listen_sock)
                return;
        }
 
+#ifdef HAVE_OPENSSL
+       /* We have to upgrade to TLS as soon as possible so that the whole protocol
+        * goes through the encrypted tunnel, including early error messages. */
+       if (uses_ssl)
+       {
+               ssl = ssl_promotion(1, sockctrl, errbuf, PCAP_ERRBUF_SIZE);
+               if (! ssl)
+               {
+                       rpcapd_log(LOGPRIO_ERROR, "TLS handshake on control connection failed: %s",
+                           errbuf);
+                       goto error;
+               }
+       }
+#endif
+
        //
        // We have a connection.
        // Check whether the connecting host is among the ones allowed.
        //
        if (sock_check_hostlist(hostlist, RPCAP_HOSTLIST_SEP, &from, errbuf, PCAP_ERRBUF_SIZE) < 0)
        {
-               rpcap_senderror(sockctrl, 0, PCAP_ERR_HOSTNOAUTH, errbuf, NULL);
-               sock_close(sockctrl, NULL, 0);
-               return;
+               rpcap_senderror(sockctrl, ssl, 0, PCAP_ERR_HOSTNOAUTH, errbuf, NULL);
+               goto error;
        }
 
 #ifdef _WIN32
@@ -1137,16 +1189,14 @@ accept_connection(SOCKET listen_sock)
        if (WSAEventSelect(sockctrl, NULL, 0) == SOCKET_ERROR)
        {
                sock_geterror("ioctlsocket(FIONBIO): ", errbuf, PCAP_ERRBUF_SIZE);
-               rpcap_senderror(sockctrl, 0, PCAP_ERR_HOSTNOAUTH, errbuf, NULL);
-               sock_close(sockctrl, NULL, 0);
-               return;
+               rpcap_senderror(sockctrl, ssl, 0, PCAP_ERR_HOSTNOAUTH, errbuf, NULL);
+               goto error;
        }
        if (ioctlsocket(sockctrl, FIONBIO, &off) == SOCKET_ERROR)
        {
                sock_geterror("ioctlsocket(FIONBIO): ", errbuf, PCAP_ERRBUF_SIZE);
-               rpcap_senderror(sockctrl, 0, PCAP_ERR_HOSTNOAUTH, errbuf, NULL);
-               sock_close(sockctrl, NULL, 0);
-               return;
+               rpcap_senderror(sockctrl, ssl, 0, PCAP_ERR_HOSTNOAUTH, errbuf, NULL);
+               goto error;
        }
 
        //
@@ -1156,26 +1206,24 @@ accept_connection(SOCKET listen_sock)
        // I guess we *could* just cast sockctrl to a void *, but that's
        // a bit ugly.
        //
-       sockctrl_temp = (SOCKET *)malloc(sizeof (SOCKET));
-       if (sockctrl_temp == NULL)
+       sock_copy = malloc(sizeof(*sock_copy));
+       if (sock_copy == NULL)
        {
                pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
                    errno, "malloc() failed");
-               rpcap_senderror(sockctrl, 0, PCAP_ERR_OPEN, errbuf, NULL);
-               sock_close(sockctrl, NULL, 0);
-               return;
+               rpcap_senderror(sockctrl, ssl, 0, PCAP_ERR_OPEN, errbuf, NULL);
+               goto error;
        }
-       *sockctrl_temp = sockctrl;
+       sock_copy->sockctrl = sockctrl;
+       sock_copy->ssl = NULL;
 
        threadId = (HANDLE)_beginthreadex(NULL, 0,
-           main_passive_serviceloop_thread, (void *) sockctrl_temp, 0, NULL);
+           main_passive_serviceloop_thread, (void *) sock_copy, 0, NULL);
        if (threadId == 0)
        {
                pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error creating the child thread");
-               rpcap_senderror(sockctrl, 0, PCAP_ERR_OPEN, errbuf, NULL);
-               sock_close(sockctrl, NULL, 0);
-               free(sockctrl_temp);
-               return;
+               rpcap_senderror(sockctrl, ssl, 0, PCAP_ERR_OPEN, errbuf, NULL);
+               goto error;
        }
        CloseHandle(threadId);
 #else
@@ -1183,9 +1231,8 @@ accept_connection(SOCKET listen_sock)
        if (pid == -1)
        {
                pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error creating the child process");
-               rpcap_senderror(sockctrl, 0, PCAP_ERR_OPEN, errbuf, NULL);
-               sock_close(sockctrl, NULL, 0);
-               return;
+               rpcap_senderror(sockctrl, ssl, 0, PCAP_ERR_OPEN, errbuf, NULL);
+               goto error;
        }
        if (pid == 0)
        {
@@ -1216,8 +1263,8 @@ accept_connection(SOCKET listen_sock)
                // This is passive mode, so we don't care whether we were
                // told by the client to close.
                //
-               (void)daemon_serviceloop(sockctrl, sockctrl, 0,
-                   nullAuthAllowed);
+               (void)daemon_serviceloop(sockctrl, sockctrl, ssl, 0,
+                   nullAuthAllowed, uses_ssl);
 
                close(sockctrl);
 
@@ -1226,8 +1273,25 @@ accept_connection(SOCKET listen_sock)
 
        // I am the parent
        // Close the socket for this session (must be open only in the child)
+#ifdef HAVE_OPENSSL
+       if (ssl)
+       {
+               SSL_free(ssl);
+               ssl = NULL;
+       }
+#endif
        closesocket(sockctrl);
 #endif
+  return;
+
+error:
+#ifdef _WIN32
+       if (sock_copy) free(sock_copy);
+#endif
+#ifdef HAVE_OPENSSL
+       if (ssl) SSL_free(ssl);  // Have to be done before closing soskctrl
+#endif
+       sock_close(sockctrl, NULL, 0);
 }
 
 /*!
@@ -1251,6 +1315,7 @@ main_active(void *ptr)
        struct addrinfo hints;                  // temporary struct to keep settings needed to open the new socket
        struct addrinfo *addrinfo;              // keeps the addrinfo chain; required to open a new socket
        struct active_pars *activepars;
+       SSL *ssl = NULL;
 
        activepars = (struct active_pars *) ptr;
 
@@ -1295,9 +1360,28 @@ main_active(void *ptr)
                        continue;
                }
 
-               activeclose = daemon_serviceloop(sockctrl, sockctrl, 1,
-                   nullAuthAllowed);
+#ifdef HAVE_OPENSSL
+               /* Even in active mode the other other end has to initiate the TLS handshake
+                * as we still are the server as far as TLS is concerned: */
+               if (uses_ssl)
+               {
+                       ssl = ssl_promotion(1, sockctrl, errbuf, PCAP_ERRBUF_SIZE);
+                       if (! ssl)
+                       {
+                               rpcapd_log(LOGPRIO_ERROR, "TLS handshake on control connection failed: %s",
+                                   errbuf);
+                               sock_close(sockctrl, NULL, 0);
+                               continue;
+                       }
+               }
+#endif
+
+               activeclose = daemon_serviceloop(sockctrl, sockctrl, ssl, 1,
+                   nullAuthAllowed, uses_ssl);
 
+#ifdef HAVE_OPENSSL
+               if (ssl) SSL_free(ssl);
+#endif
                sock_close(sockctrl, NULL, 0);
 
                // If the connection is closed by the user explicitely, don't try to connect to it again
@@ -1316,9 +1400,7 @@ main_active(void *ptr)
 //
 unsigned __stdcall main_passive_serviceloop_thread(void *ptr)
 {
-       SOCKET sockctrl;
-
-       sockctrl = *((SOCKET *)ptr);
+       struct sock_copy sock = *(struct sock_copy *)ptr;
        free(ptr);
 
        //
@@ -1326,9 +1408,10 @@ unsigned __stdcall main_passive_serviceloop_thread(void *ptr)
        // This is passive mode, so we don't care whether we were
        // told by the client to close.
        //
-       (void)daemon_serviceloop(sockctrl, sockctrl, 0, nullAuthAllowed);
+       (void)daemon_serviceloop(sock.sockctrl, sock.sockctrl, sock.ssl, 0,
+           nullAuthAllowed, uses_ssl);
 
-       sock_close(sockctrl, NULL, 0);
+       sock_close(sock.sockctrl, NULL, 0);
 
        return 0;
 }
index e01bd9679b40d5651129e56d28dd6cb5c1c0475f..8474552712c02b36e9b49c785cc2903e808ac6ed 100644 (file)
@@ -640,7 +640,7 @@ int sock_initaddress(const char *host, const char *port,
  * '-2' if we got one of those errors.
  * For errors, an error message is returned in the 'errbuf' variable.
  */
-int sock_send(SOCKET sock, const char *buffer, size_t size,
+int sock_send(SOCKET sock, SSL *ssl, const char *buffer, size_t size,
     char *errbuf, int errbuflen)
 {
        int remaining;
@@ -659,6 +659,12 @@ int sock_send(SOCKET sock, const char *buffer, size_t size,
        remaining = (int)size;
 
        do {
+#ifdef HAVE_OPENSSL
+               if (ssl) return ssl_send(ssl, buffer, remaining, errbuf, errbuflen);
+#else
+               (void)ssl;
+#endif
+
 #ifdef MSG_NOSIGNAL
                /*
                 * Send with MSG_NOSIGNAL, so that we don't get SIGPIPE
@@ -835,7 +841,7 @@ int sock_bufferize(const char *buffer, int size, char *tempbuf, int *offset, int
  * The error message is returned in the 'errbuf' variable.
  */
 
-int sock_recv(SOCKET sock, void *buffer, size_t size, int flags,
+int sock_recv(SOCKET sock, SSL *ssl, void *buffer, size_t size, int flags,
     char *errbuf, int errbuflen)
 {
        char *bufp = buffer;
@@ -866,6 +872,16 @@ int sock_recv(SOCKET sock, void *buffer, size_t size, int flags,
         * Win32.
         */
        for (;;) {
+#ifdef HAVE_OPENSSL
+               if (ssl)
+               {
+                       nread = ssl_recv(ssl, bufp, remaining, errbuf, errbuflen);
+                       if (nread == -2) return -1;
+               }
+               else
+#else
+               (void)ssl;
+#endif
                nread = recv(sock, bufp, remaining, 0);
 
                if (nread == -1)
@@ -924,7 +940,7 @@ int sock_recv(SOCKET sock, void *buffer, size_t size, int flags,
  *
  * Returns the size of the datagram on success or -1 on error.
  */
-int sock_recv_dgram(SOCKET sock, void *buffer, size_t size,
+int sock_recv_dgram(SOCKET sock, SSL *ssl, void *buffer, size_t size,
     char *errbuf, int errbuflen)
 {
        ssize_t nread;
@@ -949,6 +965,13 @@ int sock_recv_dgram(SOCKET sock, void *buffer, size_t size,
                return -1;
        }
 
+       // TODO: DTLS
+       if (ssl)
+       {
+               pcap_snprintf(errbuf, errbuflen, "DTLS not implemented yet");
+               return -1;
+       }
+
        /*
         * This should be a datagram socket, so we should get the
         * entire datagram in one recv() or recvmsg() call, and
@@ -1059,7 +1082,7 @@ int sock_recv_dgram(SOCKET sock, void *buffer, size_t size,
  * \return '0' if everything is fine, '-1' if some errors occurred.
  * The error message is returned in the 'errbuf' variable.
  */
-int sock_discard(SOCKET sock, int size, char *errbuf, int errbuflen)
+int sock_discard(SOCKET sock, SSL *ssl, int size, char *errbuf, int errbuflen)
 {
 #define TEMP_BUF_SIZE 32768
 
@@ -1075,7 +1098,7 @@ int sock_discard(SOCKET sock, int size, char *errbuf, int errbuflen)
         */
        while (size > TEMP_BUF_SIZE)
        {
-               if (sock_recv(sock, buffer, TEMP_BUF_SIZE, SOCK_RECEIVEALL_YES, errbuf, errbuflen) == -1)
+               if (sock_recv(sock, ssl, buffer, TEMP_BUF_SIZE, SOCK_RECEIVEALL_YES, errbuf, errbuflen) == -1)
                        return -1;
 
                size -= TEMP_BUF_SIZE;
@@ -1087,7 +1110,7 @@ int sock_discard(SOCKET sock, int size, char *errbuf, int errbuflen)
         */
        if (size)
        {
-               if (sock_recv(sock, buffer, size, SOCK_RECEIVEALL_YES, errbuf, errbuflen) == -1)
+               if (sock_recv(sock, ssl, buffer, size, SOCK_RECEIVEALL_YES, errbuf, errbuflen) == -1)
                        return -1;
        }
 
index d3299eaf22acddcee468ec525b4d74f438654db0..95bd8ddb30846d3df475cb03fc7761e241471fbb 100644 (file)
   #define closesocket(a) close(a)
 #endif
 
+#include "sslutils.h"  // for SSL type, whatever that turns out to be
+
 /*
  * MingW headers include this definition, but only for Windows XP and above.
  * MSDN states that this function is available for most versions on Windows.
@@ -206,17 +208,17 @@ void sock_geterror(const char *caller, char *errbuf, int errbufsize);
 int sock_initaddress(const char *address, const char *port,
     struct addrinfo *hints, struct addrinfo **addrinfo,
     char *errbuf, int errbuflen);
-int sock_recv(SOCKET sock, void *buffer, size_t size, int receiveall,
+int sock_recv(SOCKET sock, SSL *, void *buffer, size_t size, int receiveall,
     char *errbuf, int errbuflen);
-int sock_recv_dgram(SOCKET sock, void *buffer, size_t size,
+int sock_recv_dgram(SOCKET sock, SSL *, void *buffer, size_t size,
     char *errbuf, int errbuflen);
 SOCKET sock_open(struct addrinfo *addrinfo, int server, int nconn, char *errbuf, int errbuflen);
 int sock_close(SOCKET sock, char *errbuf, int errbuflen);
 
-int sock_send(SOCKET sock, const char *buffer, size_t size,
+int sock_send(SOCKET sock, SSL *, const char *buffer, size_t size,
     char *errbuf, int errbuflen);
 int sock_bufferize(const char *buffer, int size, char *tempbuf, int *offset, int totsize, int checkonly, char *errbuf, int errbuflen);
-int sock_discard(SOCKET sock, int size, char *errbuf, int errbuflen);
+int sock_discard(SOCKET sock, SSL *, int size, char *errbuf, int errbuflen);
 int    sock_check_hostlist(char *hostlist, const char *sep, struct sockaddr_storage *from, char *errbuf, int errbuflen);
 int sock_cmpaddr(struct sockaddr_storage *first, struct sockaddr_storage *second);
 
index 346466e2309482642e8bd03af2459318225d76e3..637940a1ba5dcaee73aa99bdd1449e81537733f5 100644 (file)
@@ -41,7 +41,6 @@
 #include "sslutils.h"
 #include "pcap/pcap.h"
 
-int uses_ssl; //!< '1' to use TLS over the data socket
 char ssl_keyfile[PATH_MAX]; //!< file containing the private key in PEM format
 char ssl_certfile[PATH_MAX];  //!< file containing the server's certificate in PEM format
 char ssl_rootfile[PATH_MAX];  //!< file containing the list of CAs trusted by the client
@@ -59,26 +58,40 @@ static int ssl_init_once(int is_server, char *errbuf, size_t errbuflen)
        SSL_load_error_strings();
        OpenSSL_add_ssl_algorithms();
 
+<<<<<<< HEAD
        SSL_METHOD const *meth = SSLv23_method();
        ctx = SSL_CTX_new(meth);
        if (! ctx)
        {
+=======
+       SSL_METHOD const *meth =
+               is_server ? SSLv23_server_method() : SSLv23_client_method();
+       ctx = SSL_CTX_new(meth);
+       if (! ctx) {
+>>>>>>> b5063379... TLS for rpcap: also encrypt the control socket
                pcap_snprintf(errbuf, errbuflen, "Cannot get a new SSL context: %s", ERR_error_string(ERR_get_error(), NULL));
                goto die;
        }
 
        SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
 
+<<<<<<< HEAD
        if (is_server)
        {
                char const *certfile = ssl_certfile[0] ? ssl_certfile : "cert.pem";
                if (1 != SSL_CTX_use_certificate_file(ctx, certfile, SSL_FILETYPE_PEM))
                {
+=======
+       if (is_server) {
+               char const *certfile = ssl_certfile[0] ? ssl_certfile : "cert.pem";
+               if (1 != SSL_CTX_use_certificate_file(ctx, certfile, SSL_FILETYPE_PEM)) {
+>>>>>>> b5063379... TLS for rpcap: also encrypt the control socket
                        pcap_snprintf(errbuf, errbuflen, "Cannot read certificate file %s: %s", certfile, ERR_error_string(ERR_get_error(), NULL));
                        goto die;
                }
 
                char const *keyfile = ssl_keyfile[0] ? ssl_keyfile : "key.pem";
+<<<<<<< HEAD
                if (1 != SSL_CTX_use_PrivateKey_file(ctx, keyfile, SSL_FILETYPE_PEM))
                {
                        pcap_snprintf(errbuf, errbuflen, "Cannot read private key file %s: %s", keyfile, ERR_error_string(ERR_get_error(), NULL));
@@ -97,19 +110,40 @@ static int ssl_init_once(int is_server, char *errbuf, size_t errbuflen)
                }
                else
                {
+=======
+               if (1 != SSL_CTX_use_PrivateKey_file(ctx, keyfile, SSL_FILETYPE_PEM)) {
+                       pcap_snprintf(errbuf, errbuflen, "Cannot read private key file %s: %s", keyfile, ERR_error_string(ERR_get_error(), NULL));
+                       goto die;
+               }
+       } else {
+               if (ssl_rootfile[0]) {
+                       if (! SSL_CTX_load_verify_locations(ctx, ssl_rootfile, 0)) {
+                               pcap_snprintf(errbuf, errbuflen, "Cannot read CA list from %s", ssl_rootfile);
+                               goto die;
+                       }
+               } else {
+>>>>>>> b5063379... TLS for rpcap: also encrypt the control socket
                        SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
                }
        }
 
 #if 0
+<<<<<<< HEAD
        if (! RAND_load_file(RANDOM, 1024*1024))
        {
+=======
+       if (! RAND_load_file(RANDOM, 1024*1024)) {
+>>>>>>> b5063379... TLS for rpcap: also encrypt the control socket
                pcap_snprintf(errbuf, errbuflen, "Cannot init random");
                goto die;
        }
 
+<<<<<<< HEAD
        if (is_server)
        {
+=======
+       if (is_server) {
+>>>>>>> b5063379... TLS for rpcap: also encrypt the control socket
                SSL_CTX_set_session_id_context(ctx, (void *)&s_server_session_id_context, sizeof(s_server_session_id_context));
        }
 #endif
@@ -125,36 +159,37 @@ void init_ssl_or_die(int is_server)
 {
        char errbuf[PCAP_ERRBUF_SIZE];
 
+<<<<<<< HEAD
        if (ssl_init_once(is_server, errbuf, sizeof errbuf) < 0)
        {
                fprintf(stderr, "%s\n", errbuf);
                exit(3);
        }
+=======
+       if (ssl_init_once(is_server, errbuf, sizeof errbuf) < 0) {
+               fprintf(stderr, "%s\n", errbuf);
+               exit(3);
+       }
 }
 
-SSL *ssl_promotion(int is_server, SOCKET s, char *errbuf, size_t errbuflen)
+SSL *ssl_promotion_rw(int is_server, SOCKET in, SOCKET out, char *errbuf, size_t errbuflen)
 {
-       if (ssl_init_once(is_server, errbuf, errbuflen) < 0)
-       {
+       if (ssl_init_once(is_server, errbuf, errbuflen) < 0) {
                return NULL;
        }
 
-       SSL *ssl = SSL_new(ctx);
-       SSL_set_fd(ssl, s);
+       SSL *ssl = SSL_new(ctx); // TODO: also a DTLS context
+       SSL_set_rfd(ssl, in);
+       SSL_set_wfd(ssl, out);
 
-       if (is_server)
-       {
-               if (SSL_accept(ssl) <= 0)
-               {
+       if (is_server) {
+               if (SSL_accept(ssl) <= 0) {
                        pcap_snprintf(errbuf, errbuflen, "SSL_accept(): %s",
                                        ERR_error_string(ERR_get_error(), NULL));
                        return NULL;
                }
-       }
-       else
-       {
-               if (SSL_connect(ssl) <= 0)
-               {
+       } else {
+               if (SSL_connect(ssl) <= 0) {
                        pcap_snprintf(errbuf, errbuflen, "SSL_connect(): %s",
                                        ERR_error_string(ERR_get_error(), NULL));
                        return NULL;
@@ -162,6 +197,12 @@ SSL *ssl_promotion(int is_server, SOCKET s, char *errbuf, size_t errbuflen)
        }
 
        return ssl;
+>>>>>>> b5063379... TLS for rpcap: also encrypt the control socket
+}
+
+SSL *ssl_promotion(int is_server, SOCKET s, char *errbuf, size_t errbuflen)
+{
+       return ssl_promotion_rw(is_server, s, s, errbuf, errbuflen);
 }
 
 // Same return value as sock_send:
@@ -193,9 +234,8 @@ int ssl_send(SSL *ssl, char const *buffer, size_t size, char *errbuf, size_t err
        }
 }
 
-// Same return status as sock_recv(SOCK_EOF_IS_ERROR):
-// -3 for EINTR, -1 on error and EOF, or number of bytes read
-int ssl_recv(SSL *ssl, unsigned char *buffer, size_t size, char *errbuf, size_t errbuflen)
+// Returns the number of bytes read, or -1 on syserror, or -2 on SSL error.
+int ssl_recv(SSL *ssl, char *buffer, size_t size, char *errbuf, size_t errbuflen)
 {
        int status = SSL_read(ssl, buffer, size);
        if (status <= 0)
@@ -203,26 +243,24 @@ int ssl_recv(SSL *ssl, unsigned char *buffer, size_t size, char *errbuf, size_t
                int ssl_err = SSL_get_error(ssl, status);
                if (ssl_err == SSL_ERROR_ZERO_RETURN)
                {
-                       pcap_snprintf(errbuf, errbuflen, "The other host terminated the connection.");
-                       return -1;
+                       return 0;
                }
                else if (ssl_err == SSL_ERROR_SYSCALL)
                {
-#ifndef _WIN32
-                       if (errno == EINTR)
-                       {
-                               return -3;
-                       }
-                       else
-                       {
-                               pcap_snprintf(errbuf, errbuflen, "SSL_read(): %s",
-                                   ERR_error_string(ERR_get_error(), NULL));
-                               return -1;
-                       }
-#endif
+                       return -1;
                }
+               else
+               {
+                       // Should not happen
+                       pcap_snprintf(errbuf, errbuflen, "SSL_read(): %s",
+                           ERR_error_string(ERR_get_error(), NULL));
+                       return -2;
+               }
+       }
+       else
+       {
+               return status;
        }
-       return status;
 }
 
 #endif // HAVE_OPENSSL
index b2ae319427e22f7d1a67240b51d3eb1b5c660b81..457c92140327fbd937c269dbf7bcc2ace5ed5a82 100644 (file)
 #define __SSLUTILS_H__
 
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #ifdef HAVE_OPENSSL
 #include <openssl/ssl.h>
 #include <openssl/err.h>
-#include "sockutils.h"
+#include "pcap/pcap.h"  // for SOCKET
 
 /*
  * Configuration parameters
  */
 
-extern int uses_ssl;
 extern char ssl_keyfile[PATH_MAX];
 extern char ssl_certfile[PATH_MAX];
 extern char ssl_rootfile[PATH_MAX];
@@ -57,8 +56,14 @@ extern char ssl_rootfile[PATH_MAX];
 
 void init_ssl_or_die(int is_server);
 SSL *ssl_promotion(int is_server, SOCKET s, char *errbuf, size_t errbuflen);
+SSL *ssl_promotion_rw(int is_server, SOCKET in, SOCKET out, char *errbuf, size_t errbuflen);
 int ssl_send(SSL *, char const *buffer, size_t size, char *errbuf, size_t errbuflen);
-int ssl_recv(SSL *, unsigned char *buffer, size_t size, char *errbuf, size_t errbuflen);
+int ssl_recv(SSL *, char *buffer, size_t size, char *errbuf, size_t errbuflen);
+
+#else   // HAVE_OPENSSL
+
+// This saves us from a lot of ifdefs:
+#define SSL void const
 
 #endif  // HAVE_OPENSSL