1#include <stdio.h> 2#include <stdlib.h> 3#include <stdbool.h> 4#include <ctype.h> 5#include <string.h> 6#include <stdarg.h> 7#include <unistd.h> 8 9#include <shared.h> 10#include "httpd.h" 11#include "openvpn_options.h" 12#define TYPEDEF_BOOL 13#include <bcmnvram.h> 14#include <shared.h> 15#include "shutils.h" 16 17struct buffer 18alloc_buf (size_t size) 19{ 20 struct buffer buf; 21 22 if (!buf_size_valid (size)) 23 buf_size_error (size); 24 buf.capacity = (int)size; 25 buf.offset = 0; 26 buf.len = 0; 27 buf.data = calloc (1, size); 28 29 return buf; 30} 31 32void 33buf_size_error (const size_t size) 34{ 35 logmessage ("OVPN", "fatal buffer size error, size=%lu", (unsigned long)size); 36} 37 38bool 39buf_printf (struct buffer *buf, const char *format, ...) 40{ 41 int ret = false; 42 if (buf_defined (buf)) 43 { 44 va_list arglist; 45 uint8_t *ptr = buf_bend (buf); 46 int cap = buf_forward_capacity (buf); 47 48 if (cap > 0) 49 { 50 int stat; 51 va_start (arglist, format); 52 stat = vsnprintf ((char *)ptr, cap, format, arglist); 53 va_end (arglist); 54 *(buf->data + buf->capacity - 1) = 0; /* windows vsnprintf needs this */ 55 buf->len += (int) strlen ((char *)ptr); 56 if (stat >= 0 && stat < cap) 57 ret = true; 58 } 59 } 60 return ret; 61} 62 63bool 64buf_parse (struct buffer *buf, const int delim, char *line, const int size) 65{ 66 bool eol = false; 67 int n = 0; 68 int c; 69 70 do 71 { 72 c = buf_read_u8 (buf); 73 if (c < 0) 74 eol = true; 75 if (c <= 0 || c == delim) 76 c = 0; 77 if (n >= size) 78 break; 79 line[n++] = c; 80 } 81 while (c); 82 83 line[size-1] = '\0'; 84 return !(eol && !strlen (line)); 85} 86 87void 88buf_clear (struct buffer *buf) 89{ 90 if (buf->capacity > 0) 91 memset (buf->data, 0, buf->capacity); 92 buf->len = 0; 93 buf->offset = 0; 94} 95 96void 97free_buf (struct buffer *buf) 98{ 99 if (buf->data) 100 free (buf->data); 101 CLEAR (*buf); 102} 103 104char * 105string_alloc (const char *str) 106{ 107 if (str) 108 { 109 const int n = strlen (str) + 1; 110 char *ret; 111 112 ret = calloc(n, 1); 113 if(!ret) 114 return NULL; 115 116 memcpy (ret, str, n); 117 return ret; 118 } 119 else 120 return NULL; 121} 122 123static inline bool 124space (unsigned char c) 125{ 126 return c == '\0' || isspace (c); 127} 128 129int 130parse_line (const char *line, char *p[], const int n, const int line_num) 131{ 132 const int STATE_INITIAL = 0; 133 const int STATE_READING_QUOTED_PARM = 1; 134 const int STATE_READING_UNQUOTED_PARM = 2; 135 const int STATE_DONE = 3; 136 const int STATE_READING_SQUOTED_PARM = 4; 137 138 int ret = 0; 139 const char *c = line; 140 int state = STATE_INITIAL; 141 bool backslash = false; 142 char in, out; 143 144 char parm[OPTION_PARM_SIZE]; 145 unsigned int parm_len = 0; 146 147 do 148 { 149 in = *c; 150 out = 0; 151 152 if (!backslash && in == '\\' && state != STATE_READING_SQUOTED_PARM) 153 { 154 backslash = true; 155 } 156 else 157 { 158 if (state == STATE_INITIAL) 159 { 160 if (!space (in)) 161 { 162 if (in == ';' || in == '#') /* comment */ 163 break; 164 if (!backslash && in == '\"') 165 state = STATE_READING_QUOTED_PARM; 166 else if (!backslash && in == '\'') 167 state = STATE_READING_SQUOTED_PARM; 168 else 169 { 170 out = in; 171 state = STATE_READING_UNQUOTED_PARM; 172 } 173 } 174 } 175 else if (state == STATE_READING_UNQUOTED_PARM) 176 { 177 if (!backslash && space (in)) 178 state = STATE_DONE; 179 else 180 out = in; 181 } 182 else if (state == STATE_READING_QUOTED_PARM) 183 { 184 if (!backslash && in == '\"') 185 state = STATE_DONE; 186 else 187 out = in; 188 } 189 else if (state == STATE_READING_SQUOTED_PARM) 190 { 191 if (in == '\'') 192 state = STATE_DONE; 193 else 194 out = in; 195 } 196 197 if (state == STATE_DONE) 198 { 199 p[ret] = calloc (parm_len + 1, 1); 200 memcpy (p[ret], parm, parm_len); 201 p[ret][parm_len] = '\0'; 202 state = STATE_INITIAL; 203 parm_len = 0; 204 ++ret; 205 } 206 207 if (backslash && out) 208 { 209 if (!(out == '\\' || out == '\"' || space (out))) 210 { 211 logmessage ("OVPN", "Options warning: Bad backslash ('\\') usage in %d", line_num); 212 return 0; 213 } 214 } 215 backslash = false; 216 } 217 218 /* store parameter character */ 219 if (out) 220 { 221 if (parm_len >= SIZE (parm)) 222 { 223 parm[SIZE (parm) - 1] = 0; 224 logmessage ("OVPN", "Options error: Parameter at %d is too long (%d chars max): %s", 225 line_num, (int) SIZE (parm), parm); 226 return 0; 227 } 228 parm[parm_len++] = out; 229 } 230 231 /* avoid overflow if too many parms in one config file line */ 232 if (ret >= n) 233 break; 234 235 } while (*c++ != '\0'); 236 237 238 if (state == STATE_READING_QUOTED_PARM) 239 { 240 logmessage ("OVPN", "Options error: No closing quotation (\") in %d", line_num); 241 return 0; 242 } 243 if (state == STATE_READING_SQUOTED_PARM) 244 { 245 logmessage ("OVPN", "Options error: No closing single quotation (\') in %d", line_num); 246 return 0; 247 } 248 if (state != STATE_INITIAL) 249 { 250 logmessage ("OVPN", "Options error: Residual parse state (%d) in %d", line_num); 251 return 0; 252 } 253 254 return ret; 255} 256 257static void 258bypass_doubledash (char **p) 259{ 260 if (strlen (*p) >= 3 && !strncmp (*p, "--", 2)) 261 *p += 2; 262} 263 264static bool 265in_src_get (const struct in_src *is, char *line, const int size) 266{ 267 if (is->type == IS_TYPE_FP) 268 { 269 return BOOL_CAST (fgets (line, size, is->u.fp)); 270 } 271 else if (is->type == IS_TYPE_BUF) 272 { 273 bool status = buf_parse (is->u.multiline, '\n', line, size); 274 if ((int) strlen (line) + 1 < size) 275 strcat (line, "\n"); 276 return status; 277 } 278 else 279 { 280 return false; 281 } 282} 283 284static char * 285read_inline_file (struct in_src *is, const char *close_tag) 286{ 287 char line[OPTION_LINE_SIZE]; 288 struct buffer buf = alloc_buf (10000); 289 char *ret; 290 while (in_src_get (is, line, sizeof (line))) 291 { 292 if (!strncmp (line, close_tag, strlen (close_tag))) 293 break; 294 buf_printf (&buf, "%s", line); 295 } 296 ret = string_alloc (buf_str (&buf)); 297 buf_clear (&buf); 298 free_buf (&buf); 299 CLEAR (line); 300 return ret; 301} 302 303static bool 304check_inline_file (struct in_src *is, char *p[]) 305{ 306 bool ret = false; 307 if (p[0] && !p[1]) 308 { 309 char *arg = p[0]; 310 if (arg[0] == '<' && arg[strlen(arg)-1] == '>') 311 { 312 struct buffer close_tag; 313 arg[strlen(arg)-1] = '\0'; 314 p[0] = string_alloc (arg+1); 315 p[1] = string_alloc (INLINE_FILE_TAG); 316 close_tag = alloc_buf (strlen(p[0]) + 4); 317 buf_printf (&close_tag, "</%s>", p[0]); 318 p[2] = read_inline_file (is, buf_str (&close_tag)); 319 p[3] = NULL; 320 free_buf (&close_tag); 321 ret = true; 322 } 323 } 324 return ret; 325} 326 327static bool 328check_inline_file_via_fp (FILE *fp, char *p[]) 329{ 330 struct in_src is; 331 is.type = IS_TYPE_FP; 332 is.u.fp = fp; 333 return check_inline_file (&is, p); 334} 335 336void 337add_custom(char *nv, char *p[]) 338{ 339 char *custom = nvram_safe_get(nv); 340 char *param = NULL; 341 char *final_custom = NULL; 342 int i = 0, size = 0; 343 344 if(!p[0]) 345 return; 346 347 while(p[i]) { 348 size += strlen(p[i]) + 1; 349 i++; 350 } 351 352 param = (char*)calloc(size, sizeof(char)); 353 354 if(!param) 355 return; 356 357 i = 0; 358 while(p[i]) { 359 if(*param) 360 strcat(param, " "); 361 strcat(param, p[i]); 362 i++; 363 } 364 365 if(custom) { 366 final_custom = calloc(strlen(custom) + strlen(param) + 2, sizeof(char)); 367 if(final_custom) { 368 if(*custom) { 369 strcat(final_custom, custom); 370 strcat(final_custom, "\n"); 371 } 372 strcat(final_custom, param); 373 nvram_set(nv, final_custom); 374 free(final_custom); 375 } 376 } 377 else 378 nvram_set(nv, param); 379 380 free(param); 381} 382 383static int 384add_option (char *p[], int line, int unit) 385{ 386 char buf[32] = {0}; 387 FILE *fp; 388 char file_path[128] ={0}; 389 390 if (streq (p[0], "dev") && p[1]) 391 { 392 sprintf(buf, "vpn_client%d_if", unit); 393 if(!strncmp(p[1], "tun", 3)) 394 nvram_set(buf, "tun"); 395 else if(!strncmp(p[1], "tap", 3)) 396 nvram_set(buf, "tap"); 397 } 398 else if (streq (p[0], "proto") && p[1]) 399 { 400 sprintf(buf, "vpn_client%d_proto", unit); 401 nvram_set(buf, p[1]); 402 } 403 else if (streq (p[0], "remote") && p[1]) 404 { 405 sprintf(buf, "vpn_client%d_addr", unit); 406 nvram_set(buf, p[1]); 407 408 sprintf(buf, "vpn_client%d_port", unit); 409 if(p[2]) 410 nvram_set(buf, p[2]); 411 else 412 nvram_set(buf, "1194"); 413 } 414 else if (streq (p[0], "resolv-retry") && p[1]) 415 { 416 sprintf(buf, "vpn_client%d_retry", unit); 417 if (streq (p[1], "infinite")) 418 nvram_set(buf, "-1"); 419 else 420 nvram_set(buf, p[1]); 421 } 422 else if (streq (p[0], "comp-lzo")) 423 { 424 sprintf(buf, "vpn_client%d_comp", unit); 425 if(p[1]) 426 nvram_set(buf, p[1]); 427 else 428 nvram_set(buf, "adaptive"); 429 } 430 else if (streq (p[0], "cipher") && p[1]) 431 { 432 sprintf(buf, "vpn_client%d_cipher", unit); 433 nvram_set(buf, p[1]); 434 } 435 else if (streq (p[0], "verb") && p[1]) 436 { 437 nvram_set("vpn_loglevel", p[1]); 438 } 439 else if (streq (p[0], "ca") && p[1]) 440 { 441 sprintf(buf, "vpn_client%d_crypt", unit); 442 nvram_set(buf, "tls"); 443 if (streq (p[1], INLINE_FILE_TAG) && p[2]) 444 { 445 sprintf(buf, "vpn_crt_client%d_ca", unit); 446#if defined(RTCONFIG_JFFS2) || defined(RTCONFIG_BRCM_NAND_JFFS2) || defined(RTCONFIG_UBIFS) 447 snprintf(file_path, sizeof(file_path) -1, "%s/%s", OVPN_FS_PATH, buf); 448 fp = fopen(file_path, "w"); 449 if(fp) { 450 fprintf(fp, "%s", strstr(p[2], "-----BEGIN")); 451 fclose(fp); 452 } 453 else 454#endif 455 nvram_set(buf, strstr(p[2], "-----BEGIN")); 456 } 457 else 458 { 459 return VPN_UPLOAD_NEED_CA_CERT; 460 } 461 } 462 else if (streq (p[0], "cert") && p[1]) 463 { 464 if (streq (p[1], INLINE_FILE_TAG) && p[2]) 465 { 466 sprintf(buf, "vpn_crt_client%d_crt", unit); 467#if defined(RTCONFIG_JFFS2) || defined(RTCONFIG_BRCM_NAND_JFFS2) || defined(RTCONFIG_UBIFS) 468 snprintf(file_path, sizeof(file_path) -1, "%s/%s", OVPN_FS_PATH, buf); 469 fp = fopen(file_path, "w"); 470 if(fp) { 471 fprintf(fp, "%s", strstr(p[2], "-----BEGIN")); 472 fclose(fp); 473 } 474 else 475#endif 476 nvram_set(buf, strstr(p[2], "-----BEGIN")); 477 } 478 else 479 { 480 return VPN_UPLOAD_NEED_CERT; 481 } 482 } 483 else if (streq (p[0], "key") && p[1]) 484 { 485 if (streq (p[1], INLINE_FILE_TAG) && p[2]) 486 { 487 sprintf(buf, "vpn_crt_client%d_key", unit); 488#if defined(RTCONFIG_JFFS2) || defined(RTCONFIG_BRCM_NAND_JFFS2) || defined(RTCONFIG_UBIFS) 489 snprintf(file_path, sizeof(file_path) -1, "%s/%s", OVPN_FS_PATH, buf); 490 fp = fopen(file_path, "w"); 491 if(fp) { 492 fprintf(fp, "%s", strstr(p[2], "-----BEGIN")); 493 fclose(fp); 494 } 495 else 496#endif 497 nvram_set(buf, strstr(p[2], "-----BEGIN")); 498 } 499 else 500 { 501 return VPN_UPLOAD_NEED_KEY; 502 } 503 } 504 else if (streq (p[0], "tls-auth") && p[1]) 505 { 506 if (streq (p[1], INLINE_FILE_TAG) && p[2]) 507 { 508 sprintf(buf, "vpn_crt_client%d_static", unit); 509#if defined(RTCONFIG_JFFS2) || defined(RTCONFIG_BRCM_NAND_JFFS2) || defined(RTCONFIG_UBIFS) 510 snprintf(file_path, sizeof(file_path) -1, "%s/%s", OVPN_FS_PATH, buf); 511 fp = fopen(file_path, "w"); 512 if(fp) { 513 fprintf(fp, "%s", strstr(p[2], "-----BEGIN")); 514 fclose(fp); 515 } 516 else 517#endif 518 nvram_set(buf, strstr(p[2], "-----BEGIN")); 519 //key-direction 520 sprintf(buf, "vpn_crt_client%d_hmac", unit); 521 if(nvram_match(buf, "-1")) //default, disable 522 nvram_set(buf, "2"); //openvpn default value: KEY_DIRECTION_BIDIRECTIONAL 523 } 524 else 525 { 526 if(p[2]) { 527 sprintf(buf, "vpn_client%d_hmac", unit); 528 nvram_set(buf, p[2]); 529 } 530 return VPN_UPLOAD_NEED_STATIC; 531 } 532 } 533 else if (streq (p[0], "secret") && p[1]) 534 { 535 sprintf(buf, "vpn_client%d_crypt", unit); 536 nvram_set(buf, "secret"); 537 if (streq (p[1], INLINE_FILE_TAG) && p[2]) 538 { 539 sprintf(buf, "vpn_crt_client%d_static", unit); 540#if defined(RTCONFIG_JFFS2) || defined(RTCONFIG_BRCM_NAND_JFFS2) || defined(RTCONFIG_UBIFS) 541 snprintf(file_path, sizeof(file_path) -1, "%s/%s", OVPN_FS_PATH, buf); 542 fp = fopen(file_path, "w"); 543 if(fp) { 544 fprintf(fp, "%s", strstr(p[2], "-----BEGIN")); 545 fclose(fp); 546 } 547 else 548#endif 549 nvram_set(buf, strstr(p[2], "-----BEGIN")); 550 } 551 else 552 { 553 return VPN_UPLOAD_NEED_STATIC; 554 } 555 } 556 else if (streq (p[0], "auth-user-pass")) 557 { 558 sprintf(buf, "vpn_client%d_userauth", unit); 559 nvram_set(buf, "1"); 560 } 561 else if (streq (p[0], "tls-remote") && p[1]) 562 { 563 sprintf(buf, "vpn_client%d_tlsremote", unit); 564 nvram_set(buf, "1"); 565 sprintf(buf, "vpn_client%d_cn", unit); 566 nvram_set(buf, p[1]); 567 } 568 else if (streq (p[0], "key-direction") && p[1]) 569 { 570 sprintf(buf, "vpn_client%d_hmac", unit); 571 nvram_set(buf, p[1]); 572 } 573 else if (streq (p[0], "crl-verify") && p[1]) 574 { 575 if (p[2] && streq(p[2], "dir")) 576 ;//TODO: not support? 577 return VPN_UPLOAD_NEED_CRL; 578 } 579 else 580 { 581 sprintf(buf, "vpn_client%d_custom", unit); 582 add_custom(buf, p); 583 } 584 return 0; 585} 586 587int 588read_config_file (const char *file, int unit) 589{ 590 FILE *fp; 591 int line_num; 592 char line[OPTION_LINE_SIZE]; 593 char *p[MAX_PARMS]; 594 int ret = 0; 595 596 fp = fopen (file, "r"); 597 if (fp) 598 { 599 line_num = 0; 600 while (fgets(line, sizeof (line), fp)) 601 { 602 int offset = 0; 603 CLEAR (p); 604 ++line_num; 605 /* Ignore UTF-8 BOM at start of stream */ 606 if (line_num == 1 && strncmp (line, "\xEF\xBB\xBF", 3) == 0) 607 offset = 3; 608 if (parse_line (line + offset, p, SIZE (p), line_num)) 609 { 610 bypass_doubledash (&p[0]); 611 check_inline_file_via_fp (fp, p); 612 ret |= add_option (p, line_num, unit); 613 } 614 } 615 fclose (fp); 616 } 617 else 618 { 619 logmessage ("OVPN", "Error opening configuration file"); 620 } 621 622 CLEAR (line); 623 CLEAR (p); 624 625 return ret; 626} 627 628void reset_client_setting(int unit){ 629 char nv[32]; 630 char file_path[128] ={0}; 631 632 sprintf(nv, "vpn_client%d_custom", unit); 633 nvram_set(nv, ""); 634 sprintf(nv, "vpn_client%d_comp", unit); 635 nvram_set(nv, "-1"); 636 sprintf(nv, "vpn_client%d_reneg", unit); 637 nvram_set(nv, "-1"); 638 sprintf(nv, "vpn_client%d_hmac", unit); 639 nvram_set(nv, "-1"); 640 sprintf(nv, "vpn_client%d_retry", unit); 641 nvram_set(nv, "-1"); 642 sprintf(nv, "vpn_client%d_cipher", unit); 643 nvram_set(nv, "default"); 644 sprintf(nv, "vpn_client%d_tlsremote", unit); 645 nvram_set(nv, "0"); 646 sprintf(nv, "vpn_client%d_cn", unit); 647 nvram_set(nv, ""); 648 sprintf(nv, "vpn_client%d_userauth", unit); 649 nvram_set(nv, "0"); 650 sprintf(nv, "vpn_client%d_username", unit); 651 nvram_set(nv, ""); 652 sprintf(nv, "vpn_client%d_password", unit); 653 nvram_set(nv, ""); 654 sprintf(nv, "vpn_crt_client%d_ca", unit); 655 nvram_set(nv, ""); 656#if defined(RTCONFIG_JFFS2) || defined(RTCONFIG_BRCM_NAND_JFFS2) || defined(RTCONFIG_UBIFS) 657 snprintf(file_path, sizeof(file_path) -1, "%s/%s", OVPN_FS_PATH, nv); 658 unlink(file_path); 659#endif 660 sprintf(nv, "vpn_crt_client%d_crt", unit); 661 nvram_set(nv, ""); 662#if defined(RTCONFIG_JFFS2) || defined(RTCONFIG_BRCM_NAND_JFFS2) || defined(RTCONFIG_UBIFS) 663 snprintf(file_path, sizeof(file_path) -1, "%s/%s", OVPN_FS_PATH, nv); 664 unlink(file_path); 665#endif 666 sprintf(nv, "vpn_crt_client%d_key", unit); 667 nvram_set(nv, ""); 668#if defined(RTCONFIG_JFFS2) || defined(RTCONFIG_BRCM_NAND_JFFS2) || defined(RTCONFIG_UBIFS) 669 snprintf(file_path, sizeof(file_path) -1, "%s/%s", OVPN_FS_PATH, nv); 670 unlink(file_path); 671#endif 672 sprintf(nv, "vpn_crt_client%d_static", unit); 673 nvram_set(nv, ""); 674#if defined(RTCONFIG_JFFS2) || defined(RTCONFIG_BRCM_NAND_JFFS2) || defined(RTCONFIG_UBIFS) 675 snprintf(file_path, sizeof(file_path) -1, "%s/%s", OVPN_FS_PATH, nv); 676 unlink(file_path); 677#endif 678 sprintf(nv, "vpn_crt_client%d_crl", unit); 679 nvram_set(nv, ""); 680#if defined(RTCONFIG_JFFS2) || defined(RTCONFIG_BRCM_NAND_JFFS2) || defined(RTCONFIG_UBIFS) 681 snprintf(file_path, sizeof(file_path) -1, "%s/%s", OVPN_FS_PATH, nv); 682 unlink(file_path); 683#endif 684} 685 686void parse_openvpn_status(int unit){ 687 FILE *fpi, *fpo; 688 char buf[512]; 689 char *token; 690 char nv_name[32] = ""; 691 char prefix_vpn[] = "vpn_serverXX_"; 692 693 sprintf(buf, "/etc/openvpn/server%d/status", unit); 694 fpi = fopen(buf, "r"); 695 696 sprintf(buf, "/etc/openvpn/server%d/client_status", unit); 697 fpo = fopen(buf, "w"); 698 699 snprintf(prefix_vpn, sizeof(prefix_vpn), "vpn_server%d_", unit); 700 701 if(fpi && fpo) { 702 while(!feof(fpi)){ 703 CLEAR(buf); 704 if (!fgets(buf, sizeof(buf), fpi)) 705 break; 706 if(!strncmp(buf, "CLIENT_LIST", 11)) { 707 //printf("%s", buf); 708 token = strtok(buf, ","); //CLIENT_LIST 709 token = strtok(NULL, ","); //Common Name 710 token = strtok(NULL, ","); //Real Address 711 if(token) 712 fprintf(fpo, "%s ", token); 713 else 714 fprintf(fpo, "NoRealAddress "); 715 snprintf(nv_name, sizeof(nv_name) -1, "vpn_server%d_if", unit); 716 717 if(nvram_match(strcat_r(prefix_vpn, "if", nv_name), "tap") 718 && nvram_match(strcat_r(prefix_vpn, "dhcp", nv_name), "1")) { 719 fprintf(fpo, "VirtualAddressAssignedByDhcp "); 720 } 721 else { 722 token = strtok(NULL, ","); //Virtual Address 723 if(token) 724 fprintf(fpo, "%s ", token); 725 else 726 fprintf(fpo, "NoVirtualAddress "); 727 } 728 token = strtok(NULL, ","); //Bytes Received 729 token = strtok(NULL, ","); //Bytes Sent 730 token = strtok(NULL, ","); //Connected Since 731 token = strtok(NULL, ","); //Connected Since (time_t) 732 token = strtok(NULL, ","); //Username, include'\n' 733 if(token) 734 fprintf(fpo, "%s", token); 735 else 736 fprintf(fpo, "NoUsername"); 737 } 738 } 739 fclose(fpi); 740 fclose(fpo); 741 } 742} 743