diff options
Diffstat (limited to 'accel-pptpd')
-rw-r--r-- | accel-pptpd/CMakeLists.txt | 2 | ||||
-rw-r--r-- | accel-pptpd/accel-pptpd.conf | 8 | ||||
-rw-r--r-- | accel-pptpd/ctrl/pptp.c | 8 | ||||
l--------- | accel-pptpd/include/iprange.h | 1 | ||||
-rw-r--r-- | accel-pptpd/iprange.c | 134 | ||||
-rw-r--r-- | accel-pptpd/iprange.h | 10 | ||||
-rw-r--r-- | accel-pptpd/ppp/ipcp_opt_ipaddr.c | 9 | ||||
-rw-r--r-- | accel-pptpd/radius/CMakeLists.txt | 2 | ||||
-rw-r--r-- | accel-pptpd/radius/pd_coa.c | 48 | ||||
-rw-r--r-- | accel-pptpd/radius/radius.c | 10 | ||||
-rw-r--r-- | accel-pptpd/radius/radius.h | 4 |
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); |