summaryrefslogtreecommitdiff
path: root/accel-pptpd
diff options
context:
space:
mode:
Diffstat (limited to 'accel-pptpd')
-rw-r--r--accel-pptpd/CMakeLists.txt2
-rw-r--r--accel-pptpd/accel-pptpd.conf8
-rw-r--r--accel-pptpd/ctrl/pptp.c8
l---------accel-pptpd/include/iprange.h1
-rw-r--r--accel-pptpd/iprange.c134
-rw-r--r--accel-pptpd/iprange.h10
-rw-r--r--accel-pptpd/ppp/ipcp_opt_ipaddr.c9
-rw-r--r--accel-pptpd/radius/CMakeLists.txt2
-rw-r--r--accel-pptpd/radius/pd_coa.c48
-rw-r--r--accel-pptpd/radius/radius.c10
-rw-r--r--accel-pptpd/radius/radius.h4
11 files changed, 202 insertions, 34 deletions
diff --git a/accel-pptpd/CMakeLists.txt b/accel-pptpd/CMakeLists.txt
index 041c668..729b4e2 100644
--- a/accel-pptpd/CMakeLists.txt
+++ b/accel-pptpd/CMakeLists.txt
@@ -28,6 +28,8 @@ ADD_EXECUTABLE(pptpd
log.c
pwdb.c
ipdb.c
+
+ iprange.c
main.c
)
diff --git a/accel-pptpd/accel-pptpd.conf b/accel-pptpd/accel-pptpd.conf
index 26bb27d..9d5aa9b 100644
--- a/accel-pptpd/accel-pptpd.conf
+++ b/accel-pptpd/accel-pptpd.conf
@@ -24,5 +24,11 @@ nas-ip-address=127.0.0.1
gw-ip-address=192.168.100.100
auth_server=127.0.0.1:1812,testing123
acct_server=127.0.0.1:1813,testing123
-pd_coa_secret=testing123
+dm_coa_secret=testing123
verbose=1
+
+[client-ip-range]
+192.168.10.20-20
+
+[ip-pool]
+192.168.100.200/24
diff --git a/accel-pptpd/ctrl/pptp.c b/accel-pptpd/ctrl/pptp.c
index 3a3c242..38f8473 100644
--- a/accel-pptpd/ctrl/pptp.c
+++ b/accel-pptpd/ctrl/pptp.c
@@ -17,7 +17,7 @@
#include "triton.h"
#include "log.h"
#include "ppp.h"
-
+#include "iprange.h"
#define STATE_IDLE 0
#define STATE_ESTB 1
@@ -477,6 +477,12 @@ static int pptp_connect(struct triton_md_handler_t *h)
log_info("pptp: new connection from %s\n", inet_ntoa(addr.sin_addr));
+ if (iprange_client_check(addr.sin_addr.s_addr)) {
+ log_warn("pptp: IP is out of client-ip-range, droping connection...\n");
+ close(sock);
+ continue;
+ }
+
if (fcntl(sock, F_SETFL, O_NONBLOCK)) {
log_error("pptp: failed to set nonblocking mode: %s, closing connection...\n", strerror(errno));
close(sock);
diff --git a/accel-pptpd/include/iprange.h b/accel-pptpd/include/iprange.h
new file mode 120000
index 0000000..b8c2c43
--- /dev/null
+++ b/accel-pptpd/include/iprange.h
@@ -0,0 +1 @@
+../iprange.h \ No newline at end of file
diff --git a/accel-pptpd/iprange.c b/accel-pptpd/iprange.c
new file mode 100644
index 0000000..000e6e6
--- /dev/null
+++ b/accel-pptpd/iprange.c
@@ -0,0 +1,134 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include "triton.h"
+#include "list.h"
+
+#include "iprange.h"
+
+struct iprange_t
+{
+ struct list_head entry;
+ uint32_t prefix;
+ uint32_t mask;
+ uint32_t end;
+};
+
+static LIST_HEAD(client_ranges);
+//static LIST_HEAD(tunnel_ranges);
+
+//parses ranges like x.x.x.x/mask
+static struct iprange_t *parse1(const char *str)
+{
+ int n,f1,f2,f3,f4,m;
+ struct iprange_t *r;
+
+ n = sscanf(str, "%u.%u.%u.%u/%u",&f1, &f2, &f3, &f4, &m);
+ if (n != 5)
+ return NULL;
+ if (f1 > 255)
+ return NULL;
+ if (f1 > 255)
+ return NULL;
+ if (f1 > 255)
+ return NULL;
+ if (f1 > 255)
+ return NULL;
+ if (m == 0 || m > 32)
+ return NULL;
+
+ r = malloc(sizeof(*r));
+ r->prefix = (f4 << 24) | (f3 << 16) | (f2 << 8) | f1;
+ r->mask = 0;
+
+ for (n = 0; n < m ; n++)
+ r->mask |= 1 << n;
+
+ return r;
+}
+
+//parses ranges like x.x.x.x-y
+static struct iprange_t *parse2(const char *str)
+{
+ int n,f1,f2,f3,f4,m;
+ struct iprange_t *r;
+
+ n = sscanf(str, "%u.%u.%u.%u-%u",&f1, &f2, &f3, &f4, &m);
+ if (n != 5)
+ return NULL;
+ if (f1 > 255)
+ return NULL;
+ if (f2 > 255)
+ return NULL;
+ if (f3 > 255)
+ return NULL;
+ if (f4 > 255)
+ return NULL;
+ if (m < f4 || m > 255)
+ return NULL;
+
+ r = malloc(sizeof(*r));
+ r->prefix = (f4 << 24) | (f3 << 16) | (f2 << 8) | f1;
+ r->end = (m << 24) | (f2 << 16) | (f3 << 8) | f1;
+ r->mask = 0;
+
+ return r;
+}
+
+static void load_ranges(struct list_head *list, const char *conf_sect)
+{
+ struct conf_sect_t *s = conf_get_section(conf_sect);
+ struct conf_option_t *opt;
+ struct iprange_t *r;
+
+ if (!s) {
+ fprintf(stderr, "iprange: section '%s' not found in config file, pptp and l2tp probably will not work...\n", conf_sect);
+ return;
+ }
+
+ list_for_each_entry(opt, &s->items, entry) {
+ r = parse1(opt->name);
+ if (!r)
+ r = parse2(opt->name);
+ if (!r) {
+ fprintf(stderr, "iprange: cann't parse '%s' in '%s'\n", opt->name, conf_sect);
+ _exit(EXIT_FAILURE);
+ }
+ list_add_tail(&r->entry, list);
+ }
+}
+
+static int check_range(struct list_head *list, in_addr_t ipaddr)
+{
+ struct iprange_t *r;
+
+ list_for_each_entry(r, list, entry) {
+ if (r->mask) {
+ if ((r->prefix & r->mask) == (ipaddr & r->mask))
+ return 0;
+ } else {
+ if (ipaddr >= r->prefix && ipaddr <= r->end)
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+int __export iprange_client_check(in_addr_t ipaddr)
+{
+ return check_range(&client_ranges, ipaddr);
+}
+/*int __export iprange_tunnel_check(in_addr_t ipaddr)
+{
+ return check_range(&tunnel_ranges, ipaddr);
+}*/
+
+static void __init iprange_init(void)
+{
+ load_ranges(&client_ranges, "client-ip-range");
+ //load_ranges(&tunnel_ranges, "tunnel-ip-range");
+}
+
diff --git a/accel-pptpd/iprange.h b/accel-pptpd/iprange.h
new file mode 100644
index 0000000..88a2486
--- /dev/null
+++ b/accel-pptpd/iprange.h
@@ -0,0 +1,10 @@
+#ifndef __IPRANGE_H
+#define __IPRANGE_H
+
+#include <netinet/in.h>
+
+int iprange_client_check(in_addr_t ipaddr);
+int iprange_tunnel_check(in_addr_t ipaddr);
+
+#endif
+
diff --git a/accel-pptpd/ppp/ipcp_opt_ipaddr.c b/accel-pptpd/ppp/ipcp_opt_ipaddr.c
index ddfb3d2..6e52cfa 100644
--- a/accel-pptpd/ppp/ipcp_opt_ipaddr.c
+++ b/accel-pptpd/ppp/ipcp_opt_ipaddr.c
@@ -10,6 +10,7 @@
#include "ppp_ipcp.h"
#include "log.h"
#include "ipdb.h"
+#include "iprange.h"
static struct ipcp_option_t *ipaddr_init(struct ppp_ipcp_t *ipcp);
static void ipaddr_free(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt);
@@ -65,6 +66,14 @@ static int ipaddr_send_conf_req(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *o
log_warn("ppp:ipcp: no free IP address\n");
return -1;
}
+ if (!iprange_client_check(ipaddr_opt->peer_addr)) {
+ log_warn("ppp:ipcp: to avoid hard loops requested IP cannot be assigned (%i.%i.%i.%i)\n",
+ ipaddr_opt->peer_addr&0xff,
+ (ipaddr_opt->peer_addr >> 8)&0xff,
+ (ipaddr_opt->peer_addr >> 16)&0xff,
+ (ipaddr_opt->peer_addr >> 24)&0xff);
+ return -1;
+ }
opt32->hdr.id=CI_ADDR;
opt32->hdr.len=6;
diff --git a/accel-pptpd/radius/CMakeLists.txt b/accel-pptpd/radius/CMakeLists.txt
index ac8a3a9..c8c44f8 100644
--- a/accel-pptpd/radius/CMakeLists.txt
+++ b/accel-pptpd/radius/CMakeLists.txt
@@ -6,7 +6,7 @@ SET(sources
packet.c
auth.c
acct.c
- pd_coa.c
+ dm_coa.c
)
ADD_LIBRARY(radius SHARED ${sources})
diff --git a/accel-pptpd/radius/pd_coa.c b/accel-pptpd/radius/pd_coa.c
index b19575c..0d2f405 100644
--- a/accel-pptpd/radius/pd_coa.c
+++ b/accel-pptpd/radius/pd_coa.c
@@ -18,13 +18,13 @@
#define PD_COA_PORT 3799
-struct pd_coa_serv_t
+struct dm_coa_serv_t
{
struct triton_context_t ctx;
struct triton_md_handler_t hnd;
};
-static int pd_coa_check_RA(struct rad_packet_t *pack, const char *secret)
+static int dm_coa_check_RA(struct rad_packet_t *pack, const char *secret)
{
uint8_t RA[16];
MD5_CTX ctx;
@@ -41,7 +41,7 @@ static int pd_coa_check_RA(struct rad_packet_t *pack, const char *secret)
return memcmp(RA, pack->buf + 4, 16);
}
-static void pd_coa_set_RA(struct rad_packet_t *pack, const char *secret)
+static void dm_coa_set_RA(struct rad_packet_t *pack, const char *secret)
{
MD5_CTX ctx;
@@ -53,21 +53,21 @@ static void pd_coa_set_RA(struct rad_packet_t *pack, const char *secret)
static void disconnect_request(struct radius_pd_t *rpd)
{
- rad_packet_free(rpd->pd_coa_req);
- rpd->pd_coa_req = NULL;
+ rad_packet_free(rpd->dm_coa_req);
+ rpd->dm_coa_req = NULL;
ppp_terminate(rpd->ppp, 0);
}
static void coa_request(struct radius_pd_t *rpd)
{
- rad_packet_free(rpd->pd_coa_req);
- rpd->pd_coa_req = NULL;
+ rad_packet_free(rpd->dm_coa_req);
+ rpd->dm_coa_req = NULL;
/// TODO: CoA handling
}
-static int pd_coa_read(struct triton_md_handler_t *h)
+static int dm_coa_read(struct triton_md_handler_t *h)
{
struct rad_packet_t *pack;
struct rad_packet_t *reply = NULL;
@@ -82,12 +82,12 @@ static int pd_coa_read(struct triton_md_handler_t *h)
return 0;
if (pack->code != CODE_DISCONNECT_REQUEST && pack->code != CODE_COA_REQUEST) {
- log_warn("radius:pd_coa: unexpected code (%i) received\n", pack->code);
+ log_warn("radius:dm_coa: unexpected code (%i) received\n", pack->code);
goto out_err_no_reply;
}
- if (pd_coa_check_RA(pack, conf_pd_coa_secret)) {
- log_warn("radius:pd_coa: RA validation failed\n");
+ if (dm_coa_check_RA(pack, conf_dm_coa_secret)) {
+ log_warn("radius:dm_coa: RA validation failed\n");
goto out_err_no_reply;
}
@@ -99,19 +99,19 @@ static int pd_coa_read(struct triton_md_handler_t *h)
}
if (rad_check_nas_pack(pack)) {
- log_warn("radius:pd_coa: NAS identification failed\n");
+ log_warn("radius:dm_coa: NAS identification failed\n");
err_code = 403;
goto out_err;
}
rpd = rad_find_session_pack(pack);
if (!rpd) {
- log_warn("radius:pd_coa: session not found\n");
+ log_warn("radius:dm_coa: session not found\n");
err_code = 503;
goto out_err;
}
- rpd->pd_coa_req = pack;
+ rpd->dm_coa_req = pack;
if (pack->code == CODE_DISCONNECT_REQUEST)
triton_context_call(rpd->ppp->ctrl->ctx, (void (*)(void *))disconnect_request, rpd);
@@ -124,7 +124,7 @@ static int pd_coa_read(struct triton_md_handler_t *h)
reply->id = pack->id;
if (rad_packet_build(reply, RA))
goto out_err_no_reply;
- pd_coa_set_RA(reply, conf_pd_coa_secret);
+ dm_coa_set_RA(reply, conf_dm_coa_secret);
if (conf_verbose) {
log_debug("send ");
rad_packet_print(reply, log_debug);
@@ -140,7 +140,7 @@ out_err:
reply->id = pack->id;
if (rad_packet_build(reply, RA))
goto out_err_no_reply;
- pd_coa_set_RA(reply, conf_pd_coa_secret);
+ dm_coa_set_RA(reply, conf_dm_coa_secret);
if (conf_verbose) {
log_debug("send ");
rad_packet_print(reply, log_debug);
@@ -154,16 +154,16 @@ out_err_no_reply:
return 0;
}
-static void pd_coa_close(struct triton_context_t *ctx)
+static void dm_coa_close(struct triton_context_t *ctx)
{
- struct pd_coa_serv_t *serv = container_of(ctx, typeof(*serv), ctx);
+ struct dm_coa_serv_t *serv = container_of(ctx, typeof(*serv), ctx);
triton_md_unregister_handler(&serv->hnd);
close(serv->hnd.fd);
}
-static struct pd_coa_serv_t serv = {
- .ctx.close = pd_coa_close,
- .hnd.read = pd_coa_read,
+static struct dm_coa_serv_t serv = {
+ .ctx.close = dm_coa_close,
+ .hnd.read = dm_coa_read,
};
static void __init init(void)
@@ -172,7 +172,7 @@ static void __init init(void)
serv.hnd.fd = socket (PF_INET, SOCK_DGRAM, 0);
if (serv.hnd.fd < 0) {
- log_error("radius:pd_coa: socket: %s\n", strerror(errno));
+ log_error("radius:dm_coa: socket: %s\n", strerror(errno));
return;
}
addr.sin_family = AF_INET;
@@ -182,13 +182,13 @@ static void __init init(void)
else
addr.sin_addr.s_addr = htonl (INADDR_ANY);
if (bind (serv.hnd.fd, (struct sockaddr *) &addr, sizeof (addr)) < 0) {
- log_error("radius:pd_coa: bind: %s\n", strerror(errno));
+ log_error("radius:dm_coa: bind: %s\n", strerror(errno));
close(serv.hnd.fd);
return;
}
if (fcntl(serv.hnd.fd, F_SETFL, O_NONBLOCK)) {
- log_error("radius:pd_coa: failed to set nonblocking mode: %s\n", strerror(errno));
+ log_error("radius:dm_coa: failed to set nonblocking mode: %s\n", strerror(errno));
close(serv.hnd.fd);
return;
}
diff --git a/accel-pptpd/radius/radius.c b/accel-pptpd/radius/radius.c
index de64f6b..d709963 100644
--- a/accel-pptpd/radius/radius.c
+++ b/accel-pptpd/radius/radius.c
@@ -30,7 +30,7 @@ char *conf_auth_secret;
char *conf_acct_server;
int conf_acct_server_port = 1813;
char *conf_acct_secret;
-char *conf_pd_coa_secret;
+char *conf_dm_coa_secret;
static LIST_HEAD(sessions);
static pthread_rwlock_t sessions_lock = PTHREAD_RWLOCK_INITIALIZER;
@@ -137,8 +137,8 @@ static void ppp_finished(struct ppp_notified_t *n, struct ppp_t *ppp)
pthread_mutex_unlock(&rpd->lock);
pthread_rwlock_unlock(&sessions_lock);
- if (rpd->pd_coa_req)
- rad_packet_free(rpd->pd_coa_req);
+ if (rpd->dm_coa_req)
+ rad_packet_free(rpd->dm_coa_req);
list_del(&rpd->pd.entry);
free(rpd);
@@ -308,9 +308,9 @@ static void __init radius_init(void)
_exit(EXIT_FAILURE);
}
- opt = conf_get_opt("radius", "pd_coa_secret");
+ opt = conf_get_opt("radius", "dm_coa_secret");
if (opt)
- conf_pd_coa_secret = opt;
+ conf_dm_coa_secret = opt;
opt = conf_get_opt("radius", "dictionary");
if (!opt) {
diff --git a/accel-pptpd/radius/radius.h b/accel-pptpd/radius/radius.h
index 9728a4a..cededbe 100644
--- a/accel-pptpd/radius/radius.h
+++ b/accel-pptpd/radius/radius.h
@@ -40,7 +40,7 @@ struct radius_pd_t
struct rad_req_t *acct_req;
struct triton_timer_t acct_interim_timer;
- struct rad_packet_t *pd_coa_req;
+ struct rad_packet_t *dm_coa_req;
in_addr_t ipaddr;
int acct_interim_interval;
@@ -120,7 +120,7 @@ extern int conf_auth_server_port;
extern char *conf_acct_server;
extern char *conf_acct_secret;
extern int conf_acct_server_port;
-extern char *conf_pd_coa_secret;
+extern char *conf_dm_coa_secret;
int rad_check_nas_pack(struct rad_packet_t *pack);
struct radius_pd_t *rad_find_session(const char *sessionid, const char *username, int port_id, in_addr_t ipaddr);