aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile6
-rw-r--r--README8
-rw-r--r--pdesc.c56
-rw-r--r--pkt.c244
-rw-r--r--pkt.h3
-rw-r--r--ptunnel.c280
-rw-r--r--ptunnel.h6
-rw-r--r--utils.c51
-rw-r--r--utils.h4
9 files changed, 372 insertions, 286 deletions
diff --git a/Makefile b/Makefile
index fd5722c..1ea871e 100644
--- a/Makefile
+++ b/Makefile
@@ -3,14 +3,14 @@
# ptunnel.exe target added by Mike Miller, mike@mikeage.net
CC = gcc
-CFLAGS = -Wall -g -fstrict-aliasing
+CFLAGS = -Wall -g -fstrict-aliasing -Os
LDOPTS = -lpthread -lpcap
-PT_OBJS = options.o pdesc.o ptunnel.o md5.o base64.o
+PT_OBJS = utils.o options.o pkt.o pdesc.o ptunnel.o md5.o base64.o
WIN32_CC = mingw32-gcc
WIN32_CFLAGS = -g -Wall -DWIN32 -I"c:\Program Files\WpdPack\Include"
WIN32_LDOPTS = -lwpcap -lwsock32 -L"c:\Program Files\WpdPack\Lib"
-WIN32_PT_OBJS = options.obj pdesc.obj ptunnel.obj md5.obj base64.obj
+WIN32_PT_OBJS = utils.obj options.obj pkt.obj pdesc.obj ptunnel.obj md5.obj base64.obj
prefix = $(DESTDIR)/usr
bindir = $(prefix)/sbin
diff --git a/README b/README
index 688da91..a1e234f 100644
--- a/README
+++ b/README
@@ -1,11 +1,13 @@
-PingTunnel Read Me
+PingTunnel-ng Read Me
==================
-What is ptunnel?
+What is ptunnel-ng?
----------------
Ptunnel is an application that allows you to reliably tunnel TCP connections
to a remote host using ICMP echo request and reply packets, commonly known as
ping requests and replies.
+Ptunnel-ng is a bugfixed and refactored version of Ptunnel with some additional
+features e.g. change the magic value without recompiling (bypass Cisco IPS).
Contact details
@@ -16,6 +18,8 @@ The official ptunnel website is located here:
<http://www.cs.uit.no/~daniels/PingTunnel/>
The Windows port was created by Mike Miller:
<mike@mikeage.net>
+The ng fork was done by Toni Uhlig:
+ <matzeton@googlemail.com>
Compiling
diff --git a/pdesc.c b/pdesc.c
index 0195b4a..6cac5b8 100644
--- a/pdesc.c
+++ b/pdesc.c
@@ -1,3 +1,5 @@
+#include <stdlib.h>
+
#include "pdesc.h"
#include "options.h"
#include "ptunnel.h"
@@ -25,7 +27,7 @@ proxy_desc_t* create_and_insert_proxy_desc(uint16_t id_no, uint16_t icmp_id,
pthread_mutex_unlock(&chain_lock);
pt_log(kLog_debug, "Adding proxy desc to run loop. Type is %s. Will create socket: %s\n", (type == kUser_flag ? "user" : "proxy"), (sock ? "No" : "Yes"));
- cur = calloc(1, sizeof(proxy_desc_t));
+ cur = (proxy_desc_t *) calloc(1, sizeof(proxy_desc_t));
cur->id_no = id_no;
cur->dest_addr = *addr;
cur->dst_ip = dst_ip;
@@ -50,7 +52,7 @@ proxy_desc_t* create_and_insert_proxy_desc(uint16_t id_no, uint16_t icmp_id,
cur->pkt_type = kICMP_echo_request;
else
cur->pkt_type = (opts.unprivileged ? kICMP_echo_request : kICMP_echo_reply);
- cur->buf = malloc(icmp_receive_buf_len);
+ cur->buf = (char *) malloc(icmp_receive_buf_len);
cur->last_activity = time_as_double();
cur->authenticated = 0;
@@ -62,3 +64,53 @@ proxy_desc_t* create_and_insert_proxy_desc(uint16_t id_no, uint16_t icmp_id,
cur->xfer.bytes_out = 0.0;
return cur;
}
+
+/* remove_proxy_desc: Removes the given proxy desc, freeing its resources.
+ * Assumes that we hold the chain_lock.
+ */
+void remove_proxy_desc(proxy_desc_t *cur, proxy_desc_t *prev) {
+ int i;
+ struct timeval tt;
+
+ pt_log(kLog_debug, "Removing proxy descriptor.\n");
+ /* Get a timestamp, for making an entry in the seq_expiry_tbl */
+ gettimeofday(&tt, 0);
+ seq_expiry_tbl[cur->id_no] = tt.tv_sec+(2*kAutomatic_close_timeout);
+
+ /* Free resources associated with connection */
+ if (cur->buf)
+ free(cur->buf);
+ cur->buf = 0;
+ for (i=0;i<kPing_window_size;i++) {
+ if (cur->send_ring[i].pkt)
+ free(cur->send_ring[i].pkt);
+ cur->send_ring[i].pkt = 0;
+ if (cur->recv_ring[i])
+ free(cur->recv_ring[i]);
+ cur->recv_ring[i] = 0;
+ }
+ close(cur->sock);
+ cur->sock = 0;
+
+ /* Keep list up-to-date */
+ if (prev)
+ prev->next = cur->next;
+ else
+ chain = cur->next;
+ if (cur->challenge)
+ free(cur->challenge);
+ free(cur);
+ num_tunnels--;
+}
+
+forward_desc_t* create_fwd_desc(uint16_t seq_no, uint32_t data_len, char *data) {
+ forward_desc_t *fwd_desc;
+ fwd_desc = (forward_desc_t *) malloc(sizeof(forward_desc_t)+data_len);
+ fwd_desc->seq_no = seq_no;
+ fwd_desc->length = data_len;
+ fwd_desc->remaining = data_len;
+ if (data_len > 0)
+ memcpy(fwd_desc->data, data, data_len);
+ return fwd_desc;
+}
+
diff --git a/pkt.c b/pkt.c
new file mode 100644
index 0000000..07388c4
--- /dev/null
+++ b/pkt.c
@@ -0,0 +1,244 @@
+#ifndef WIN32
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <pthread.h>
+#endif
+#include <sys/time.h>
+
+#include "ptunnel.h"
+#include "pkt.h"
+#include "pdesc.h"
+#include "options.h"
+#include "utils.h"
+
+/* handle_proxy_packet:
+ * Processes incoming ICMP packets for the proxy. The packet can come either from the
+ * packet capture lib, or from the actual socket or both.
+ * Input: A buffer pointing at the start of an IP header, the buffer length and the proxy
+ * descriptor chain.
+ */
+void handle_packet(char *buf, unsigned bytes, int is_pcap, struct sockaddr_in *addr, int icmp_sock) {
+ ip_packet_t *ip_pkt;
+ icmp_echo_packet_t *pkt;
+ ping_tunnel_pkt_t *pt_pkt;
+ proxy_desc_t *cur;
+ uint32_t type_flag, pkt_flag, init_state, proxy_flag;
+ challenge_t *challenge;
+ struct timeval tt;
+
+ proxy_flag = kProxy_flag;
+
+ if (bytes < sizeof(icmp_echo_packet_t)+sizeof(ping_tunnel_pkt_t))
+ pt_log(kLog_verbose, "Skipping this packet - too short. "
+ "Expect: %d+%d = %d ; Got: %d\n",
+ sizeof(icmp_echo_packet_t),
+ sizeof(ping_tunnel_pkt_t),
+ sizeof(icmp_echo_packet_t) +
+ sizeof(ping_tunnel_pkt_t), bytes);
+ else {
+ if (opts.udp) {
+ ip_pkt = 0;
+ pkt = (icmp_echo_packet_t*)buf;
+ pt_pkt = (ping_tunnel_pkt_t*)pkt->data;
+ }
+ else {
+ ip_pkt = (ip_packet_t*)buf;
+ pkt = (icmp_echo_packet_t*)ip_pkt->data;
+ pt_pkt = (ping_tunnel_pkt_t*)pkt->data;
+ }
+
+ if (ntohl(pt_pkt->magic) == opts.magic) {
+ pt_pkt->state = ntohl(pt_pkt->state);
+ pkt->identifier = ntohs(pkt->identifier);
+ pt_pkt->id_no = ntohs(pt_pkt->id_no);
+ pt_pkt->seq_no = ntohs(pt_pkt->seq_no);
+ /* Find the relevant connection, if it exists */
+ pthread_mutex_lock(&chain_lock);
+ for (cur=chain;cur;cur=cur->next) {
+ if (cur->id_no == pt_pkt->id_no)
+ break;
+ }
+ pthread_mutex_unlock(&chain_lock);
+
+ /* Handle the packet if it comes from "the other end." This is a bit tricky
+ * to get right, since we receive both our own and the other end's packets.
+ * Basically, a proxy will accept any packet from a user, regardless if it
+ * has a valid connection or not. A user will only accept the packet if there
+ * exists a connection to handle it.
+ */
+ if (cur) {
+ type_flag = cur->type_flag;
+ if (type_flag == (uint32_t)kProxy_flag)
+ cur->icmp_id = pkt->identifier;
+ if (!is_pcap)
+ cur->xfer.icmp_in++;
+ }
+ else
+ type_flag = kProxy_flag;
+
+ pkt_flag = pt_pkt->state & kFlag_mask;
+ pt_pkt->state &= ~kFlag_mask;
+ pt_log(kLog_sendrecv, "Recv: %d [%d] bytes "
+ "[seq = %d] [type = %s] "
+ "[ack = %d] [icmp = %d] "
+ "[user = %s] [pcap = %d]\n",
+ bytes, ntohl(pt_pkt->data_len),
+ pt_pkt->seq_no, state_name[pt_pkt->state & (~kFlag_mask)],
+ ntohl(pt_pkt->ack), pkt->type,
+ (pkt_flag == kUser_flag ? "yes" : "no"), is_pcap);
+
+ /* This test essentially verifies that the packet comes from someone who isn't us. */
+ if ((pkt_flag == kUser_flag && type_flag == proxy_flag) ||
+ (pkt_flag == proxy_flag && type_flag == kUser_flag))
+ {
+ pt_pkt->data_len = ntohl(pt_pkt->data_len);
+ pt_pkt->ack = ntohl(pt_pkt->ack);
+ if (pt_pkt->state == kProxy_start) {
+ if (!cur && type_flag == proxy_flag) {
+ pt_log(kLog_info, "Incoming tunnel request from %s.\n",
+ inet_ntoa(*(struct in_addr *)&addr->sin_addr));
+ gettimeofday(&tt, 0);
+ if (tt.tv_sec < seq_expiry_tbl[pt_pkt->id_no]) {
+ pt_log(kLog_verbose, "Dropping request: ID was recently in use.\n");
+ return;
+ }
+ pt_log(kLog_info, "Starting new session to %s:%d with ID %d\n",
+ inet_ntoa(*(struct in_addr *)&pt_pkt->dst_ip),
+ ntohl(pt_pkt->dst_port), pt_pkt->id_no);
+ if ((opts.given_dst_ip && opts.given_dst_ip != pt_pkt->dst_ip) ||
+ ((uint32_t)-1 != opts.given_dst_port && opts.given_dst_port != ntohl(pt_pkt->dst_port)))
+ {
+ pt_log(kLog_info, "Destination administratively prohibited!\n");
+ return;
+ }
+
+ if (opts.password)
+ init_state = kProto_authenticate;
+ else
+ init_state = kProto_data;
+
+ cur = create_and_insert_proxy_desc(pt_pkt->id_no, pkt->identifier, 0,
+ addr, pt_pkt->dst_ip,
+ ntohl(pt_pkt->dst_port),
+ init_state, kProxy_flag);
+ if (init_state == kProto_authenticate) {
+ pt_log(kLog_debug, "Sending authentication challenge..\n");
+ /* Send challenge */
+ cur->challenge = generate_challenge();
+ memcpy(cur->buf, cur->challenge, sizeof(challenge_t));
+ queue_packet(icmp_sock, cur->pkt_type, cur->buf,
+ sizeof(challenge_t), cur->id_no,
+ cur->icmp_id, &cur->my_seq, cur->send_ring,
+ &cur->send_idx, &cur->send_wait_ack, 0, 0,
+ kProto_authenticate | cur->type_flag,
+ &cur->dest_addr, cur->next_remote_seq,
+ &cur->send_first_ack, &cur->ping_seq);
+ }
+ }
+ else if (type_flag == kUser_flag) {
+ pt_log(kLog_error, "Dropping proxy session request - we are not a proxy!\n");
+ return;
+ }
+ else
+ pt_log(kLog_error, "Dropping duplicate proxy session request.\n");
+ }
+ else if (cur && pt_pkt->state == kProto_authenticate) {
+ /* Sanity check packet length, and make sure it matches what we expect */
+ if (pt_pkt->data_len != sizeof(challenge_t)) {
+ pt_log(kLog_error, "Received challenge packet, but data length "
+ "is not as expected.\n");
+ pt_log(kLog_debug, "Data length: %d Expected: %d\n",
+ pt_pkt->data_len, sizeof (challenge_t));
+ cur->should_remove = 1;
+ return;
+ }
+ /* Prevent packet data from being forwarded over TCP! */
+ pt_pkt->data_len = 0;
+ challenge = (challenge_t*)pt_pkt->data;
+ /* If client: Compute response to challenge */
+ if (type_flag == kUser_flag) {
+ if (!opts.password) {
+ pt_log(kLog_error, "This proxy requires a password! "
+ "Please supply one usin g the -x switch.\n");
+ send_termination_msg(cur, icmp_sock);
+ cur->should_remove = 1;
+ return;
+ }
+ pt_log(kLog_debug, "Got authentication challenge - sending response\n");
+ generate_response(challenge);
+ queue_packet(icmp_sock, cur->pkt_type, (char*)challenge,
+ sizeof(challenge_t), cur->id_no, cur->icmp_id,
+ &cur->my_seq, cur->send_ring, &cur->send_idx,
+ &cur->send_wait_ack, 0, 0,
+ kProto_authenticate | cur->type_flag, &cur->dest_addr,
+ cur->next_remote_seq, &cur->send_first_ack, &cur-> ping_seq);
+ /* We have authenticated locally.
+ * It's up to the proxy now if it accepts our response or not..
+ */
+ cur->authenticated = 1;
+ handle_data(pkt, bytes, cur->recv_ring, &cur->recv_wait_send,
+ &cur->recv_idx, &cur->next_remote_seq);
+ return;
+ }
+ /* If proxy: Handle client's response to challenge */
+ else if (type_flag == proxy_flag) {
+ pt_log(kLog_debug, "Received remote challenge response.\n");
+ if (validate_challenge(cur->challenge, challenge) ||
+ cur->authenticated)
+ {
+ pt_log(kLog_verbose, "Remote end authenticated successfully.\n");
+ /* Authentication has succeeded, so now we can proceed
+ * to handle incoming TCP data.
+ */
+ cur->authenticated = 1;
+ cur->state = kProto_data;
+ /* Insert the packet into the receive ring, to avoid
+ * confusing the reliab ility mechanism.
+ */
+ handle_data(pkt, bytes, cur->recv_ring, &cur->recv_wait_send,
+ &cur->recv_idx, &cur->next_remote_seq);
+ }
+ else {
+ pt_log(kLog_info, "Remote end failed authentication.\n");
+ send_termination_msg(cur, icmp_sock);
+ cur->should_remove = 1;
+ }
+ return;
+ }
+ }
+ /* Handle close-messages for connections we know about */
+ if (cur && pt_pkt->state == kProto_close) {
+ pt_log(kLog_info, "Received session close from remote peer.\n");
+ cur->should_remove = 1;
+ return;
+ }
+ /* The proxy will ignore any other packets from the client
+ * until it has been authenticated. The packet resend mechanism
+ * insures that this isn't problematic.
+ */
+ if (type_flag == proxy_flag && opts.password &&
+ cur && !cur->authenticated)
+ {
+ pt_log(kLog_debug, "Ignoring packet with seq-no %d "
+ "- not authenticated yet.\n", pt_pkt->seq_no);
+ return;
+ }
+
+ if (cur && cur->sock) {
+ if (pt_pkt->state == kProto_data || pt_pkt->state == kProxy_start ||
+ pt_pkt->state == kProto_ack)
+ {
+ handle_data(pkt, bytes, cur->recv_ring, &cur->recv_wait_send,
+ &cur->recv_idx, &cur->next_remote_seq);
+ }
+ handle_ack((uint16_t)pt_pkt->ack, cur->send_ring, &cur->send_wait_ack,
+ 0, cur->send_idx, &cur->send_first_ack, &cur->remote_ack_val,
+ is_pcap);
+ cur->last_activity = time_as_double();
+ }
+ }
+ }
+ else
+ pt_log(kLog_verbose, "Ignored incoming packet.\n");
+ }
+}
diff --git a/pkt.h b/pkt.h
index 22cd289..c3731cb 100644
--- a/pkt.h
+++ b/pkt.h
@@ -80,4 +80,7 @@ typedef struct {
char data[0];
} __attribute__ ((packed)) icmp_echo_packet_t;
+
+void handle_packet(char *buf, unsigned bytes, int is_pcap, struct sockaddr_in *addr, int icmp_sock);
+
#endif
diff --git a/ptunnel.c b/ptunnel.c
index 6718f81..c16338a 100644
--- a/ptunnel.c
+++ b/ptunnel.c
@@ -83,10 +83,10 @@ pthread_mutex_t
chain_lock, // Lock protecting the chain of connections
num_threads_lock; // Lock protecting the num_threads variable
int
- num_threads = 0, // Current thread count
- num_tunnels = 0; // Current tunnel count
-uint32_t
- *seq_expiry_tbl = 0; // Table indicating when a connection ID is allowable (used by proxy)
+ num_threads = 0; // Current thread count
+uint32_t num_tunnels = 0; // Current tunnel count
+/** Table indicating when a connection ID is allowable (used by proxy) */
+uint32_t *seq_expiry_tbl = NULL;
// Some buffer constants
const int
@@ -716,219 +716,6 @@ void pcap_packet_handler(u_char *refcon, const struct pcap_pkthdr *hdr, const u
}
-
-/* handle_proxy_packet:
- Processes incoming ICMP packets for the proxy. The packet can come either from the
- packet capture lib, or from the actual socket or both.
- Input: A buffer pointing at the start of an IP header, the buffer length and the proxy
- descriptor chain.
-*/
-void handle_packet(char *buf, int bytes, int is_pcap, struct sockaddr_in *addr, int icmp_sock) {
- ip_packet_t *ip_pkt;
- icmp_echo_packet_t *pkt;
- ping_tunnel_pkt_t *pt_pkt;
- proxy_desc_t *cur;
- uint32_t type_flag, pkt_flag, init_state;
- challenge_t *challenge;
- struct timeval tt;
-
- if (bytes < sizeof(icmp_echo_packet_t)+sizeof(ping_tunnel_pkt_t))
- pt_log(kLog_verbose, "Skipping this packet - too short. Expect: %d+%d = %d ; Got: %d\n", sizeof(icmp_echo_packet_t), sizeof(ping_tunnel_pkt_t), sizeof(icmp_echo_packet_t)+sizeof(ping_tunnel_pkt_t), bytes);
- else {
- if (opts.udp) {
- ip_pkt = 0;
- pkt = (icmp_echo_packet_t*)buf;
- pt_pkt = (ping_tunnel_pkt_t*)pkt->data;
- }
- else {
- ip_pkt = (ip_packet_t*)buf;
- pkt = (icmp_echo_packet_t*)ip_pkt->data;
- pt_pkt = (ping_tunnel_pkt_t*)pkt->data;
- }
- if (ntohl(pt_pkt->magic) == opts.magic) {
- pt_pkt->state = ntohl(pt_pkt->state);
- pkt->identifier = ntohs(pkt->identifier);
- pt_pkt->id_no = ntohs(pt_pkt->id_no);
- pt_pkt->seq_no = ntohs(pt_pkt->seq_no);
- // Find the relevant connection, if it exists
- pthread_mutex_lock(&chain_lock);
- for (cur=chain;cur;cur=cur->next) {
- if (cur->id_no == pt_pkt->id_no)
- break;
- }
- pthread_mutex_unlock(&chain_lock);
-
- /* Handle the packet if it comes from "the other end." This is a bit tricky
- to get right, since we receive both our own and the other end's packets.
- Basically, a proxy will accept any packet from a user, regardless if it
- has a valid connection or not. A user will only accept the packet if there
- exists a connection to handle it.
- */
- if (cur) {
- type_flag = cur->type_flag;
- if (type_flag == kProxy_flag)
- cur->icmp_id = pkt->identifier;
-
- if (!is_pcap)
- cur->xfer.icmp_in++;
- }
- else
- type_flag = kProxy_flag;
-
- pkt_flag = pt_pkt->state & kFlag_mask;
- pt_pkt->state &= ~kFlag_mask;
- pt_log(kLog_sendrecv, "Recv: %d [%d] bytes [seq = %d] [type = %s] [ack = %d] [icmp = %d] [user = %s] [pcap = %d]\n",
- bytes, ntohl(pt_pkt->data_len), pt_pkt->seq_no, state_name[pt_pkt->state & (~kFlag_mask)],
- ntohl(pt_pkt->ack), pkt->type, (pkt_flag == kUser_flag ? "yes" : "no"), is_pcap);
-
- // This test essentially verifies that the packet comes from someone who isn't us.
- if ((pkt_flag == kUser_flag && type_flag == kProxy_flag) || (pkt_flag == kProxy_flag && type_flag == kUser_flag)) {
- pt_pkt->data_len = ntohl(pt_pkt->data_len);
- pt_pkt->ack = ntohl(pt_pkt->ack);
- if (pt_pkt->state == kProxy_start) {
- if (!cur && type_flag == kProxy_flag) {
- pt_log(kLog_info, "Incoming tunnel request from %s.\n", inet_ntoa(*(struct in_addr*)&addr->sin_addr));
- gettimeofday(&tt, 0);
- if (tt.tv_sec < seq_expiry_tbl[pt_pkt->id_no]) {
- pt_log(kLog_verbose, "Dropping request: ID was recently in use.\n");
- return;
- }
- pt_log(kLog_info, "Starting new session to %s:%d with ID %d\n", inet_ntoa(*(struct in_addr*)&pt_pkt->dst_ip), ntohl(pt_pkt->dst_port), pt_pkt->id_no);
- if ((opts.given_dst_ip && opts.given_dst_ip != pt_pkt->dst_ip) || (-1 != opts.given_dst_port && opts.given_dst_port != ntohl(pt_pkt->dst_port))) {
- pt_log(kLog_info, "Destination administratively prohibited!\n");
- return;
- }
- if (opts.password)
- init_state = kProto_authenticate;
- else
- init_state = kProto_data;
- cur = create_and_insert_proxy_desc(pt_pkt->id_no, pkt->identifier, 0, addr, pt_pkt->dst_ip, ntohl(pt_pkt->dst_port), init_state, kProxy_flag);
- if (init_state == kProto_authenticate) {
- pt_log(kLog_debug, "Sending authentication challenge..\n");
- // Send challenge
- cur->challenge = generate_challenge();
- memcpy(cur->buf, cur->challenge, sizeof(challenge_t));
- queue_packet(icmp_sock, cur->pkt_type, cur->buf, sizeof(challenge_t), cur->id_no, cur->icmp_id, &cur->my_seq, cur->send_ring, &cur->send_idx, &cur->send_wait_ack, 0, 0, kProto_authenticate | cur->type_flag, &cur->dest_addr, cur->next_remote_seq, &cur->send_first_ack, &cur->ping_seq);
- }
- }
- else if (type_flag == kUser_flag) {
- pt_log(kLog_error, "Dropping proxy session request - we are not a proxy!\n");
- return;
- }
- else
- pt_log(kLog_error, "Dropping duplicate proxy session request.\n");
- }
- else if (cur && pt_pkt->state == kProto_authenticate) {
- // Sanity check packet length, and make sure it matches what we expect
- if (pt_pkt->data_len != sizeof(challenge_t)) {
- pt_log(kLog_error, "Received challenge packet, but data length is not as expected.\n");
- pt_log(kLog_debug, "Data length: %d Expected: %d\n", pt_pkt->data_len, sizeof(challenge_t));
- cur->should_remove = 1;
- return;
- }
- // Prevent packet data from being forwarded over TCP!
- pt_pkt->data_len = 0;
- challenge = (challenge_t*)pt_pkt->data;
- // If client: Compute response to challenge
- if (type_flag == kUser_flag) {
- if (!opts.password) {
- pt_log(kLog_error, "This proxy requires a password! Please supply one using the -x switch.\n");
- send_termination_msg(cur, icmp_sock);
- cur->should_remove = 1;
- return;
- }
- pt_log(kLog_debug, "Got authentication challenge - sending response\n");
- generate_response(challenge);
- queue_packet(icmp_sock, cur->pkt_type, (char*)challenge, sizeof(challenge_t), cur->id_no, cur->icmp_id, &cur->my_seq, cur->send_ring, &cur->send_idx, &cur->send_wait_ack, 0, 0, kProto_authenticate | cur->type_flag, &cur->dest_addr, cur->next_remote_seq, &cur->send_first_ack, &cur->ping_seq);
- // We have authenticated locally. It's up to the proxy now if it accepts our response or not..
- cur->authenticated = 1;
- handle_data(pkt, bytes, cur->recv_ring, &cur->recv_wait_send, &cur->recv_idx, &cur->next_remote_seq);
- return;
- }
- // If proxy: Handle client's response to challenge
- else if (type_flag == kProxy_flag) {
- pt_log(kLog_debug, "Received remote challenge response.\n");
- if (validate_challenge(cur->challenge, challenge) || cur->authenticated) {
- pt_log(kLog_verbose, "Remote end authenticated successfully.\n");
- // Authentication has succeeded, so now we can proceed to handle incoming TCP data.
- cur->authenticated = 1;
- cur->state = kProto_data;
- // Insert the packet into the receive ring, to avoid confusing the reliability mechanism.
- handle_data(pkt, bytes, cur->recv_ring, &cur->recv_wait_send, &cur->recv_idx, &cur->next_remote_seq);
- }
- else {
- pt_log(kLog_info, "Remote end failed authentication.\n");
- send_termination_msg(cur, icmp_sock);
- cur->should_remove = 1;
- }
- return;
- }
- }
- // Handle close-messages for connections we know about
- if (cur && pt_pkt->state == kProto_close) {
- pt_log(kLog_info, "Received session close from remote peer.\n");
- cur->should_remove = 1;
- return;
- }
- // The proxy will ignore any other packets from the client
- // until it has been authenticated. The packet resend mechanism
- // insures that this isn't problematic.
- if (type_flag == kProxy_flag && opts.password && cur && !cur->authenticated) {
- pt_log(kLog_debug, "Ignoring packet with seq-no %d - not authenticated yet.\n", pt_pkt->seq_no);
- return;
- }
-
- if (cur && cur->sock) {
- if (pt_pkt->state == kProto_data || pt_pkt->state == kProxy_start || pt_pkt->state == kProto_ack)
- handle_data(pkt, bytes, cur->recv_ring, &cur->recv_wait_send, &cur->recv_idx, &cur->next_remote_seq);
- handle_ack((uint16_t)pt_pkt->ack, cur->send_ring, &cur->send_wait_ack, 0, cur->send_idx, &cur->send_first_ack, &cur->remote_ack_val, is_pcap);
- cur->last_activity = time_as_double();
- }
- }
- }
- else
- pt_log(kLog_verbose, "Ignored incoming packet.\n");
- }
-}
-
-/* remove_proxy_desc: Removes the given proxy desc, freeing its resources.
- Assumes that we hold the chain_lock.
-*/
-void remove_proxy_desc(proxy_desc_t *cur, proxy_desc_t *prev) {
- int i;
- struct timeval tt;
-
- pt_log(kLog_debug, "Removing proxy descriptor.\n");
- // Get a timestamp, for making an entry in the seq_expiry_tbl
- gettimeofday(&tt, 0);
- seq_expiry_tbl[cur->id_no] = tt.tv_sec+(2*kAutomatic_close_timeout);
-
- // Free resources associated with connection
- if (cur->buf)
- free(cur->buf);
- cur->buf = 0;
- for (i=0;i<kPing_window_size;i++) {
- if (cur->send_ring[i].pkt)
- free(cur->send_ring[i].pkt);
- cur->send_ring[i].pkt = 0;
- if (cur->recv_ring[i])
- free(cur->recv_ring[i]);
- cur->recv_ring[i] = 0;
- }
- close(cur->sock);
- cur->sock = 0;
-
- // Keep list up-to-date
- if (prev)
- prev->next = cur->next;
- else
- chain = cur->next;
- if (cur->challenge)
- free(cur->challenge);
- free(cur);
- num_tunnels--;
-}
-
#if kPT_add_iphdr
static int ip_id_counter = 1;
#endif
@@ -1218,19 +1005,6 @@ void handle_ack(uint16_t seq_no, icmp_desc_t ring[], int *packets_awaiting_ack,
}
-
-forward_desc_t* create_fwd_desc(uint16_t seq_no, uint32_t data_len, char *data) {
- forward_desc_t *fwd_desc;
- fwd_desc = malloc(sizeof(forward_desc_t)+data_len);
- fwd_desc->seq_no = seq_no;
- fwd_desc->length = data_len;
- fwd_desc->remaining = data_len;
- if (data_len > 0)
- memcpy(fwd_desc->data, data, data_len);
- return fwd_desc;
-}
-
-
uint16_t calc_icmp_checksum(uint16_t *data, int bytes) {
uint32_t sum;
int i;
@@ -1308,49 +1082,3 @@ void send_termination_msg(proxy_desc_t *cur, int icmp_sock) {
queue_packet(icmp_sock, cur->pkt_type, 0, 0, cur->id_no, cur->icmp_id, &cur->my_seq, cur->send_ring, &cur->send_idx, &cur->send_wait_ack, 0, 0, kProto_close | cur->type_flag, &cur->dest_addr, cur->next_remote_seq, &cur->send_first_ack, &cur->ping_seq);
cur->xfer.icmp_out += 2;
}
-
-
-void pt_log(int level, const char *fmt, ...) {
- va_list args;
- const char *header[] = { "[err]: ",
- "[inf]: ",
- "[evt]: ",
- "[vbs]: ",
- "[dbg]: ",
- "[xfr]: " };
-#ifndef WIN32
- int syslog_levels[] = {LOG_ERR, LOG_NOTICE, LOG_NOTICE, LOG_INFO, LOG_DEBUG, LOG_DEBUG};
-#endif /* !WIN32 */
-
- if (level <= opts.log_level) {
- va_start(args, fmt);
-#ifndef WIN32
- if (opts.use_syslog) {
- char log[255];
- int header_len;
- header_len = snprintf(log,sizeof(log),"%s",header[level]);
- vsnprintf(log+header_len,sizeof(log)-header_len,fmt,args);
- syslog(syslog_levels[level], "%s", log);
- }
- else
-#endif /* !WIN32 */
- fprintf(opts.log_file, "%s", header[level]), vfprintf(opts.log_file, fmt, args);
- va_end(args);
-#ifndef WIN32
- if (opts.log_file != stdout && !opts.use_syslog)
-#else
- if (opts.log_file != stdout)
-#endif
- fflush(opts.log_file);
- }
-}
-
-
-double time_as_double(void) {
- double result;
- struct timeval tt;
-
- gettimeofday(&tt, 0);
- result = (double)tt.tv_sec + ((double)tt.tv_usec / (double)10e5);
- return result;
-}
diff --git a/ptunnel.h b/ptunnel.h
index 22313b0..4f81b39 100644
--- a/ptunnel.h
+++ b/ptunnel.h
@@ -64,7 +64,6 @@
#include <stdlib.h>
#include <string.h>
#include <time.h>
-#include <sys/time.h>
#include <signal.h>
#include <stdint.h>
#include <stdbool.h>
@@ -75,9 +74,11 @@
#include "challenge.h"
extern pthread_mutex_t chain_lock;
-extern int num_tunnels;
+extern uint32_t num_tunnels;
extern const int icmp_receive_buf_len;
extern proxy_desc_t *chain;
+extern uint32_t *seq_expiry_tbl;
+extern const char *state_name[kNum_proto_types];
/* pt_thread_info_t: A simple (very simple, in fact) structure that allows us
to pass an arbitrary number of params to the threads we create. Currently,
@@ -132,7 +133,6 @@ typedef struct {
// Prototypes (sorry about the long lines..)
void* pt_proxy(void *args);
void pcap_packet_handler(u_char *refcon, const struct pcap_pkthdr *hdr, const u_char* pkt);
- void handle_packet(char *buf, int bytes, int is_pcap, struct sockaddr_in *addr, int icmp_sock);
void pt_forwarder(void);
diff --git a/utils.c b/utils.c
new file mode 100644
index 0000000..c1cd6aa
--- /dev/null
+++ b/utils.c
@@ -0,0 +1,51 @@
+#ifndef WIN32
+#include <syslog.h>
+#endif
+#include <sys/time.h>
+
+#include "utils.h"
+#include "options.h"
+
+void pt_log(int level, const char *fmt, ...) {
+ va_list args;
+ const char *header[] = { "[err]: ",
+ "[inf]: ",
+ "[evt]: ",
+ "[vbs]: ",
+ "[dbg]: ",
+ "[xfr]: " };
+#ifndef WIN32
+ int syslog_levels[] = {LOG_ERR, LOG_NOTICE, LOG_NOTICE, LOG_INFO, LOG_DEBUG, LOG_DEBUG};
+#endif /* !WIN32 */
+
+ if (level <= opts.log_level) {
+ va_start(args, fmt);
+#ifndef WIN32
+ if (opts.use_syslog) {
+ char log[255];
+ int header_len;
+ header_len = snprintf(log,sizeof(log),"%s",header[level]);
+ vsnprintf(log+header_len,sizeof(log)-header_len,fmt,args);
+ syslog(syslog_levels[level], "%s", log);
+ }
+ else
+#endif /* !WIN32 */
+ fprintf(opts.log_file, "%s", header[level]), vfprintf(opts.log_file, fmt, args);
+ va_end(args);
+#ifndef WIN32
+ if (opts.log_file != stdout && !opts.use_syslog)
+#else
+ if (opts.log_file != stdout)
+#endif
+ fflush(opts.log_file);
+ }
+}
+
+double time_as_double(void) {
+ double result;
+ struct timeval tt;
+
+ gettimeofday(&tt, 0);
+ result = (double)tt.tv_sec + ((double)tt.tv_usec / (double)10e5);
+ return result;
+}
diff --git a/utils.h b/utils.h
index 2ac39f7..5bd539a 100644
--- a/utils.h
+++ b/utils.h
@@ -3,4 +3,8 @@
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
+void pt_log(int level, const char *fmt, ...);
+
+double time_as_double(void);
+
#endif