diff options
Diffstat (limited to 'pcap-rpcap.c')
-rw-r--r-- | pcap-rpcap.c | 131 |
1 files changed, 112 insertions, 19 deletions
diff --git a/pcap-rpcap.c b/pcap-rpcap.c index c85acc2c..f7d4e0cc 100644 --- a/pcap-rpcap.c +++ b/pcap-rpcap.c @@ -45,6 +45,7 @@ #include <limits.h> /* for INT_MAX */ #include "sockutils.h" #include "pcap-int.h" +#include "pcap-util.h" #include "rpcap-protocol.h" #include "pcap-rpcap.h" @@ -95,6 +96,7 @@ struct activehosts SOCKET sockctrl; SSL *ssl; uint8_t protocol_version; + int byte_swapped; struct activehosts *next; }; @@ -130,6 +132,7 @@ struct pcap_rpcap { uint8_t protocol_version; /* negotiated protocol version */ uint8_t uses_ssl; /* User asked for rpcaps scheme */ + int byte_swapped; /* Server byte order is swapped from ours */ unsigned int TotNetDrops; /* keeps the number of packets that have been dropped by the network */ @@ -684,9 +687,14 @@ static int pcap_read_rpcap(pcap_t *p, int cnt, pcap_handler callback, u_char *us if (ret == 1) { /* - * We got a packet. Hand it to the callback - * and count it so we can return the count. + * We got a packet. + * + * Do whatever post-processing is necessary, hand + * it to the callback, and count it so we can + * return the count. */ + pcap_post_process(p->linktype, pr->byte_swapped, + &pkt_header, pkt_data); (*callback)(user, &pkt_header, pkt_data); n++; } @@ -1945,6 +1953,10 @@ static int pcap_setsampling_remote(pcap_t *fp) * \param ver: pointer to variable to which to set the protocol version * number we selected. * + * \param byte_swapped: pointer to variable to which to set 1 if the + * byte order the server says it has is byte-swapped from ours, 0 + * otherwise (whether it's the same as ours or is unknown). + * * \param auth: authentication parameters that have to be sent. * * \param errbuf: a pointer to a user-allocated buffer (of size @@ -1955,7 +1967,8 @@ 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, SSL *ssl, uint8_t *ver, struct pcap_rmtauth *auth, char *errbuf) +static int rpcap_doauth(SOCKET sockctrl, SSL *ssl, uint8_t *ver, + int *byte_swapped, 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 */ @@ -1967,6 +1980,8 @@ static int rpcap_doauth(SOCKET sockctrl, SSL *ssl, uint8_t *ver, struct pcap_rmt uint32_t plen; struct rpcap_authreply authreply; /* authentication reply message */ uint8_t ourvers; + int has_byte_order; /* The server sent its version of the byte-order magic number */ + u_int their_byte_order_magic; /* Here's what it is */ if (auth) { @@ -2071,8 +2086,10 @@ static int rpcap_doauth(SOCKET sockctrl, SSL *ssl, uint8_t *ver, struct pcap_rmt plen = header.plen; if (plen != 0) { - /* Yes - is it big enough to be version information? */ - if (plen < sizeof(struct rpcap_authreply)) + size_t reply_len; + + /* Yes - is it big enough to include version information? */ + if (plen < sizeof(struct rpcap_authreply_old)) { /* No - discard it and fail. */ snprintf(errbuf, PCAP_ERRBUF_SIZE, @@ -2081,9 +2098,34 @@ static int rpcap_doauth(SOCKET sockctrl, SSL *ssl, uint8_t *ver, struct pcap_rmt return -1; } + /* Yes - does it include server byte order information? */ + if (plen == sizeof(struct rpcap_authreply_old)) + { + /* No - just read the version information */ + has_byte_order = 0; + reply_len = sizeof(struct rpcap_authreply_old); + } + else if (plen >= sizeof(struct rpcap_authreply_old)) + { + /* Yes - read it all. */ + has_byte_order = 1; + reply_len = sizeof(struct rpcap_authreply); + } + else + { + /* + * Too long for old reply, too short for new reply. + * Discard it and fail. + */ + snprintf(errbuf, PCAP_ERRBUF_SIZE, + "Authenticaton reply from server is too short"); + (void)rpcap_discard(sockctrl, ssl, plen, NULL); + return -1; + } + /* Read the reply body */ if (rpcap_recv(sockctrl, ssl, (char *)&authreply, - sizeof(struct rpcap_authreply), &plen, errbuf) == -1) + reply_len, &plen, errbuf) == -1) { (void)rpcap_discard(sockctrl, ssl, plen, NULL); return -1; @@ -2106,12 +2148,32 @@ static int rpcap_doauth(SOCKET sockctrl, SSL *ssl, uint8_t *ver, struct pcap_rmt "The server's minimum supported protocol version is greater than its maximum supported protocol version"); return -1; } + + if (has_byte_order) + { + their_byte_order_magic = authreply.byte_order_magic; + } + else + { + /* + * The server didn't tell us what its byte + * order is; assume it's ours. + */ + their_byte_order_magic = RPCAP_BYTE_ORDER_MAGIC;; + } } else { /* No - it supports only version 0. */ authreply.minvers = 0; authreply.maxvers = 0; + + /* + * And it didn't tell us what its byte order is; assume + * it's ours. + */ + has_byte_order = 0; + their_byte_order_magic = RPCAP_BYTE_ORDER_MAGIC; } /* @@ -2144,6 +2206,27 @@ static int rpcap_doauth(SOCKET sockctrl, SSL *ssl, uint8_t *ver, struct pcap_rmt goto novers; } + /* + * Is the server byte order the opposite of ours? + */ + if (their_byte_order_magic == RPCAP_BYTE_ORDER_MAGIC) + { + /* No, it's the same. */ + *byte_swapped = 0; + } + else if (their_byte_order_magic == RPCAP_BYTE_ORDER_MAGIC_SWAPPED) + { + /* Yes, it's the opposite of ours. */ + *byte_swapped = 1; + } + else + { + /* They sent us something bogus. */ + snprintf(errbuf, PCAP_ERRBUF_SIZE, + "The server did not send us a valid byte order value"); + return -1; + } + *ver = ourvers; return 0; @@ -2164,7 +2247,8 @@ static const char userinfo_allowed_symbols[] = "-._~!&'()*+,;="; * struct created from a username and password parsed out of the userinfo * portion of a URI. */ -static int rpcap_doauth_userinfo(SOCKET sockctrl, SSL *ssl, uint8_t *ver, const char *userinfo, char *errbuf) +static int rpcap_doauth_userinfo(SOCKET sockctrl, SSL *ssl, uint8_t *ver, + int *byte_swapped, const char *userinfo, char *errbuf) { struct pcap_rmtauth auth; const char *ptr; @@ -2222,10 +2306,11 @@ static int rpcap_doauth_userinfo(SOCKET sockctrl, SSL *ssl, uint8_t *ver, const } } - return rpcap_doauth(sockctrl, ssl, ver, &auth, errbuf); + return rpcap_doauth(sockctrl, ssl, ver, byte_swapped, &auth, + errbuf); } - return rpcap_doauth(sockctrl, ssl, ver, NULL, errbuf); + return rpcap_doauth(sockctrl, ssl, ver, byte_swapped, NULL, errbuf); } @@ -2249,8 +2334,8 @@ pcap_setnonblock_rpcap(pcap_t *p, int nonblock _U_) static int rpcap_setup_session(const char *source, struct pcap_rmtauth *auth, int *activep, SOCKET *sockctrlp, uint8_t *uses_sslp, SSL **sslp, - int rmt_flags, uint8_t *protocol_versionp, char *host, char *port, - char *iface, char *errbuf) + int rmt_flags, uint8_t *protocol_versionp, int *byte_swappedp, + char *host, char *port, char *iface, char *errbuf) { int type; int auth_result; @@ -2303,6 +2388,7 @@ rpcap_setup_session(const char *source, struct pcap_rmtauth *auth, *sockctrlp = activeconn->sockctrl; *sslp = activeconn->ssl; *protocol_versionp = activeconn->protocol_version; + *byte_swappedp = activeconn->byte_swapped; } else { @@ -2371,13 +2457,13 @@ rpcap_setup_session(const char *source, struct pcap_rmtauth *auth, if (auth == NULL && *userinfo != '\0') { - auth_result = rpcap_doauth_userinfo(*sockctrlp, *sslp, protocol_versionp, - userinfo, errbuf); + auth_result = rpcap_doauth_userinfo(*sockctrlp, *sslp, + protocol_versionp, byte_swappedp, userinfo, errbuf); } else { - auth_result = rpcap_doauth(*sockctrlp, *sslp, protocol_versionp, auth, - errbuf); + auth_result = rpcap_doauth(*sockctrlp, *sslp, + protocol_versionp, byte_swappedp, auth, errbuf); } if (auth_result == -1) @@ -2446,6 +2532,7 @@ pcap_t *pcap_open_rpcap(const char *source, int snaplen, int flags, int read_tim SOCKET sockctrl; SSL *ssl = NULL; uint8_t protocol_version; /* negotiated protocol version */ + int byte_swapped; /* server is known to be byte-swapped */ int active; uint32_t plen; char sendbuf[RPCAP_NETBUF_SIZE]; /* temporary buffer in which data to be sent is buffered */ @@ -2491,8 +2578,8 @@ pcap_t *pcap_open_rpcap(const char *source, int snaplen, int flags, int read_tim * Attempt to set up the session with the server. */ if (rpcap_setup_session(fp->opt.device, auth, &active, &sockctrl, - &pr->uses_ssl, &ssl, flags, &protocol_version, host, ctrlport, - iface, errbuf) == -1) + &pr->uses_ssl, &ssl, flags, &protocol_version, &byte_swapped, + host, ctrlport, iface, errbuf) == -1) { /* Session setup failed. */ pcap_close(fp); @@ -2541,6 +2628,7 @@ pcap_t *pcap_open_rpcap(const char *source, int snaplen, int flags, int read_tim pr->rmt_sockctrl = sockctrl; pr->ctrl_ssl = ssl; pr->protocol_version = protocol_version; + pr->byte_swapped = byte_swapped; pr->rmt_clientside = 1; /* This code is duplicated from the end of this function */ @@ -2612,6 +2700,7 @@ int pcap_findalldevs_ex_remote(const char *source, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf) { uint8_t protocol_version; /* protocol version */ + int byte_swapped; /* Server byte order is swapped from ours */ SOCKET sockctrl; /* socket descriptor of the control connection */ SSL *ssl = NULL; /* optional SSL handler for sockctrl */ uint32_t plen; @@ -2633,7 +2722,8 @@ pcap_findalldevs_ex_remote(const char *source, struct pcap_rmtauth *auth, pcap_i * Attempt to set up the session with the server. */ if (rpcap_setup_session(source, auth, &active, &sockctrl, &uses_ssl, - &ssl, 0, &protocol_version, host, port, NULL, errbuf) == -1) + &ssl, 0, &protocol_version, &byte_swapped, host, port, NULL, + errbuf) == -1) { /* Session setup failed. */ return -1; @@ -2925,6 +3015,7 @@ SOCKET pcap_remoteact_accept_ex(const char *address, const char *port, const cha SOCKET sockctrl; /* keeps the main socket identifier */ SSL *ssl = NULL; /* Optional SSL handler for sockctrl */ uint8_t protocol_version; /* negotiated protocol version */ + int byte_swapped; /* 1 if server byte order is known to be the reverse of ours */ struct activehosts *temp, *prev; /* temp var needed to scan he host list chain */ *connectinghost = 0; /* just in case */ @@ -3035,7 +3126,8 @@ SOCKET pcap_remoteact_accept_ex(const char *address, const char *port, const cha /* * Send authentication to the remote machine. */ - if (rpcap_doauth(sockctrl, ssl, &protocol_version, auth, errbuf) == -1) + if (rpcap_doauth(sockctrl, ssl, &protocol_version, &byte_swapped, + auth, errbuf) == -1) { /* Unrecoverable error. */ rpcap_senderror(sockctrl, ssl, 0, PCAP_ERR_REMOTEACCEPT, errbuf, NULL); @@ -3100,6 +3192,7 @@ SOCKET pcap_remoteact_accept_ex(const char *address, const char *port, const cha temp->sockctrl = sockctrl; temp->ssl = ssl; temp->protocol_version = protocol_version; + temp->byte_swapped = byte_swapped; temp->next = NULL; return sockctrl; |