TCPonly now works (in a relatively clean way too).

This commit is contained in:
Guus Sliepen 2001-05-25 11:54:28 +00:00
parent a5e2ae6b2b
commit fcf869cd42
6 changed files with 104 additions and 97 deletions

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: connection.h,v 1.1.2.8 2001/03/04 13:59:25 guus Exp $ $Id: connection.h,v 1.1.2.9 2001/05/25 11:54:28 guus Exp $
*/ */
#ifndef __TINC_CONNECTION_H__ #ifndef __TINC_CONNECTION_H__
@ -85,7 +85,7 @@ typedef struct connection_t {
char *buffer; /* metadata input buffer */ char *buffer; /* metadata input buffer */
int buflen; /* bytes read into buffer */ int buflen; /* bytes read into buffer */
int reqlen; /* length of first request in buffer */ int tcplen; /* length of incoming TCPpacket */
int allow_request; /* defined if there's only one request possible */ int allow_request; /* defined if there's only one request possible */
time_t last_ping_time; /* last time we saw some activity from the other end */ time_t last_ping_time; /* last time we saw some activity from the other end */

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: meta.c,v 1.1.2.17 2001/05/25 08:36:11 guus Exp $ $Id: meta.c,v 1.1.2.18 2001/05/25 11:54:28 guus Exp $
*/ */
#include "config.h" #include "config.h"
@ -45,15 +45,13 @@
int send_meta(connection_t *cl, char *buffer, int length) int send_meta(connection_t *cl, char *buffer, int length)
{ {
char outbuf[MAXBUFSIZE];
char *bufp; char *bufp;
int outlen; int outlen;
char outbuf[MAXBUFSIZE];
cp cp
if(debug_lvl >= DEBUG_META) if(debug_lvl >= DEBUG_META)
syslog(LOG_DEBUG, _("Sending %d bytes of metadata to %s (%s): %s"), length, syslog(LOG_DEBUG, _("Sending %d bytes of metadata to %s (%s)"), length,
cl->name, cl->hostname, buffer); cl->name, cl->hostname);
buffer[length-1]='\n';
if(cl->status.encryptout) if(cl->status.encryptout)
{ {
@ -91,9 +89,9 @@ int receive_meta(connection_t *cl)
{ {
int x, l = sizeof(x); int x, l = sizeof(x);
int oldlen, i; int oldlen, i;
int lenin = 0; int lenin, reqlen;
char inbuf[MAXBUFSIZE];
int decrypted = 0; int decrypted = 0;
char inbuf[MAXBUFSIZE];
cp cp
if(getsockopt(cl->meta_socket, SOL_SOCKET, SO_ERROR, &x, &l) < 0) if(getsockopt(cl->meta_socket, SOL_SOCKET, SO_ERROR, &x, &l) < 0)
{ {
@ -108,6 +106,15 @@ cp
return -1; return -1;
} }
/* Strategy:
- Read as much as possible from the TCP socket in one go.
- Decrypt it.
- Check if a full request is in the input buffer.
- If yes, process request and remove it from the buffer,
then check again.
- If not, keep stuff in buffer and exit.
*/
lenin = read(cl->meta_socket, cl->buffer + cl->buflen, MAXBUFSIZE - cl->buflen); lenin = read(cl->meta_socket, cl->buffer + cl->buflen, MAXBUFSIZE - cl->buflen);
if(lenin<=0) if(lenin<=0)
@ -133,6 +140,8 @@ cp
while(lenin) while(lenin)
{ {
/* Decrypt */
if(cl->status.decryptin && !decrypted) if(cl->status.decryptin && !decrypted)
{ {
EVP_DecryptUpdate(cl->cipher_inctx, inbuf, &lenin, cl->buffer + oldlen, lenin); EVP_DecryptUpdate(cl->cipher_inctx, inbuf, &lenin, cl->buffer + oldlen, lenin);
@ -140,31 +149,51 @@ cp
decrypted = 1; decrypted = 1;
} }
cl->reqlen = 0; /* Are we receiving a TCPpacket? */
if(cl->tcplen)
{
if(cl->tcplen <= cl->buflen)
{
receive_tcppacket(cl, cl->buffer, cl->tcplen);
cl->buflen -= cl->tcplen;
lenin -= cl->tcplen;
memmove(cl->buffer, cl->buffer + cl->tcplen, cl->buflen);
oldlen = 0;
cl->tcplen = 0;
continue;
}
else
{
break;
}
}
/* Otherwise we are waiting for a request */
reqlen = 0;
for(i = oldlen; i < cl->buflen; i++) for(i = oldlen; i < cl->buflen; i++)
{ {
if(cl->buffer[i] == '\n') if(cl->buffer[i] == '\n')
{ {
cl->buffer[i] = 0; /* replace end-of-line by end-of-string so we can use sscanf */ cl->buffer[i] = '\0'; /* replace end-of-line by end-of-string so we can use sscanf */
cl->reqlen = i + 1; reqlen = i + 1;
break; break;
} }
} }
if(cl->reqlen) if(reqlen)
{ {
if(debug_lvl >= DEBUG_META)
syslog(LOG_DEBUG, _("Got request from %s (%s): %s"),
cl->name, cl->hostname, cl->buffer);
if(receive_request(cl)) if(receive_request(cl))
return -1; return -1;
cl->buflen -= cl->reqlen; cl->buflen -= reqlen;
lenin -= cl->reqlen; lenin -= reqlen;
memmove(cl->buffer, cl->buffer + cl->reqlen, cl->buflen); memmove(cl->buffer, cl->buffer + reqlen, cl->buflen);
oldlen = 0; oldlen = 0;
continue;
} }
else else
{ {

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: net.c,v 1.35.4.107 2001/05/25 10:08:11 guus Exp $ $Id: net.c,v 1.35.4.108 2001/05/25 11:54:28 guus Exp $
*/ */
#include "config.h" #include "config.h"
@ -184,6 +184,17 @@ cp
cp cp
} }
void receive_tcppacket(connection_t *cl, char *buffer, int len)
{
vpn_packet_t outpkt;
cp
outpkt.len = len;
memcpy(outpkt.data, buffer, len);
receive_packet(cl, &outpkt);
cp
}
void accept_packet(vpn_packet_t *packet) void accept_packet(vpn_packet_t *packet)
{ {
cp cp
@ -203,7 +214,7 @@ cp
if(write(tap_fd, packet->data - 2, packet->len + 2) < 0) if(write(tap_fd, packet->data - 2, packet->len + 2) < 0)
syslog(LOG_ERR, _("Can't write to ethertap device: %m")); syslog(LOG_ERR, _("Can't write to ethertap device: %m"));
else else
total_tap_out += packet->len + 2; total_tap_out += packet->len;
} }
cp cp
} }
@ -1290,7 +1301,7 @@ cp
vp.len = lenin - 2; vp.len = lenin - 2;
} }
total_tap_in += lenin; total_tap_in += vp.len;
if(lenin < 32) if(lenin < 32)
{ {

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: net.h,v 1.9.4.30 2001/05/07 19:08:46 guus Exp $ $Id: net.h,v 1.9.4.31 2001/05/25 11:54:28 guus Exp $
*/ */
#ifndef __TINC_NET_H__ #ifndef __TINC_NET_H__
@ -109,6 +109,7 @@ extern int str2opt(const char *);
extern char *opt2str(int); extern char *opt2str(int);
extern void send_packet(connection_t *, vpn_packet_t *); extern void send_packet(connection_t *, vpn_packet_t *);
extern void receive_packet(connection_t *, vpn_packet_t *); extern void receive_packet(connection_t *, vpn_packet_t *);
extern void receive_tcppacket(connection_t *, char *, int);
extern void accept_packet(vpn_packet_t *); extern void accept_packet(vpn_packet_t *);
extern int setup_network_connections(void); extern int setup_network_connections(void);
extern void close_network_connections(void); extern void close_network_connections(void);

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: protocol.c,v 1.28.4.90 2001/05/25 08:36:11 guus Exp $ $Id: protocol.c,v 1.28.4.91 2001/05/25 11:54:28 guus Exp $
*/ */
#include "config.h" #include "config.h"
@ -106,11 +106,15 @@ cp
return -1; return -1;
} }
len++;
if(debug_lvl >= DEBUG_PROTOCOL) if(debug_lvl >= DEBUG_PROTOCOL)
syslog(LOG_DEBUG, _("Sending %s to %s (%s)"), request_name[request], cl->name, cl->hostname); {
if(debug_lvl >= DEBUG_META)
syslog(LOG_DEBUG, _("Sending %s to %s (%s): %s"), request_name[request], cl->name, cl->hostname, buffer);
else
syslog(LOG_DEBUG, _("Sending %s to %s (%s)"), request_name[request], cl->name, cl->hostname);
}
buffer[len++] = '\n';
cp cp
return send_meta(cl, buffer, len); return send_meta(cl, buffer, len);
} }
@ -118,20 +122,31 @@ cp
int receive_request(connection_t *cl) int receive_request(connection_t *cl)
{ {
int request; int request;
cp cp
if(sscanf(cl->buffer, "%d", &request) == 1) if(sscanf(cl->buffer, "%d", &request) == 1)
{ {
if((request < 0) || (request >= LAST) || (request_handlers[request] == NULL)) if((request < 0) || (request >= LAST) || (request_handlers[request] == NULL))
{ {
syslog(LOG_ERR, _("Unknown request from %s (%s)"), if(debug_lvl >= DEBUG_META)
cl->name, cl->hostname); syslog(LOG_DEBUG, _("Unknown request from %s (%s): %s"),
cl->name, cl->hostname, cl->buffer);
else
syslog(LOG_ERR, _("Unknown request from %s (%s)"),
cl->name, cl->hostname);
return -1; return -1;
} }
else else
{ {
if(debug_lvl >= DEBUG_PROTOCOL) if(debug_lvl >= DEBUG_PROTOCOL)
syslog(LOG_DEBUG, _("Got %s from %s (%s)"), {
request_name[request], cl->name, cl->hostname); if(debug_lvl >= DEBUG_META)
syslog(LOG_DEBUG, _("Got %s from %s (%s): %s"),
request_name[request], cl->name, cl->hostname, cl->buffer);
else
syslog(LOG_DEBUG, _("Got %s from %s (%s)"),
request_name[request], cl->name, cl->hostname);
}
} }
if((cl->allow_request != ALL) && (cl->allow_request != request)) if((cl->allow_request != ALL) && (cl->allow_request != request))
@ -158,34 +173,8 @@ cp
return 0; return 0;
} }
/* Connection protocol: /* The authentication protocol is described in detail in doc/SECURITY2,
the rest will be described in doc/PROTOCOL. */
Client Server
send_id(u)
send_challenge(R)
send_chal_reply(H)
send_id(u)
send_challenge(R)
send_chal_reply(H)
---------------------------------------
send_metakey(R)
send_metakey(R)
---------------------------------------
send_ack(u)
send_ack(u)
---------------------------------------
Other requests(E)...
(u) Unencrypted,
(R) RSA,
(H) SHA1,
(E) Encrypted with symmetric cipher.
Part of the challenge is directly used to set the symmetric cipher
key and the initial vector. Since a man-in-the-middle cannot
decrypt the RSA challenges, this means that he cannot get or forge
the key for the symmetric cipher.
*/
int send_id(connection_t *cl) int send_id(connection_t *cl)
{ {
@ -1287,53 +1276,29 @@ int send_tcppacket(connection_t *cl, vpn_packet_t *packet)
{ {
int x; int x;
cp cp
/* Evil hack. */
x = send_request(cl->nexthop, "%d %hd", PACKET, packet->len); x = send_request(cl->nexthop, "%d %hd", PACKET, packet->len);
if(x) if(x)
return x; return x;
cp
return send_meta(cl->nexthop, packet->data, packet->len); return send_meta(cl, packet->data, packet->len);
} }
int tcppacket_h(connection_t *cl) int tcppacket_h(connection_t *cl)
{ {
vpn_packet_t packet; short int len;
char *p;
int todo, x;
cp cp
if(sscanf(cl->buffer, "%*d %hd", &packet.len) != 1) if(sscanf(cl->buffer, "%*d %hd", &len) != 1)
{ {
syslog(LOG_ERR, _("Got bad PACKET from %s (%s)"), cl->name, cl->hostname); syslog(LOG_ERR, _("Got bad PACKET from %s (%s)"), cl->name, cl->hostname);
return -1; return -1;
} }
/* Evil hack. */ /* Set reqlen to len, this will tell receive_meta() that a tcppacket is coming. */
p = packet.data; cl->tcplen = len;
todo = packet.len;
while(todo)
{
x = read(cl->meta_socket, p, todo);
if(x<=0)
{
if(x==0)
syslog(LOG_NOTICE, _("Connection closed by %s (%s)"), cl->name, cl->hostname);
else
if(errno==EINTR || errno==EAGAIN) /* FIXME: select() or poll() or reimplement this evil hack */
continue;
else
syslog(LOG_ERR, _("Error during reception of PACKET from %s (%s): %m"), cl->name, cl->hostname);
return -1;
}
todo -= x;
p += x;
}
receive_packet(cl, &packet);
cp cp
return 0; return 0;
} }

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: route.c,v 1.1.2.7 2001/03/04 13:59:32 guus Exp $ $Id: route.c,v 1.1.2.8 2001/05/25 11:54:28 guus Exp $
*/ */
#include "config.h" #include "config.h"
@ -181,11 +181,12 @@ void route_incoming(connection_t *source, vpn_packet_t *packet)
{ {
switch(routing_mode) switch(routing_mode)
{ {
case RMODE_ROUTER:
memcpy(packet->data, mymac.net.mac.address.x, 6);
break;
case RMODE_SWITCH: case RMODE_SWITCH:
learn_mac(source, (mac_t *)(&packet->data[0])); learn_mac(source, (mac_t *)(&packet->data[0]));
break; break;
case RMODE_ROUTER:
memcpy(packet->data, mymac.net.mac.address.x, 6);
} }
accept_packet(packet); accept_packet(packet);