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
{
struct sockaddr_storage host;
SOCKET sockctrl;
+ SSL *ssl;
uint8 protocol_version;
struct activehosts *next;
};
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 */
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);
/****************************************************
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 */
#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)
{
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)
{
/*
* 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' */
* 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
* 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)
{
/*
* 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);
}
}
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)
{
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;
#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;
* 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;
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.
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;
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
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;
/*
* 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
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);
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;
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;
* \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;
* 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)
{
//
* 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)
{
//
* 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 */
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. */
*
* 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;
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;
* 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;
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 */
/* 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;
}
/*
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;
* 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;
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 */
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 */
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. */
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 */
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;
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;
}
/* Retrieve adapter name */
- if (rpcap_recv(sockctrl, tmpstring,
+ if (rpcap_recv(sockctrl, ssl, tmpstring,
findalldevs_if.namelen, &plen, errbuf) == -1)
goto error;
}
/* Retrieve adapter description */
- if (rpcap_recv(sockctrl, tmpstring,
+ if (rpcap_recv(sockctrl, ssl, tmpstring,
findalldevs_if.desclen, &plen, errbuf) == -1)
goto error;
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;
}
/* 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;
}
*
* 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();
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));
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;
}
/* 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;
}
/*
* 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;
}
{
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;
* 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)
* 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;
/*
* 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)
* 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?
/*
* 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;
/*
* 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;
* 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;
}
/*
* 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;
/*
/*
* 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;
/*
* 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);
}
* 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;
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)
{
/*
* 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];
* 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)
{
/*
* 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)
{
}
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)
{
* 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;
* 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)
{
*
* 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.
}
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;
*port = '\0';
if (name)
*name = '\0';
+ if (uses_ssl)
+ *uses_ssl = 0;
/* Parse the source string */
if (pcap_parse_source(source, &scheme, &tmpuserinfo, &tmphost,
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)
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 *
* - 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:
*
*
* \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
* 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 */
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;
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 */
};
/*
*********************************************************/
#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
{
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
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;
};
// 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);
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
// 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;
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;
}
// 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;
}
//
// 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.
//
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)
{
}
// 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;
// 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;
// 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:
{
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)
{
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;
{
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)
{
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;
// 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)
{
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;
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);
// 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",
//
// 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.
// 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)
}
// 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;
}
{
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;
{
// 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",
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.
}
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",
}
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",
// 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",
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;
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)
{
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;
//
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)
{
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;
* 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];
* 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)
{
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;
}
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)
{
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;
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);
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);
//
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)
{
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);
}
// 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;
}
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.
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;
}
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;
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.",
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;
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);
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)
{
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;
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.
}
// 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;
}
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
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)
{
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,
// 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.
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);
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
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;
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.
}
// 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;
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);
}
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);
}
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;
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)
{
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)
{
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.
}
// 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;
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);
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;
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;
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;
}
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.
}
// 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;
}
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;
}
// 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;
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;
}
// 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)
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);
* 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)
{
* 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
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)
{
* 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);
/*
* 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
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);
- }
-}
#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);
#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()
" 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"
signal(SIGPIPE, SIG_IGN);
#endif
-#ifndef _WIN32
# ifdef HAVE_OPENSSL
if (uses_ssl) init_ssl_or_die(1);
# endif
+
+#ifndef _WIN32
if (isrunbyinetd)
{
//
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.
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.
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
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
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;
}
//
// 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
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)
{
// 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);
// 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);
}
/*!
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;
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
//
unsigned __stdcall main_passive_serviceloop_thread(void *ptr)
{
- SOCKET sockctrl;
-
- sockctrl = *((SOCKET *)ptr);
+ struct sock_copy sock = *(struct sock_copy *)ptr;
free(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;
}
* '-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;
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
* 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;
* 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)
*
* 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;
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
* \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
*/
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;
*/
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;
}
#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.
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);
#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
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));
}
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
{
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;
}
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:
}
}
-// 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)
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
#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];
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