summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKozlov Dmitry <xeb@mail.ru>2012-05-16 23:30:41 +0400
committerKozlov Dmitry <xeb@mail.ru>2012-05-16 23:30:41 +0400
commitcf358fcdc57dd52d30ca490b1164d832cf11fe8b (patch)
tree38d7c49723d9018d6e5c3546deeeb2ba926b3595
parent4fb9e3f03506695023d6aac0106b7f541b820c80 (diff)
downloadaccel-ppp-cf358fcdc57dd52d30ca490b1164d832cf11fe8b.tar.gz
accel-ppp-cf358fcdc57dd52d30ca490b1164d832cf11fe8b.zip
l2tp: implemented Challenge attribute handling (shared secret)
-rw-r--r--accel-pppd/accel-ppp.conf1
-rw-r--r--accel-pppd/accel-ppp.conf.54
-rw-r--r--accel-pppd/ctrl/l2tp/l2tp.c52
3 files changed, 50 insertions, 7 deletions
diff --git a/accel-pppd/accel-ppp.conf b/accel-pppd/accel-ppp.conf
index d055c59..527c2fb 100644
--- a/accel-pppd/accel-ppp.conf
+++ b/accel-pppd/accel-ppp.conf
@@ -80,6 +80,7 @@ verbose=1
#retransmit=5
#host-name=accel-ppp
#dir300_quirk=0
+#secret=
verbose=1
[dns]
diff --git a/accel-pppd/accel-ppp.conf.5 b/accel-pppd/accel-ppp.conf.5
index 3a1efa7..21e5923 100644
--- a/accel-pppd/accel-ppp.conf.5
+++ b/accel-pppd/accel-ppp.conf.5
@@ -300,6 +300,10 @@ is greater of zero then l2tp module will produce verbose logging.
.TP
.BI "mppe=" deny|allow|prefer|require
.TP
+.TP
+.BI "secret=" string
+Specifies secret to connect to server.
+.TP
.SH [radius]
.br
Configuration of RADIUS module.
diff --git a/accel-pppd/ctrl/l2tp/l2tp.c b/accel-pppd/ctrl/l2tp/l2tp.c
index 1ec2daa..50523cf 100644
--- a/accel-pppd/ctrl/l2tp/l2tp.c
+++ b/accel-pppd/ctrl/l2tp/l2tp.c
@@ -23,6 +23,7 @@
#include "utils.h"
#include "iprange.h"
#include "cli.h"
+#include "crypto.h"
#include "connlimit.h"
@@ -52,6 +53,7 @@ static int conf_retransmit = 5;
static int conf_hello_interval = 60;
static int conf_dir300_quirk = 0;
static const char *conf_host_name = "accel-ppp";
+static const char *conf_secret = NULL;
static int conf_mppe = MPPE_UNSET;
static unsigned int stat_active;
@@ -80,6 +82,8 @@ struct l2tp_conn_t
uint16_t peer_tid;
uint16_t peer_sid;
uint32_t framing_cap;
+ uint16_t challenge_len;
+ l2tp_value_t challenge;
int retransmit;
uint16_t Ns, Nr;
@@ -153,7 +157,8 @@ static void l2tp_disconnect(struct l2tp_conn_t *conn)
if (conn->ppp.chan_name)
_free(conn->ppp.chan_name);
-
+ if (conn->challenge_len)
+ _free(conn->challenge.octets);
_free(conn->ctrl.calling_station_id);
_free(conn->ctrl.called_station_id);
@@ -224,7 +229,8 @@ static void l2tp_conn_close(struct triton_context_t *ctx)
l2tp_disconnect(conn);
}
-static int l2tp_tunnel_alloc(struct l2tp_serv_t *serv, struct l2tp_packet_t *pack, struct in_pktinfo *pkt_info, struct l2tp_attr_t *assigned_tid, struct l2tp_attr_t *framing_cap)
+static int l2tp_tunnel_alloc(struct l2tp_serv_t *serv, struct l2tp_packet_t *pack, struct in_pktinfo *pkt_info, struct l2tp_attr_t *assigned_tid,
+ struct l2tp_attr_t *framing_cap, struct l2tp_attr_t *challenge)
{
struct l2tp_conn_t *conn;
struct sockaddr_in addr;
@@ -296,6 +302,23 @@ static int l2tp_tunnel_alloc(struct l2tp_serv_t *serv, struct l2tp_packet_t *pac
conn->peer_tid = assigned_tid->val.uint16;
conn->framing_cap = framing_cap->val.uint32;
+ /* If challenge set in SCCRQ, we need to calculate response for SCCRP */
+ if (challenge && challenge->length <= 16) {
+ char state = 2; /* SCCRP, TODO: define them in some .h? */
+ MD5_CTX md5_ctx;
+ uint8_t md5[MD5_DIGEST_LENGTH];
+
+ MD5_Init(&md5_ctx);
+ MD5_Update(&md5_ctx, &state, 1);
+ MD5_Update(&md5_ctx, conf_secret, strlen(conf_secret));
+ MD5_Update(&md5_ctx, challenge->val.octets, challenge->length);
+ MD5_Final(md5, &md5_ctx);
+
+ conn->challenge_len = MD5_DIGEST_LENGTH;
+ conn->challenge.octets = _malloc(MD5_DIGEST_LENGTH);
+ memcpy(conn->challenge.octets, &md5, MD5_DIGEST_LENGTH);
+ }
+
conn->ctx.before_switch = log_switch;
conn->ctx.close = l2tp_conn_close;
conn->hnd.read = l2tp_conn_read;
@@ -524,6 +547,11 @@ static void l2tp_send_SCCRP(struct l2tp_conn_t *conn)
goto out_err;
if (l2tp_packet_add_string(pack, Vendor_Name, "accel-ppp", 0))
goto out_err;
+ /* If challenge response available */
+ if (conn->challenge_len) {
+ if (l2tp_packet_add_octets(pack, Challenge_Response, conn->challenge.octets, 16, 1))
+ goto out_err;
+ }
if (l2tp_send(conn, pack, 0))
goto out;
@@ -623,6 +651,7 @@ static int l2tp_recv_SCCRQ(struct l2tp_serv_t *serv, struct l2tp_packet_t *pack,
struct l2tp_attr_t *assigned_cid = NULL;
struct l2tp_attr_t *framing_cap = NULL;
struct l2tp_attr_t *router_id = NULL;
+ struct l2tp_attr_t *challenge = NULL;
if (ppp_shutdown)
return 0;
@@ -642,9 +671,8 @@ static int l2tp_recv_SCCRQ(struct l2tp_serv_t *serv, struct l2tp_packet_t *pack,
assigned_tid = attr;
break;
case Challenge:
- if (conf_verbose)
- log_warn("l2tp: Challenge in SCCRQ is not supported\n");
- return -1;
+ challenge = attr;
+ break;
case Assigned_Connection_ID:
assigned_cid = attr;
break;
@@ -675,7 +703,7 @@ static int l2tp_recv_SCCRQ(struct l2tp_serv_t *serv, struct l2tp_packet_t *pack,
return -1;
}
- if (l2tp_tunnel_alloc(serv, pack, pkt_info, assigned_tid, framing_cap))
+ if (l2tp_tunnel_alloc(serv, pack, pkt_info, assigned_tid, framing_cap, challenge))
return -1;
} else if (assigned_cid) {
@@ -687,6 +715,12 @@ static int l2tp_recv_SCCRQ(struct l2tp_serv_t *serv, struct l2tp_packet_t *pack,
return -1;
}
+ if (conf_secret && !challenge) {
+ if (conf_verbose)
+ log_warn("l2tp: SCCRQ: no Challenge present in message\n");
+ return -1;
+ }
+
return 0;
}
@@ -1144,7 +1178,11 @@ static void load_config(void)
conf_host_name = opt;
else
conf_host_name = "accel-ppp";
-
+
+ opt = conf_get_opt("l2tp", "secret");
+ if (opt)
+ conf_secret = opt;
+
opt = conf_get_opt("l2tp", "dir300_quirk");
if (opt)
conf_dir300_quirk = atoi(opt);