1/* 2 * pptp.c 3 * 4 * Copyright (C) 2007 Sebastian Gottschall <gottschall@dd-wrt.com> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 2 9 * of the License. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 * 20 * $Id: 21 */ 22 23#include <rc.h> 24#include <stdlib.h> 25#include <bcmnvram.h> 26#include <shutils.h> 27#include <utils.h> 28#include <syslog.h> 29#include <errno.h> 30#include <sys/stat.h> 31 32void get_broadcast(char *ipaddr, char *netmask) 33{ 34 int ip2[4], mask2[4]; 35 unsigned char ip[4], mask[4]; 36 37 if (!ipaddr || !netmask) 38 return; 39 40 sscanf(ipaddr, "%d.%d.%d.%d", &ip2[0], &ip2[1], &ip2[2], &ip2[3]); 41 sscanf(netmask, "%d.%d.%d.%d", &mask2[0], &mask2[1], &mask2[2], 42 &mask2[3]); 43 int i = 0; 44 45 for (i = 0; i < 4; i++) { 46 ip[i] = ip2[i]; 47 mask[i] = mask2[i]; 48 ip[i] = (ip[i] & mask[i]) | (0xff & ~mask[i]); 49 } 50 51 sprintf(ipaddr, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); 52 53 //fprintf(stderr, "get_broadcast return %s\n", value); 54} 55 56char *pptp_encode(char *str, char *output) 57{ 58 int i; 59 int j; 60 61 i=j=0; 62 63 while(*(str+i)) { 64 if(*(str+i)==' ' || *(str+i)=='\\' || *(str+i)=='*' || *(str+i)=='\'' || *(str+i)=='"' || *(str+i)=='#') { 65 *(output+j++)='\\'; 66 *(output+j++)=*(str+i); 67 } 68 else *(output+j++) = *(str+i); 69 i++; 70 } 71 72 *(output+j)=0; 73 74 return output; 75} 76 77void write_chap_secret(char *file) 78{ 79 FILE *fp; 80 char *nv, *nvp, *b; 81 char *username, *passwd; 82 char namebuf[256], passwdbuf[256]; 83 84 fp=fopen(file, "w"); 85 86 if (fp==NULL) return; 87 88 nv = nvp = strdup(nvram_safe_get("pptpd_clientlist")); 89 90 if(nv) { 91 while ((b = strsep(&nvp, "<")) != NULL) { 92 if((vstrsep(b, ">", &username, &passwd)!=2)) continue; 93 if(strlen(username)==0||strlen(passwd)==0) continue; 94 fprintf(fp, "%s * %s *\n", pptp_encode(username, namebuf), pptp_encode(passwd, passwdbuf)); 95 } 96 free(nv); 97 } 98 fclose(fp); 99} 100 101void start_pptpd(void) 102{ 103 int ret = 0, mss = 0, manual_dns = 0, pptpd_opt = 0; 104 FILE *fp; 105 106 int pid = getpid(); 107 _dprintf("start_pptpd: getpid= %d\n", pid); 108 109 if(getpid() != 1) { 110 notify_rc("start_pptpd"); 111 return; 112 } 113 114 if (!nvram_match("pptpd_enable", "1")) { 115 return; 116 } 117 118 // cprintf("stop vpn modules\n"); 119 // stop_vpn_modules (); 120 121 // Create directory for use by pptpd daemon and its supporting files 122 mkdir("/tmp/pptpd", 0744); 123 //cprintf("open options file\n"); 124 // Create options file that will be unique to pptpd to avoid interference 125 // with pppoe and pptp 126 fp = fopen("/tmp/pptpd/options.pptpd", "w"); 127 fprintf(fp, "logfile /var/log/pptpd-pppd.log\n"); 128 //fprintf(fp, "debug dump logfd 2 nodetach\n"); 129 if (nvram_match("pptpd_radius", "1")) 130 fprintf(fp, "plugin radius.so\nplugin radattr.so\n" 131 "radius-config-file /tmp/pptpd/radius/radiusclient.conf\n"); 132 133 fprintf(fp, "lock\n" 134 "name *\n" 135 "proxyarp\n" 136// "ipcp-accept-local\n" 137// "ipcp-accept-remote\n" 138 "lcp-echo-failure 10\n" 139 "lcp-echo-interval 6\n" 140 "deflate 0\n" "auth\n" "-chap\n" 141 "nomppe-stateful\n"); 142 143 pptpd_opt = nvram_get_int("pptpd_chap"); 144 fprintf(fp, "%smschap\n", (pptpd_opt == 0 || pptpd_opt & 1) ? "+" : "-"); 145 fprintf(fp, "%smschap-v2\n", (pptpd_opt == 0 || pptpd_opt & 2) ? "+" : "-"); 146 147 pptpd_opt = nvram_get_int("pptpd_mppe"); 148 if (pptpd_opt == 0) 149 pptpd_opt = 1 | 4 | 8; 150 if (pptpd_opt & (1 | 2 | 4)) { 151 fprintf(fp, "%s", (pptpd_opt & 8) ? "" : "require-mppe\n"); 152 fprintf(fp, "%smppe-128\n", (pptpd_opt & 1) ? "require-" : "no"); 153 fprintf(fp, "%smppe-56\n", (pptpd_opt & 2) ? "require-" : "no"); 154 fprintf(fp, "%smppe-40\n", (pptpd_opt & 4) ? "require-" : "no"); 155 } else 156 fprintf(fp, "nomppe nomppc\n"); 157 158 fprintf(fp, "chapms-strip-domain\n" 159 "chap-secrets /tmp/pptpd/chap-secrets\n" 160 "ip-up-script /tmp/pptpd/ip-up\n" 161 "ip-down-script /tmp/pptpd/ip-down\n" 162 "mtu %s\n" "mru %s\n", 163 nvram_get("pptpd_mtu") ? nvram_get("pptpd_mtu") : "1450", 164 nvram_get("pptpd_mru") ? nvram_get("pptpd_mru") : "1450"); 165 //WINS Server 166 int wins_count = 0; 167 if (nvram_match("pptpd_ms_network", "1") && nvram_match("smbd_enable", "1")) 168 wins_count += fprintf(fp, "ms-wins %s\n", nvram_safe_get("lan_ipaddr")) > 0 ? 1 : 0; 169 if (strlen(nvram_safe_get("pptpd_wins1")) && (wins_count < 2)) 170 wins_count += fprintf(fp,"ms-wins %s\n", nvram_safe_get("pptpd_wins1")) > 0 ? 1 : 0; 171 if (strlen(nvram_safe_get("pptpd_wins2")) && (wins_count < 2)) 172 wins_count += fprintf(fp,"ms-wins %s\n", nvram_safe_get("pptpd_wins2")) > 0 ? 1 : 0; 173 174 //DNS Server 175 if (strlen(nvram_safe_get("pptpd_dns1"))) { 176 fprintf(fp, "ms-dns %s\n", nvram_safe_get("pptpd_dns1")); 177 manual_dns=1; 178 } 179 if (strlen(nvram_safe_get("pptpd_dns2"))) { 180 fprintf(fp, "ms-dns %s\n", nvram_safe_get("pptpd_dns2")); 181 manual_dns=1; 182 } 183 if(!manual_dns && !nvram_match("lan_ipaddr", "")) 184 fprintf(fp, "ms-dns %s\n", nvram_safe_get("lan_ipaddr")); 185 186 // force ppp interface starting from 10 187 fprintf(fp, "minunit 10\n"); 188 189 // Following is all crude and need to be revisited once testing confirms 190 // that it does work 191 // Should be enough for testing.. 192 if (nvram_match("pptpd_radius", "1")) { 193 if (nvram_get("pptpd_radserver") != NULL 194 && nvram_get("pptpd_radpass") != NULL) { 195 196 fclose(fp); 197 198 mkdir("/tmp/pptpd/radius", 0744); 199 200 fp = fopen("/tmp/pptpd/radius/radiusclient.conf", "w"); 201 fprintf(fp, "auth_order radius\n" 202 "login_tries 4\n" 203 "login_timeout 60\n" 204 "radius_timeout 10\n" 205 "nologin /etc/nologin\n" 206 "servers /tmp/pptpd/radius/servers\n" 207 "dictionary /etc/dictionary\n" 208 "seqfile /var/run/radius.seq\n" 209 "mapfile /etc/port-id-map\n" 210 "radius_retries 3\n" 211 "authserver %s:%s\n", 212 nvram_get("pptpd_radserver"), 213 nvram_get("pptpd_radport") ? 214 nvram_get("pptpd_radport") : "radius"); 215 216 if (nvram_get("pptpd_radserver") != NULL 217 && nvram_get("pptpd_acctport") != NULL) 218 fprintf(fp, "acctserver %s:%s\n", 219 nvram_get("pptpd_radserver"), 220 nvram_get("pptpd_acctport") ? 221 nvram_get("pptpd_acctport") : 222 "radacct"); 223 fclose(fp); 224 225 fp = fopen("/tmp/pptpd/radius/servers", "w"); 226 fprintf(fp, "%s\t%s\n", nvram_get("pptpd_radserver"), 227 nvram_get("pptpd_radpass")); 228 fclose(fp); 229 230 } else 231 fclose(fp); 232 } else 233 fclose(fp); 234 235 // Create pptpd.conf options file for pptpd daemon 236 fp = fopen("/tmp/pptpd/pptpd.conf", "w"); 237 fprintf(fp, "localip %s\n" 238 "remoteip %s\n", nvram_safe_get("lan_ipaddr"), 239 nvram_safe_get("pptpd_clients")); 240 if (nvram_invmatch("pptpd_broadcast", "") && 241 nvram_invmatch("pptpd_broadcast", "disable")) { 242 fprintf(fp, "bcrelay %s,%s\n", 243 nvram_safe_get("lan_ifname"), "ppp1[0-9].*"); 244 } 245 246 fclose(fp); 247 248 // Create ip-up and ip-down scripts that are unique to pptpd to avoid 249 // interference with pppoe and pptp 250 /* 251 * adjust for tunneling overhead (mtu - 40 byte IP - 108 byte tunnel 252 * overhead) 253 */ 254 if (nvram_match("mtu_enable", "1")) 255 mss = nvram_get_int("wan_mtu") - 40 - 108; 256 else 257 mss = 1500 - 40 - 108; 258 char bcast[32]; 259 260 strcpy(bcast, nvram_safe_get("lan_ipaddr")); 261 get_broadcast(bcast, nvram_safe_get("lan_netmask")); 262 263 fp = fopen("/tmp/pptpd/ip-up", "w"); 264 fprintf(fp, "#!/bin/sh\n" "startservice set_routes\n" // reinitialize 265 "echo $PPPD_PID $1 $5 $6 $PEERNAME >> /tmp/pptp_connected\n" 266 "iptables -I INPUT -i $1 -j ACCEPT\n" "iptables -I FORWARD -i $1 -j ACCEPT\n" 267 "iptables -I FORWARD -i $1 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu\n" 268 "iptables -t nat -I PREROUTING -i $1 -p udp -m udp --sport 9 -j DNAT --to-destination %s " // rule for wake on lan over pptp tunnel 269 "%s\n", bcast, 270 nvram_get("pptpd_ipup_script") ? nvram_get("pptpd_ipup_script") : ""); 271 272#if defined(CONFIG_BCMWL5) || defined(RTCONFIG_BCMWL6) || defined(RTCONFIG_BCMARM) 273 /* mark connect to bypass CTF */ 274 if(nvram_match("ctf_disable", "0")) 275 fprintf(fp, "iptables -t mangle -A FORWARD -i $1 -m state --state NEW -j MARK --set-mark 0x01/0x7\n"); 276#endif 277 278 //Add static router for vpn client 279 char *nv, *nvp, *b; 280 char *pptpd_client, *vpn_network, *vpn_netmask; 281 282 nv = nvp = strdup(nvram_safe_get("pptpd_sr_rulelist")); 283 if(nv) { 284 while ((b = strsep(&nvp, "<")) != NULL) { 285 if((vstrsep(b, ">", &pptpd_client, &vpn_network, &vpn_netmask)!=3)) continue; 286 if(strlen(pptpd_client)==0||strlen(vpn_network)==0||strlen(vpn_netmask)==0) continue; 287 fprintf(fp, "if[ \"$PEERNAME\" == \"%s\" ] then;\n", pptpd_client); 288 fprintf(fp, "route del -net %s netmask %s\n", vpn_network, vpn_netmask); 289 fprintf(fp, "route add -net %s netmask %s dev $1\n", vpn_network, vpn_netmask); 290 fprintf(fp, "fi\n"); 291 } 292 free(nv); 293 } 294 fclose(fp); 295 fp = fopen("/tmp/pptpd/ip-down", "w"); 296 fprintf(fp, "#!/bin/sh\n" "grep -v $1 /tmp/pptp_connected > /tmp/pptp_connected.new\n" 297 "mv /tmp/pptp_connected.new /tmp/pptp_connected\n" 298 "iptables -D FORWARD -i $1 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu\n" 299 "iptables -D INPUT -i $1 -j ACCEPT\n" 300 "iptables -D FORWARD -i $1 -j ACCEPT\n" 301 "iptables -t nat -D PREROUTING -i $1 -p udp -m udp --sport 9 -j DNAT --to-destination %s " // rule for wake on lan over pptp tunnel 302 "%s\n", bcast, 303 nvram_get("pptpd_ipdown_script") ? nvram_get("pptpd_ipdown_script") : ""); 304#if defined(CONFIG_BCMWL5) || defined(RTCONFIG_BCMWL6) || defined(RTCONFIG_BCMARM) 305 /* mark connect to bypass CTF */ 306 if(nvram_match("ctf_disable", "0")) 307 fprintf(fp, "iptables -t mangle -D FORWARD -i $1 -m state --state NEW -j MARK --set-mark 0x01/0x7\n"); 308#endif 309 fclose(fp); 310 chmod("/tmp/pptpd/ip-up", 0744); 311 chmod("/tmp/pptpd/ip-down", 0744); 312 313 // Exctract chap-secrets from nvram 314 write_chap_secret("/tmp/pptpd/chap-secrets"); 315 316 chmod("/tmp/pptpd/chap-secrets", 0600); 317 318 // Execute pptpd daemon 319 ret = 320 eval("pptpd", "-c", "/tmp/pptpd/pptpd.conf", "-o", 321 "/tmp/pptpd/options.pptpd"); 322 323 _dprintf("start_pptpd: ret= %d\n", ret); 324 //dd_syslog(LOG_INFO, "pptpd : pptp daemon successfully started\n"); 325 return; 326} 327 328void stop_pptpd(void) 329{ 330 if (getpid() != 1) { 331 notify_rc("stop_pptpd"); 332 } 333 334 killall_tk("pptpd"); 335 killall_tk("bcrelay"); 336 return; 337} 338 339