From: bodea Date: Mon, 14 Feb 2005 06:58:38 +0000 (+0000) Subject: merge back 2.0 branch changes X-Git-Tag: release_2_1_0~71 X-Git-Url: http://git.sameswireless.fr/l2tpns.git/commitdiff_plain/7825a266917816e443bcc28d63c6c365997bd4ed?ds=inline merge back 2.0 branch changes --- diff --git a/Changes b/Changes index ce39428..308c552 100644 --- a/Changes +++ b/Changes @@ -1,4 +1,4 @@ -* Wed Feb 9 2005 Brendan O'Dea 2.1.0 +* Mon Feb 14 2005 Brendan O'Dea 2.1.0 - Add IPv6 support from Jonathan McDowell. - Add CHAP support from Jordan Hrycaj (work in progress). - Sanity check that cluster_send_session is not called from a child @@ -17,8 +17,21 @@ - Show time since last counter reset in "show counters". - Remove "save_state" option. Not maintained anymore; use clustering to retain state across restarts. -- Fix off-by-one in session/tunnel table initialisation. +- Ensure that sessionkill is not called on an unopened session (borks + the freelist). - Bump MAXSESSION to 60K. +- Fix off-by-one errors in session/tunnel initialisation and + sessiont <-> sessionidt functions. +- Use session[s].opened consistently when checking for in-use sessions + (rather than session[s].tunnel). +- Use <= cluster_highest_sessionid rather than < MAXSESSION in a + couple of loops. +- Don't kill a whole tunnel if we're out of sessions. +- Change session[s].ip to 0 if set from RADIUS to 255.255.255.254; + avoids the possibility that it will be interpreted as a valid IP + address. +- Avoid a possible buffer overflow in processpap. +- Kill session if authentication was rejected. * Fri Dec 17 2004 Brendan O'Dea 2.0.13 - Better cluster master collision resolution: keep a counter of state diff --git a/cluster.c b/cluster.c index c3e2002..1dc5c53 100644 --- a/cluster.c +++ b/cluster.c @@ -1,6 +1,6 @@ // L2TPNS Clustering Stuff -char const *cvs_id_cluster = "$Id: cluster.c,v 1.30 2005/02/09 02:38:51 bodea Exp $"; +char const *cvs_id_cluster = "$Id: cluster.c,v 1.31 2005/02/14 06:58:38 bodea Exp $"; #include #include @@ -571,10 +571,13 @@ void cluster_check_master(void) ++count; } - if (session[i].tunnel == T_FREE) { // Unused session. Add to free list. + if (!session[i].opened) { // Unused session. Add to free list. + memset(&session[i], 0, sizeof(session[i])); + session[i].tunnel = T_FREE; session[last_free].next = i; session[i].next = 0; last_free = i; + continue; } // Reset all the idle timeouts.. @@ -593,16 +596,14 @@ void cluster_check_master(void) if (session[i].unique_id >= high_unique_id) // This is different to the index into the session table!!! high_unique_id = session[i].unique_id+1; - session[i].tbf_in = session[i].tbf_out = 0; // Remove stale pointers from old master. throttle_session(i, session[i].throttle_in, session[i].throttle_out); - if (session[i].tunnel != T_FREE && i > config->cluster_highest_sessionid) - config->cluster_highest_sessionid = i; + config->cluster_highest_sessionid = i; } session[last_free].next = 0; // End of chain. - last_id = high_unique_id; // Keep track of the highest used session ID. + last_id = high_unique_id; // Keep track of the highest used session ID. become_master(); @@ -650,12 +651,14 @@ static void cluster_check_sessions(int highsession, int freesession_ptr, int hig config->cluster_undefined_sessions = 0; for (i = 1 ; i < MAXSESSION; ++i) { if (i > highsession) { - session[i].tunnel = T_FREE; // Defined. + if (session[i].tunnel == T_UNDEF) session[i].tunnel = T_FREE; // Defined. continue; } if (session[i].tunnel != T_UNDEF) continue; - ++config->cluster_undefined_sessions; + + if (session[i].tunnel == T_UNDEF) + ++config->cluster_undefined_sessions; } // Clear out defined tunnels, counting the number of @@ -663,12 +666,12 @@ static void cluster_check_sessions(int highsession, int freesession_ptr, int hig config->cluster_undefined_tunnels = 0; for (i = 1 ; i < MAXTUNNEL; ++i) { if (i > hightunnel) { - tunnel[i].state = TUNNELFREE; // Defined. + if (tunnel[i].state == TUNNELUNDEF) tunnel[i].state = TUNNELFREE; // Defined. continue; } - if (tunnel[i].state != TUNNELUNDEF) - continue; - ++config->cluster_undefined_tunnels; + + if (tunnel[i].state == TUNNELUNDEF) + ++config->cluster_undefined_tunnels; } diff --git a/l2tpns.c b/l2tpns.c index 813f2c7..e6cdff7 100644 --- a/l2tpns.c +++ b/l2tpns.c @@ -4,7 +4,7 @@ // Copyright (c) 2002 FireBrick (Andrews & Arnold Ltd / Watchfront Ltd) - GPL licenced // vim: sw=8 ts=8 -char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.83 2005/02/09 00:45:34 bodea Exp $"; +char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.84 2005/02/14 06:58:39 bodea Exp $"; #include #include @@ -660,7 +660,7 @@ sessionidt sessionbyip(in_addr_t ip) int s = lookup_ipmap(ip); CSTAT(sessionbyip); - if (s > 0 && s < MAXSESSION && session[s].tunnel) + if (s > 0 && s < MAXSESSION && session[s].opened) return (sessionidt) s; return 0; @@ -679,7 +679,7 @@ sessionidt sessionbyipv6(struct in6_addr ip) s = lookup_ipv6map(ip); } - if (s > 0 && s < MAXSESSION && session[s].tunnel) + if (s > 0 && s < MAXSESSION && session[s].opened) return s; return 0; @@ -815,8 +815,11 @@ sessionidt sessionbyuser(char *username) int s; CSTAT(sessionbyuser); - for (s = 1; s < MAXSESSION ; ++s) + for (s = 1; s <= config->cluster_highest_sessionid ; ++s) { + if (!session[s].opened) + continue; + if (session[s].walled_garden) continue; // Skip walled garden users. @@ -858,17 +861,16 @@ void send_garp(in_addr_t ip) sendarp(ifr.ifr_ifindex, mac, ip); } -// Find session by username, 0 for not found static sessiont *sessiontbysessionidt(sessionidt s) { - if (!s || s > MAXSESSION) return NULL; + if (!s || s >= MAXSESSION) return NULL; return &session[s]; } static sessionidt sessionidtbysessiont(sessiont *s) { sessionidt val = s-session; - if (s < session || val > MAXSESSION) return 0; + if (s < session || val >= MAXSESSION) return 0; return val; } @@ -1357,7 +1359,7 @@ static void controladd(controlt * c, tunnelidt t, sessionidt s) // void throttle_session(sessionidt s, int rate_in, int rate_out) { - if (!session[s].tunnel) + if (!session[s].opened) return; // No-one home. if (!*session[s].user) @@ -1395,7 +1397,7 @@ void throttle_session(sessionidt s, int rate_in, int rate_out) // add/remove filters from session (-1 = no change) static void filter_session(sessionidt s, int filter_in, int filter_out) { - if (!session[s].tunnel) + if (!session[s].opened) return; // No-one home. if (!*session[s].user) @@ -1438,9 +1440,9 @@ void sessionshutdown(sessionidt s, char *reason) CSTAT(sessionshutdown); - if (!session[s].tunnel) + if (!session[s].opened) { - LOG(3, s, session[s].tunnel, "Called sessionshutdown on a session with no tunnel.\n"); + LOG(3, s, session[s].tunnel, "Called sessionshutdown on an unopened session.\n"); return; // not a live session } @@ -1451,7 +1453,7 @@ void sessionshutdown(sessionidt s, char *reason) run_plugins(PLUGIN_KILL_SESSION, &data); } - if (session[s].opened && !walled_garden && !session[s].die) + if (!walled_garden && !session[s].die) { // RADIUS Stop message uint16_t r = session[s].radius; @@ -1514,7 +1516,7 @@ void sessionshutdown(sessionidt s, char *reason) } if (!session[s].die) - session[s].die = now() + 150; // Clean up in 15 seconds + session[s].die = TIME + 150; // Clean up in 15 seconds // update filter refcounts if (session[s].filter_in) ip_filters[session[s].filter_in - 1].used--; @@ -1589,12 +1591,21 @@ void sendipcp(tunnelidt t, sessionidt s) } // kill a session now -static void sessionkill(sessionidt s, char *reason) +void sessionkill(sessionidt s, char *reason) { CSTAT(sessionkill); - session[s].die = now(); + if (!session[s].opened) // not alive + return; + + if (session[s].next) + { + LOG(0, s, session[s].tunnel, "Tried to kill a session with next pointer set (%d)\n", session[s].next); + return; + } + + session[s].die = TIME; sessionshutdown(s, reason); // close radius/routes, etc. if (session[s].radius) radiusclear(session[s].radius, s); // cant send clean accounting data, session is killed @@ -1636,7 +1647,7 @@ static void tunnelkill(tunnelidt t, char *reason) controlfree = c; } // kill sessions - for (s = 1; s < MAXSESSION; s++) + for (s = 1; s <= config->cluster_highest_sessionid ; ++s) if (session[s].tunnel == t) sessionkill(s, reason); @@ -1663,12 +1674,12 @@ static void tunnelshutdown(tunnelidt t, char *reason) LOG(1, 0, t, "Shutting down tunnel %d (%s)\n", t, reason); // close session - for (s = 1; s < MAXSESSION; s++) + for (s = 1; s <= config->cluster_highest_sessionid ; ++s) if (session[s].tunnel == t) sessionshutdown(s, reason); tunnel[t].state = TUNNELDIE; - tunnel[t].die = now() + 700; // Clean up in 70 seconds + tunnel[t].die = TIME + 700; // Clean up in 70 seconds cluster_send_tunnel(t); // TBA - should we wait for sessions to stop? { // Send StopCCN @@ -2202,7 +2213,8 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr) if (!sessionfree) { STAT(session_overflow); - tunnelshutdown(t, "No free sessions"); + LOG(1, 0, t, "No free sessions"); + return; } else { @@ -2226,7 +2238,7 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr) c = controlnew(11); // sending ICRP session[s].id = sessionid++; - session[s].opened = time(NULL); + session[s].opened = time_now; session[s].tunnel = t; session[s].far = asession; session[s].last_packet = time_now; @@ -2306,7 +2318,7 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr) l -= 2; } - if (s && !session[s].tunnel) // Is something wrong?? + if (s && !session[s].opened) // Is something wrong?? { if (!config->cluster_iam_master) { @@ -2316,9 +2328,7 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr) } - LOG(1, s, t, "UDP packet contains session %d but no session[%d].tunnel " - "exists (LAC said tunnel = %d). Dropping packet.\n", s, s, t); - + LOG(1, s, t, "UDP packet contains session which is not opened. Dropping packet.\n"); STAT(tunnel_rx_errors); return; } @@ -2525,7 +2535,7 @@ static int regular_cleanups(void) if (s > config->cluster_highest_sessionid) s = 1; - if (!session[s].tunnel) // Session isn't in use + if (!session[s].opened) // Session isn't in use continue; if (!session[s].die && session[s].ip && !(session[s].flags & SF_IPCP_ACKED)) @@ -3269,8 +3279,9 @@ void rebuild_address_pool(void) for (i = 0; i < MAXSESSION; ++i) { int ipid; - if (!session[i].ip || !session[i].tunnel) + if (!(session[i].opened && session[i].ip)) continue; + ipid = - lookup_ipmap(htonl(session[i].ip)); if (session[i].ip_pool_index < 0) @@ -4016,7 +4027,7 @@ int sessionsetup(tunnelidt t, sessionidt s) LOG(3, s, t, "Doing session setup for session\n"); - if (!session[s].ip || session[s].ip == 0xFFFFFFFE) + if (!session[s].ip) { assign_ip_address(s); if (!session[s].ip) @@ -4619,7 +4630,7 @@ void become_master(void) { for (s = 1; s <= config->cluster_highest_sessionid ; ++s) { - if (!session[s].tunnel) // Not an in-use session. + if (!session[s].opened) // Not an in-use session. continue; run_plugins(PLUGIN_NEW_SESSION_MASTER, &session[s]); @@ -4651,7 +4662,7 @@ int cmd_show_hist_idle(struct cli_def *cli, char *command, char **argv, int argc for (s = 1; s <= config->cluster_highest_sessionid ; ++s) { int idle; - if (!session[s].tunnel) + if (!session[s].opened) continue; idle = time_now - session[s].last_packet; @@ -4689,7 +4700,7 @@ int cmd_show_hist_open(struct cli_def *cli, char *command, char **argv, int argc for (s = 1; s <= config->cluster_highest_sessionid ; ++s) { int open = 0, d; - if (!session[s].tunnel) + if (!session[s].opened) continue; d = time_now - session[s].opened; diff --git a/l2tpns.h b/l2tpns.h index 38ac331..042271c 100644 --- a/l2tpns.h +++ b/l2tpns.h @@ -1,5 +1,5 @@ // L2TPNS Global Stuff -// $Id: l2tpns.h,v 1.56 2005/02/09 02:39:05 bodea Exp $ +// $Id: l2tpns.h,v 1.57 2005/02/14 06:58:39 bodea Exp $ #ifndef __L2TPNS_H__ #define __L2TPNS_H__ @@ -617,6 +617,7 @@ sessionidt sessionbyip(in_addr_t ip); sessionidt sessionbyipv6(struct in6_addr ip); sessionidt sessionbyuser(char *username); void random_data(uint8_t *buf, int len); +void sessionkill(sessionidt s, char *reason); void sessionshutdown(sessionidt s, char *reason); void send_garp(in_addr_t ip); void tunnelsend(uint8_t *buf, uint16_t l, tunnelidt t); diff --git a/l2tpns.spec b/l2tpns.spec index c32b5e1..37f7995 100644 --- a/l2tpns.spec +++ b/l2tpns.spec @@ -43,5 +43,5 @@ rm -rf %{buildroot} %attr(644,root,root) /usr/share/man/man[58]/* %changelog -* Wed Feb 9 2005 Brendan O'Dea 2.1.0-1 +* Mon Feb 14 2005 Brendan O'Dea 2.1.0-1 - 2.1.0 release, see /usr/share/doc/l2tpns-2.1.0/Changes diff --git a/ppp.c b/ppp.c index 6b1bb6e..bf1d8b5 100644 --- a/ppp.c +++ b/ppp.c @@ -1,6 +1,6 @@ // L2TPNS PPP Stuff -char const *cvs_id_ppp = "$Id: ppp.c,v 1.43 2005/01/25 04:38:49 bodea Exp $"; +char const *cvs_id_ppp = "$Id: ppp.c,v 1.44 2005/02/14 06:58:39 bodea Exp $"; #include #include @@ -60,13 +60,18 @@ void processpap(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l) { uint8_t *b = p; b += 4; + user[0] = pass[0] = 0; if (*b && *b < sizeof(user)) + { memcpy(user, b + 1, *b); - user[*b] = 0; - b += 1 + *b; - if (*b && *b < sizeof(pass)) - memcpy(pass, b + 1, *b); - pass[*b] = 0; + user[*b] = 0; + b += 1 + *b; + if (*b && *b < sizeof(pass)) + { + memcpy(pass, b + 1, *b); + pass[*b] = 0; + } + } LOG(3, s, t, "PAP login %s/%s\n", user, pass); } if (session[s].ip || !session[s].radius) diff --git a/radius.c b/radius.c index 567cd72..5ac64b4 100644 --- a/radius.c +++ b/radius.c @@ -1,6 +1,6 @@ // L2TPNS Radius Stuff -char const *cvs_id_radius = "$Id: radius.c,v 1.23 2005/01/25 04:19:06 bodea Exp $"; +char const *cvs_id_radius = "$Id: radius.c,v 1.24 2005/02/14 06:58:39 bodea Exp $"; #include #include @@ -470,6 +470,9 @@ void processrad(uint8_t *buf, int len, char socket_index) session[s].ip_pool_index = -1; LOG(3, s, session[s].tunnel, " Radius reply contains IP address %s\n", fmtaddr(htonl(session[s].ip), 0)); + + if (session[s].ip == 0xFFFFFFFE) + session[s].ip = 0; // assign from pool } else if (*p == 135) { @@ -649,8 +652,8 @@ void processrad(uint8_t *buf, int len, char socket_index) } else if (r_code == AccessReject) { - LOG(2, s, session[s].tunnel, " Authentication denied for %s\n", session[s].user); - sessionshutdown(s, "Authentication denied"); + LOG(2, s, session[s].tunnel, " Authentication rejected for %s\n", session[s].user); + sessionkill(s, "Authentication rejected"); break; }