Add support for Hidden AVPs and chap-response

This commit is contained in:
David Parrish 2004-09-19 23:19:23 +00:00
parent 9801c8cd41
commit ab0c6fbd45
3 changed files with 96 additions and 4 deletions

View file

@ -1,3 +1,8 @@
* ? David Parrish <david@dparrish.com> ?
- Added support for hidden AVPs by Robert Clark
- l2tpns-chap-response.patch from Robert Clark
- l2tpns-config-hostname.patch from Robert Clark
* Thu Sep 02 2004 David Parrish <david@dparrish.com> 2.0.2 * Thu Sep 02 2004 David Parrish <david@dparrish.com> 2.0.2
- Combined LCP patches from Iain and Yuri. This should allow Windows 2k/XP - Combined LCP patches from Iain and Yuri. This should allow Windows 2k/XP
clients to connect, as well Linksys DSL modems. clients to connect, as well Linksys DSL modems.

View file

@ -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.25 2004-09-02 04:18:07 fred_nerk Exp $"; char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.26 2004-09-19 23:19:23 fred_nerk Exp $";
#include <arpa/inet.h> #include <arpa/inet.h>
#include <assert.h> #include <assert.h>
@ -169,6 +169,7 @@ void dump_state();
void tunnel_clean(); void tunnel_clean();
tunnelidt new_tunnel(); tunnelidt new_tunnel();
void update_config(); void update_config();
int unhide_avp(u8 *avp, tunnelidt t, sessionidt s, u16 length);
static void cache_ipmap(ipt ip, int s); static void cache_ipmap(ipt ip, int s);
static void uncache_ipmap(ipt ip); static void uncache_ipmap(ipt ip);
@ -1452,6 +1453,13 @@ void processudp(u8 * buf, int len, struct sockaddr_in *addr)
continue; continue;
} }
log(4, ntohl(addr->sin_addr.s_addr), s, t, "Hidden AVP\n"); log(4, ntohl(addr->sin_addr.s_addr), s, t, "Hidden AVP\n");
// Unhide the AVP
n = unhide_avp(b, t, s, n);
if (n == 0)
{
fatal = flags;
continue;
}
} }
if (*b & 0x3C) if (*b & 0x3C)
{ {
@ -1566,6 +1574,11 @@ void processudp(u8 * buf, int len, struct sockaddr_in *addr)
build_chap_response(b, 2, n, &chapresponse); build_chap_response(b, 2, n, &chapresponse);
} }
break; break;
case 13: // Response
// Why did they send a response? We never challenge.
log(2, ntohl(addr->sin_addr.s_addr), s, t, " received unexpected challenge response\n");
break;
case 14: // assigned session case 14: // assigned session
asession = session[s].far = ntohs(*(u16 *) (b)); asession = session[s].far = ntohs(*(u16 *) (b));
log(4, ntohl(addr->sin_addr.s_addr), s, t, " assigned session = %d\n", asession); log(4, ntohl(addr->sin_addr.s_addr), s, t, " assigned session = %d\n", asession);
@ -4013,3 +4026,77 @@ int cmd_show_hist_open(struct cli_def *cli, char *command, char **argv, int argc
cli_print(cli, "%d total sessions open.", count); cli_print(cli, "%d total sessions open.", count);
return CLI_OK; return CLI_OK;
} }
/* Unhide an avp.
*
* This unencodes the AVP using the L2TP CHAP secret and the
* previously stored random vector. It replaces the hidden data with
* the cleartext data and returns the length of the cleartext data
* (including the AVP "header" of 6 bytes).
*
* Based on code from rp-l2tpd by Roaring Penguin Software Inc.
*/
int unhide_avp(u8 *avp, tunnelidt t, sessionidt s, u16 length)
{
MD5_CTX ctx;
u8 *cursor;
u8 digest[16];
u8 working_vector[16];
uint16_t hidden_length;
u8 type[2];
size_t done, todo;
u8 *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
MD5Init(&ctx);
MD5Update(&ctx, type, 2);
MD5Update(&ctx, config->l2tpsecret, strlen(config->l2tpsecret));
MD5Update(&ctx, session[s].random_vector, session[s].random_vector_length);
MD5Final(digest, &ctx);
// Get hidden length
hidden_length = ((uint16_t) (digest[0] ^ cursor[0])) * 256 + (uint16_t) (digest[1] ^ cursor[1]);
// Keep these for later use
working_vector[0] = *cursor;
working_vector[1] = *(cursor + 1);
cursor += 2;
if (hidden_length > length - 8)
{
log(1, 0, s, t, "Hidden length %d too long in AVP of length %d\n", (int) hidden_length, (int) length);
return 0;
}
/* 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);
MD5Update(&ctx, config->l2tpsecret, strlen(config->l2tpsecret));
MD5Update(&ctx, &working_vector, 16);
MD5Final(digest, &ctx);
}
}
return hidden_length + 6;
}

6
ppp.c
View file

@ -1,6 +1,6 @@
// L2TPNS PPP Stuff // L2TPNS PPP Stuff
char const *cvs_id_ppp = "$Id: ppp.c,v 1.14 2004-09-02 04:18:07 fred_nerk Exp $"; char const *cvs_id_ppp = "$Id: ppp.c,v 1.15 2004-09-19 23:19:23 fred_nerk Exp $";
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -512,7 +512,8 @@ void processipcp(tunnelidt t, sessionidt s, u8 * p, u16 l)
{ {
// happy with our IPCP // happy with our IPCP
u16 r = session[s].radius; u16 r = session[s].radius;
if ((!r || radius[r].state == RADIUSIPCP) && !session[s].walled_garden) { if ((!r || radius[r].state == RADIUSIPCP) && !session[s].walled_garden)
{
if (!r) if (!r)
r = radiusnew(s); r = radiusnew(s);
if (r) if (r)
@ -636,7 +637,6 @@ void processipin(tunnelidt t, sessionidt s, u8 * p, u16 l)
{ {
ipt ip; ipt ip;
CSTAT(call_processipin); CSTAT(call_processipin);
log_hex(5, "IP", p, l); log_hex(5, "IP", p, l);