simplify AVP unhiding code
This commit is contained in:
parent
7825a26691
commit
466ffcdaac
3 changed files with 79 additions and 90 deletions
3
Changes
3
Changes
|
|
@ -1,4 +1,4 @@
|
||||||
* Mon Feb 14 2005 Brendan O'Dea <bod@optusnet.com.au> 2.1.0
|
* Thu Mar 10 2005 Brendan O'Dea <bod@optusnet.com.au> 2.1.0
|
||||||
- Add IPv6 support from Jonathan McDowell.
|
- Add IPv6 support from Jonathan McDowell.
|
||||||
- Add CHAP support from Jordan Hrycaj (work in progress).
|
- Add CHAP support from Jordan Hrycaj (work in progress).
|
||||||
- Sanity check that cluster_send_session is not called from a child
|
- Sanity check that cluster_send_session is not called from a child
|
||||||
|
|
@ -32,6 +32,7 @@
|
||||||
address.
|
address.
|
||||||
- Avoid a possible buffer overflow in processpap.
|
- Avoid a possible buffer overflow in processpap.
|
||||||
- Kill session if authentication was rejected.
|
- Kill session if authentication was rejected.
|
||||||
|
- Simplify AVP unhiding code.
|
||||||
|
|
||||||
* Fri Dec 17 2004 Brendan O'Dea <bod@optusnet.com.au> 2.0.13
|
* Fri Dec 17 2004 Brendan O'Dea <bod@optusnet.com.au> 2.0.13
|
||||||
- Better cluster master collision resolution: keep a counter of state
|
- Better cluster master collision resolution: keep a counter of state
|
||||||
|
|
|
||||||
164
l2tpns.c
164
l2tpns.c
|
|
@ -4,7 +4,7 @@
|
||||||
// Copyright (c) 2002 FireBrick (Andrews & Arnold Ltd / Watchfront Ltd) - GPL licenced
|
// Copyright (c) 2002 FireBrick (Andrews & Arnold Ltd / Watchfront Ltd) - GPL licenced
|
||||||
// vim: sw=8 ts=8
|
// vim: sw=8 ts=8
|
||||||
|
|
||||||
char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.84 2005/02/14 06:58:39 bodea Exp $";
|
char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.85 2005/03/10 03:08:08 bodea Exp $";
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
@ -187,7 +187,7 @@ static int remove_plugin(char *plugin_name);
|
||||||
static void plugins_done(void);
|
static void plugins_done(void);
|
||||||
static void processcontrol(uint8_t *buf, int len, struct sockaddr_in *addr, int alen);
|
static void processcontrol(uint8_t *buf, int len, struct sockaddr_in *addr, int alen);
|
||||||
static tunnelidt new_tunnel(void);
|
static tunnelidt new_tunnel(void);
|
||||||
static int unhide_avp(uint8_t *avp, tunnelidt t, sessionidt s, uint16_t length);
|
static void unhide_value(uint8_t *value, size_t len, uint16_t type, uint8_t *vector, size_t vec_len);
|
||||||
|
|
||||||
// return internal time (10ths since process startup)
|
// return internal time (10ths since process startup)
|
||||||
static clockt now(void)
|
static clockt now(void)
|
||||||
|
|
@ -1761,7 +1761,7 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
|
||||||
{ // control
|
{ // control
|
||||||
uint16_t message = 0xFFFF; // message type
|
uint16_t message = 0xFFFF; // message type
|
||||||
uint8_t fatal = 0;
|
uint8_t fatal = 0;
|
||||||
uint8_t mandatorymessage = 0;
|
uint8_t mandatory = 0;
|
||||||
uint8_t chap = 0; // if CHAP being used
|
uint8_t chap = 0; // if CHAP being used
|
||||||
uint16_t asession = 0; // assigned session
|
uint16_t asession = 0; // assigned session
|
||||||
uint32_t amagic = 0; // magic number
|
uint32_t amagic = 0; // magic number
|
||||||
|
|
@ -1777,7 +1777,10 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((*buf & 0xCA) != 0xC8)
|
// control messages must have bits 0x80|0x40|0x08
|
||||||
|
// (type, length and sequence) set, and bits 0x02|0x01
|
||||||
|
// (offset and priority) clear
|
||||||
|
if ((*buf & 0xCB) != 0xC8)
|
||||||
{
|
{
|
||||||
LOG(1, s, t, "Bad control header %02X\n", *buf);
|
LOG(1, s, t, "Bad control header %02X\n", *buf);
|
||||||
STAT(tunnel_rx_errors);
|
STAT(tunnel_rx_errors);
|
||||||
|
|
@ -1888,46 +1891,21 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
|
||||||
if (l)
|
if (l)
|
||||||
{ // if not a null message
|
{ // if not a null message
|
||||||
// process AVPs
|
// process AVPs
|
||||||
while (l && !(fatal & 0x80))
|
while (l && !(fatal & 0x80)) // 0x80 = mandatory AVP
|
||||||
{
|
{
|
||||||
uint16_t n = (ntohs(*(uint16_t *) p) & 0x3FF);
|
uint16_t n = (ntohs(*(uint16_t *) p) & 0x3FF);
|
||||||
uint8_t *b = p;
|
uint8_t *b = p;
|
||||||
uint8_t flags = *p;
|
uint8_t flags = *p;
|
||||||
uint16_t mtype;
|
uint16_t mtype;
|
||||||
p += n; // next
|
if (n > l)
|
||||||
if (l < n)
|
|
||||||
{
|
{
|
||||||
LOG(1, s, t, "Invalid length in AVP\n");
|
LOG(1, s, t, "Invalid length in AVP\n");
|
||||||
STAT(tunnel_rx_errors);
|
STAT(tunnel_rx_errors);
|
||||||
fatal = flags;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
p += n; // next
|
||||||
l -= n;
|
l -= n;
|
||||||
if (flags & 0x40)
|
if (flags & 0x3C) // reserved bits, should be clear
|
||||||
{
|
|
||||||
// handle hidden AVPs
|
|
||||||
if (!*config->l2tpsecret)
|
|
||||||
{
|
|
||||||
LOG(1, s, t, "Hidden AVP requested, but no L2TP secret.\n");
|
|
||||||
fatal = flags;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!session[s].random_vector_length)
|
|
||||||
{
|
|
||||||
LOG(1, s, t, "Hidden AVP requested, but no random vector.\n");
|
|
||||||
fatal = flags;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
LOG(4, s, t, "Hidden AVP\n");
|
|
||||||
// Unhide the AVP
|
|
||||||
n = unhide_avp(b, t, s, n);
|
|
||||||
if (n == 0)
|
|
||||||
{
|
|
||||||
fatal = flags;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (*b & 0x3C)
|
|
||||||
{
|
{
|
||||||
LOG(1, s, t, "Unrecognised AVP flags %02X\n", *b);
|
LOG(1, s, t, "Unrecognised AVP flags %02X\n", *b);
|
||||||
fatal = flags;
|
fatal = flags;
|
||||||
|
|
@ -1945,13 +1923,53 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
|
||||||
b += 2;
|
b += 2;
|
||||||
n -= 6;
|
n -= 6;
|
||||||
|
|
||||||
|
if (flags & 0x40)
|
||||||
|
{
|
||||||
|
uint16_t orig_len;
|
||||||
|
|
||||||
|
// handle hidden AVPs
|
||||||
|
if (!*config->l2tpsecret)
|
||||||
|
{
|
||||||
|
LOG(1, s, t, "Hidden AVP requested, but no L2TP secret.\n");
|
||||||
|
fatal = flags;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!session[s].random_vector_length)
|
||||||
|
{
|
||||||
|
LOG(1, s, t, "Hidden AVP requested, but no random vector.\n");
|
||||||
|
fatal = flags;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (n < 8)
|
||||||
|
{
|
||||||
|
LOG(2, s, t, "Short hidden AVP.\n");
|
||||||
|
fatal = flags;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(4, s, t, "Hidden AVP\n");
|
||||||
|
|
||||||
|
// Unhide the AVP
|
||||||
|
unhide_value(b, n, mtype, session[s].random_vector, session[s].random_vector_length);
|
||||||
|
|
||||||
|
orig_len = ntohs(*(uint16_t *) b);
|
||||||
|
if (orig_len > n + 2)
|
||||||
|
{
|
||||||
|
fatal = flags;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
b += 2;
|
||||||
|
n = orig_len;
|
||||||
|
}
|
||||||
|
|
||||||
LOG(4, s, t, " AVP %d (%s) len %d\n", mtype, avp_name(mtype), n);
|
LOG(4, s, t, " AVP %d (%s) len %d\n", mtype, avp_name(mtype), n);
|
||||||
switch (mtype)
|
switch (mtype)
|
||||||
{
|
{
|
||||||
case 0: // message type
|
case 0: // message type
|
||||||
message = ntohs(*(uint16_t *) b);
|
message = ntohs(*(uint16_t *) b);
|
||||||
|
mandatory = flags & 0x80;
|
||||||
LOG(4, s, t, " Message type = %d (%s)\n", *b, l2tp_message_type(message));
|
LOG(4, s, t, " Message type = %d (%s)\n", *b, l2tp_message_type(message));
|
||||||
mandatorymessage = flags;
|
|
||||||
break;
|
break;
|
||||||
case 1: // result code
|
case 1: // result code
|
||||||
{
|
{
|
||||||
|
|
@ -2276,8 +2294,8 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
STAT(tunnel_rx_errors);
|
STAT(tunnel_rx_errors);
|
||||||
if (mandatorymessage & 0x80)
|
if (mandatory)
|
||||||
tunnelshutdown(t, "Unknown message");
|
tunnelshutdown(t, "Unknown message type");
|
||||||
else
|
else
|
||||||
LOG(1, s, t, "Unknown message type %d\n", message);
|
LOG(1, s, t, "Unknown message type %d\n", message);
|
||||||
break;
|
break;
|
||||||
|
|
@ -4727,75 +4745,45 @@ int cmd_show_hist_open(struct cli_def *cli, char *command, char **argv, int argc
|
||||||
|
|
||||||
/* Unhide an avp.
|
/* Unhide an avp.
|
||||||
*
|
*
|
||||||
* This unencodes the AVP using the L2TP CHAP secret and the
|
* This unencodes the AVP using the L2TP secret and the previously
|
||||||
* previously stored random vector. It replaces the hidden data with
|
* stored random vector. It overwrites the hidden data with the
|
||||||
* the cleartext data and returns the length of the cleartext data
|
* unhidden AVP subformat.
|
||||||
* (including the AVP "header" of 6 bytes).
|
|
||||||
*
|
|
||||||
* Based on code from rp-l2tpd by Roaring Penguin Software Inc.
|
|
||||||
*/
|
*/
|
||||||
static int unhide_avp(uint8_t *avp, tunnelidt t, sessionidt s, uint16_t length)
|
static void unhide_value(uint8_t *value, size_t len, uint16_t type, uint8_t *vector, size_t vec_len)
|
||||||
{
|
{
|
||||||
MD5_CTX ctx;
|
MD5_CTX ctx;
|
||||||
uint8_t *cursor;
|
|
||||||
uint8_t digest[16];
|
uint8_t digest[16];
|
||||||
uint8_t working_vector[16];
|
uint8_t *last;
|
||||||
uint16_t hidden_length;
|
size_t d = 0;
|
||||||
uint8_t type[2];
|
|
||||||
size_t done, todo;
|
|
||||||
uint8_t *output;
|
|
||||||
|
|
||||||
// Find the AVP type.
|
|
||||||
type[0] = *(avp + 4);
|
|
||||||
type[1] = *(avp + 5);
|
|
||||||
|
|
||||||
// Line up with the hidden data
|
|
||||||
cursor = output = avp + 6;
|
|
||||||
|
|
||||||
// Compute initial pad
|
// Compute initial pad
|
||||||
MD5Init(&ctx);
|
MD5Init(&ctx);
|
||||||
MD5Update(&ctx, type, 2);
|
MD5Update(&ctx, (uint8_t) (type >> 8) & 0xff, 1);
|
||||||
|
MD5Update(&ctx, (uint8_t) type & 0xff, 1);
|
||||||
MD5Update(&ctx, config->l2tpsecret, strlen(config->l2tpsecret));
|
MD5Update(&ctx, config->l2tpsecret, strlen(config->l2tpsecret));
|
||||||
MD5Update(&ctx, session[s].random_vector, session[s].random_vector_length);
|
MD5Update(&ctx, vector, vec_len);
|
||||||
MD5Final(digest, &ctx);
|
MD5Final(digest, &ctx);
|
||||||
|
|
||||||
// Get hidden length
|
// pointer to last decoded 16 octets
|
||||||
hidden_length = ((uint16_t) (digest[0] ^ cursor[0])) * 256 + (uint16_t) (digest[1] ^ cursor[1]);
|
last = value;
|
||||||
|
|
||||||
// Keep these for later use
|
while (len > 0)
|
||||||
working_vector[0] = *cursor;
|
|
||||||
working_vector[1] = *(cursor + 1);
|
|
||||||
cursor += 2;
|
|
||||||
|
|
||||||
if (hidden_length > length - 8)
|
|
||||||
{
|
{
|
||||||
LOG(1, s, t, "Hidden length %d too long in AVP of length %d\n", (int) hidden_length, (int) length);
|
// calculate a new pad based on the last decoded block
|
||||||
return 0;
|
if (d >= sizeof(digest))
|
||||||
}
|
|
||||||
|
|
||||||
/* Decrypt remainder */
|
|
||||||
done = 2;
|
|
||||||
todo = hidden_length;
|
|
||||||
while (todo)
|
|
||||||
{
|
|
||||||
working_vector[done] = *cursor;
|
|
||||||
*output = digest[done] ^ *cursor;
|
|
||||||
++output;
|
|
||||||
++cursor;
|
|
||||||
--todo;
|
|
||||||
++done;
|
|
||||||
if (done == 16 && todo)
|
|
||||||
{
|
{
|
||||||
// Compute new digest
|
|
||||||
done = 0;
|
|
||||||
MD5Init(&ctx);
|
MD5Init(&ctx);
|
||||||
MD5Update(&ctx, config->l2tpsecret, strlen(config->l2tpsecret));
|
MD5Update(&ctx, config->l2tpsecret, strlen(config->l2tpsecret));
|
||||||
MD5Update(&ctx, &working_vector, 16);
|
MD5Update(&ctx, last, sizeof(digest));
|
||||||
MD5Final(digest, &ctx);
|
MD5Final(digest, &ctx);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return hidden_length + 6;
|
d = 0;
|
||||||
|
last = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
*value++ ^= digest[d++];
|
||||||
|
len--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ip_filter_port(ip_filter_portt *p, uint16_t port)
|
static int ip_filter_port(ip_filter_portt *p, uint16_t port)
|
||||||
|
|
|
||||||
|
|
@ -43,5 +43,5 @@ rm -rf %{buildroot}
|
||||||
%attr(644,root,root) /usr/share/man/man[58]/*
|
%attr(644,root,root) /usr/share/man/man[58]/*
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
* Mon Feb 14 2005 Brendan O'Dea <bod@optusnet.com.au> 2.1.0-1
|
* Thu Mar 10 2005 Brendan O'Dea <bod@optusnet.com.au> 2.1.0-1
|
||||||
- 2.1.0 release, see /usr/share/doc/l2tpns-2.1.0/Changes
|
- 2.1.0 release, see /usr/share/doc/l2tpns-2.1.0/Changes
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue