Add lcp_renegotiation option
To support proxy LCP negotiation. Note: we *have* to take the auth id from the proxy answer, otherwise we would replay previous ids, for which the client might cache the answer and thus ignore our new challenge and just repeat their outdated answer.
This commit is contained in:
parent
817ce35748
commit
e7db528544
6 changed files with 388 additions and 31 deletions
126
l2tpns.c
126
l2tpns.c
|
|
@ -159,6 +159,7 @@ config_descriptt config_values[] = {
|
|||
CONFIG("ppp_max_configure", ppp_max_configure, INT),
|
||||
CONFIG("ppp_max_failure", ppp_max_failure, INT),
|
||||
CONFIG("ppp_keepalive", ppp_keepalive, BOOL),
|
||||
CONFIG("lcp_renegotiation", lcp_renegotiation, STRING),
|
||||
CONFIG("primary_dns", default_dns1, IPv4),
|
||||
CONFIG("secondary_dns", default_dns2, IPv4),
|
||||
CONFIG("primary_radius", radiusserver[0], IPv4),
|
||||
|
|
@ -4163,9 +4164,18 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu
|
|||
uint16_t message = 0xFFFF; // message type
|
||||
uint8_t fatal = 0;
|
||||
uint8_t mandatory = 0;
|
||||
uint8_t *last_sent_lcp_confreq = 0;
|
||||
uint16_t last_sent_lcp_confreq_n = 0;
|
||||
uint8_t *last_received_lcp_confreq = 0;
|
||||
uint16_t last_received_lcp_confreq_n = 0;
|
||||
uint16_t atype = 0;
|
||||
uint16_t authid = 0;
|
||||
char authname[MAXUSER] = "";
|
||||
char authchall[MAXPASS] = "";
|
||||
size_t authchalln = 0;
|
||||
char authresp[MAXPASS] = "";
|
||||
size_t authrespn = 0;
|
||||
uint16_t asession = 0; // assigned session
|
||||
uint32_t amagic = 0; // magic number
|
||||
uint8_t aflags = 0; // flags from last LCF
|
||||
uint16_t version = 0x0100; // protocol version (we handle 0.0 as well and send that back just in case)
|
||||
char called[MAXTEL] = ""; // called number
|
||||
char calling[MAXTEL] = ""; // calling number
|
||||
|
|
@ -4642,50 +4652,70 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu
|
|||
}
|
||||
case 29: // Proxy Authentication Type
|
||||
{
|
||||
uint16_t atype = ntohs(*(uint16_t *)b);
|
||||
atype = ntohs(*(uint16_t *)b);
|
||||
LOG(4, s, t, " Proxy Auth Type %u (%s)\n", atype, ppp_auth_type(atype));
|
||||
break;
|
||||
}
|
||||
case 30: // Proxy Authentication Name
|
||||
{
|
||||
char authname[64];
|
||||
memset(authname, 0, sizeof(authname));
|
||||
memcpy(authname, b, (n < sizeof(authname)) ? n : sizeof(authname) - 1);
|
||||
LOG(4, s, t, " Proxy Auth Name (%s)\n",
|
||||
authname);
|
||||
if (n < sizeof(authname))
|
||||
{
|
||||
LOG(4, s, t, " Proxy Auth Name (%s)\n", authname);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(2, s, t, " Proxy Auth Name too long (%s)\n", authname);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 31: // Proxy Authentication Challenge
|
||||
{
|
||||
LOG(4, s, t, " Proxy Auth Challenge\n");
|
||||
if (n <= sizeof(authchall))
|
||||
{
|
||||
memcpy(authchall, b, n);
|
||||
authchalln = n;
|
||||
LOG(4, s, t, " Proxy Auth Challenge\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(2, s, t, " Proxy Auth Challenge too long\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 32: // Proxy Authentication ID
|
||||
{
|
||||
uint16_t authid = ntohs(*(uint16_t *)(b));
|
||||
authid = ntohs(*(uint16_t *)(b));
|
||||
LOG(4, s, t, " Proxy Auth ID (%u)\n", authid);
|
||||
break;
|
||||
}
|
||||
case 33: // Proxy Authentication Response
|
||||
LOG(4, s, t, " Proxy Auth Response\n");
|
||||
break;
|
||||
case 27: // last sent lcp
|
||||
{ // find magic number
|
||||
uint8_t *p = b, *e = p + n;
|
||||
while (p + 1 < e && p[1] && p + p[1] <= e)
|
||||
{
|
||||
if (n <= sizeof(authresp))
|
||||
{
|
||||
if (*p == 5 && p[1] == 6) // Magic-Number
|
||||
amagic = ntohl(*(uint32_t *) (p + 2));
|
||||
else if (*p == 7) // Protocol-Field-Compression
|
||||
aflags |= SESSION_PFC;
|
||||
else if (*p == 8) // Address-and-Control-Field-Compression
|
||||
aflags |= SESSION_ACFC;
|
||||
p += p[1];
|
||||
memcpy(authresp, b, n);
|
||||
authrespn = n;
|
||||
LOG(4, s, t, " Proxy Auth Response\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(2, s, t, " Proxy Auth Response too long\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 27: // last sent lcp
|
||||
{
|
||||
last_sent_lcp_confreq = b;
|
||||
last_sent_lcp_confreq_n = n;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 28: // last recv lcp confreq
|
||||
break;
|
||||
{
|
||||
last_received_lcp_confreq = b;
|
||||
last_received_lcp_confreq_n = n;
|
||||
break;
|
||||
}
|
||||
case 26: // Initial Received LCP CONFREQ
|
||||
break;
|
||||
case 39: // seq required - we control it as an LNS anyway...
|
||||
|
|
@ -4996,9 +5026,8 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu
|
|||
break;
|
||||
case 12: // ICCN
|
||||
LOG(3, s, t, "Received ICCN\n");
|
||||
if (amagic == 0) amagic = time_now;
|
||||
session[s].magic = amagic; // set magic number
|
||||
session[s].flags = aflags; // set flags received
|
||||
|
||||
session[s].magic = time_now; // set magic number
|
||||
session[s].mru = PPPoE_MRU; // default
|
||||
controlnull(t); // ack
|
||||
|
||||
|
|
@ -5013,8 +5042,39 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu
|
|||
else
|
||||
sess_local[s].mp_epdis = 0;
|
||||
|
||||
sendlcp(s, t);
|
||||
change_state(s, lcp, RequestSent);
|
||||
if (last_sent_lcp_confreq_n && last_received_lcp_confreq_n &&
|
||||
processlcpproxy(s, t, last_sent_lcp_confreq, last_sent_lcp_confreq_n,
|
||||
last_received_lcp_confreq, last_received_lcp_confreq_n)
|
||||
&& ( (sess_local[s].lcp_authtype == 0)
|
||||
|| (sess_local[s].lcp_authtype == AUTHPAP && authrespn)
|
||||
|| (sess_local[s].lcp_authtype == AUTHCHAP && authchalln == 16 && authrespn == 16)))
|
||||
{
|
||||
// Could reuse the LCP negotiation and don't have empty proxy auth response or unknown challenge size, don't renegotiate
|
||||
LOG(3, s, t, "Reusing LCP negotiation\n");
|
||||
// Start with proxy auth id to avoid client caching challenge responses
|
||||
sess_local[s].auth_id = authid;
|
||||
|
||||
if (!sess_local[s].lcp_authtype)
|
||||
{
|
||||
// No auth, open immediately
|
||||
lcp_open(s, t);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Process auth
|
||||
session[s].ppp.phase = Authenticate;
|
||||
change_state(s, lcp, Opened);
|
||||
processauthproxy(s, t, atype, authname, authchalln, authchall, authrespn, authresp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Have to renegotiate LCP
|
||||
LOG(3, s, t, "Renegotiating LCP\n");
|
||||
sendlcp(s, t);
|
||||
change_state(s, lcp, RequestSent);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 14: // CDN
|
||||
|
|
@ -7425,6 +7485,16 @@ static void update_config()
|
|||
MSS = MRU - TCP_HDRS;
|
||||
MSS6 = MRU - TCP6_HDRS;
|
||||
|
||||
if (!config->lcp_renegotiation[0])
|
||||
strcpy(config->lcp_renegotiation, "always");
|
||||
|
||||
if (strcmp(config->lcp_renegotiation, "always") &&
|
||||
strcmp(config->lcp_renegotiation, "on-mismatch"))
|
||||
{
|
||||
LOG(0, 0, 0, "Invalid LCP renegotiation type %s, assuming 'always'\n", config->lcp_renegotiation);
|
||||
strcpy(config->lcp_renegotiation, "always");
|
||||
}
|
||||
|
||||
// Update radius
|
||||
config->numradiusservers = 0;
|
||||
for (i = 0; i < MAXRADSERVER; i++)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue