1 /* 2 * Copyright (c) 2007-2012, Vsevolod Stakhov 3 * All rights reserved. 4 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * Redistributions of source code must retain the above copyright notice, this 8 * list of conditions and the following disclaimer. Redistributions in binary form 9 * must reproduce the above copyright notice, this list of conditions and the 10 * following disclaimer in the documentation and/or other materials provided with 11 * the distribution. Neither the name of the author nor the names of its 12 * contributors may be used to endorse or promote products derived from this 13 * software without specific prior written permission. 14 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 %{ 28 29 #include "cfg_file.h" 30 31 #define YYDEBUG 1 32 33 extern struct config_file *cfg; 34 extern int yylineno; 35 extern char *yytext; 36 37 struct condl *cur_conditions; 38 struct dkim_domain_entry *cur_domain; 39 uint8_t cur_flags = 0; 40 41 %} 42 %union 43 { 44 char *string; 45 size_t limit; 46 bucket_t bucket; 47 char flag; 48 unsigned int seconds; 49 unsigned int number; 50 double frac; 51 } 52 53 %token ERROR STRING QUOTEDSTRING FLAG FLOAT 54 %token TEMPDIR LOGFILE PIDFILE CLAMAV SERVERS ERROR_TIME DEAD_TIME MAXERRORS CONNECT_TIMEOUT PORT_TIMEOUT RESULTS_TIMEOUT SPF DCC 55 %token FILENAME REGEXP QUOTE SEMICOLON OBRACE EBRACE COMMA EQSIGN 56 %token BINDSOCK SOCKCRED DOMAIN_STR IPADDR IPNETWORK HOSTPORT NUMBER GREYLISTING WHITELIST TIMEOUT EXPIRE EXPIRE_WHITE 57 %token MAXSIZE SIZELIMIT SECONDS BUCKET USEDCC MEMCACHED PROTOCOL SERVERS_WHITE SERVERS_LIMITS SERVERS_GREY SERVERS_COPY SERVERS_SPAM 58 %token LIMITS LIMIT_TO LIMIT_TO_IP LIMIT_TO_IP_FROM LIMIT_WHITELIST LIMIT_WHITELIST_RCPT LIMIT_BOUNCE_ADDRS LIMIT_BOUNCE_TO LIMIT_BOUNCE_TO_IP 59 %token SPAMD REJECT_MESSAGE SERVERS_ID ID_PREFIX GREY_PREFIX WHITE_PREFIX RSPAMD_METRIC ALSO_CHECK DIFF_DIR CHECK_SYMBOLS SYMBOLS_DIR 60 %token BEANSTALK ID_REGEXP LIFETIME COPY_SERVER GREYLISTED_MESSAGE SPAMD_SOFT_FAIL STRICT_AUTH 61 %token TRACE_SYMBOL TRACE_ADDR WHITELIST_FROM SPAM_HEADER SPAM_HEADER_VALUE SPAMD_GREYLIST EXTENDED_SPAM_HEADERS 62 %token DKIM_SECTION DKIM_KEY DKIM_DOMAIN DKIM_SELECTOR DKIM_HEADER_CANON DKIM_BODY_CANON 63 %token DKIM_SIGN_ALG DKIM_RELAXED DKIM_SIMPLE DKIM_SHA1 DKIM_SHA256 DKIM_AUTH_ONLY COPY_PROBABILITY 64 %token SEND_BEANSTALK_SPAM_EXTRA_DIFF DKIM_FOLD_HEADER SPAMD_RETRY_COUNT SPAMD_RETRY_TIMEOUT SPAMD_TEMPFAIL 65 %token SPAMD_NEVER_REJECT TEMPFILES_MODE USE_REDIS REDIS DKIM_SIGN_NETWORKS OUR_NETWORKS SPAM_BAR_CHAR 66 %token SPAM_NO_AUTH_HEADER PASSWORD DBNAME SPAMD_SETTINGS_ID SPAMD_SPAM_ADD_HEADER 67 %token COPY_FULL COPY_CHANNEL SPAM_CHANNEL ENABLE EQPLUS COMPRESSION DKIM_RSPAMD_SIGN 68 %token EXTENDED_HEADERS_RCPT 69 70 %type <string> STRING 71 %type <string> QUOTEDSTRING 72 %type <string> FILENAME 73 %type <string> REGEXP 74 %type <string> SOCKCRED 75 %type <string> IPADDR IPNETWORK 76 %type <string> HOSTPORT 77 %type <string> ip_net cache_hosts clamav_addr spamd_addr bounce_addr 78 %type <string> DOMAIN_STR 79 %type <limit> SIZELIMIT 80 %type <flag> FLAG 81 %type <bucket> BUCKET; 82 %type <seconds> SECONDS; 83 %type <number> NUMBER; 84 %type <frac> FLOAT; 85 %type <frac> prob_num; 86 %% 87 88 input: 89 empty 90 | command separator input 91 ; 92 93 separator: 94 SEMICOLON 95 | empty 96 ; 97 98 empty: 99 /* %empty */ 100 ; 101 102 command : 103 tempdir 104 | tempfiles_mode 105 | strictauth 106 | pidfile 107 | clamav 108 | spamd 109 | spf 110 | bindsock 111 | maxsize 112 | usedcc 113 | cache 114 | limits 115 | greylisting 116 | whitelist 117 | dkim 118 | use_redis 119 | our_networks 120 ; 121 122 tempdir : 123 TEMPDIR EQSIGN FILENAME { 124 struct stat st; 125 126 if (stat ($3, &st) == -1) { 127 yyerror ("yyparse: cannot stat directory \"%s\": %s", $3, strerror (errno)); 128 YYERROR; 129 } 130 if (!S_ISDIR (st.st_mode)) { 131 yyerror ("yyparse: \"%s\" is not a directory", $3); 132 YYERROR; 133 } 134 135 cfg->temp_dir = $3; 136 } 137 ; 138 139 tempfiles_mode: 140 TEMPFILES_MODE EQSIGN NUMBER { 141 /* 142 * We likely have here decimal number, so we need to treat it as 143 * octal one that means oct -> dec conversion 144 */ 145 int i = 1; 146 cfg->tempfiles_mode = 0; 147 148 while ($3 > 0) { 149 cfg->tempfiles_mode += $3 % 10 * i; 150 i *= 8; 151 $3 /= 10; 152 } 153 } 154 | TEMPFILES_MODE EQSIGN QUOTEDSTRING { 155 char *err_str; 156 157 cfg->tempfiles_mode = strtoul ($3, &err_str, 8); 158 159 if (err_str != NULL && *err_str != '\0') { 160 yyerror ("yyparse: cannot convert \"%s\" to octal number: %s", $3, 161 strerror (errno)); 162 YYERROR; 163 } 164 165 free ($3); 166 } 167 ; 168 169 pidfile : 170 PIDFILE EQSIGN FILENAME { 171 cfg->pid_file = $3; 172 } 173 ; 174 175 strictauth: 176 STRICT_AUTH EQSIGN FLAG { 177 cfg->strict_auth = $3; 178 } 179 ; 180 181 clamav: 182 CLAMAV OBRACE clamavbody EBRACE 183 | CLAMAV OBRACE empty EBRACE 184 ; 185 186 clamavbody: 187 clamavcmd SEMICOLON 188 | clamavbody clamavcmd SEMICOLON 189 ; 190 191 clamavcmd: 192 clamav_servers 193 | clamav_connect_timeout 194 | clamav_port_timeout 195 | clamav_results_timeout 196 | clamav_error_time 197 | clamav_dead_time 198 | clamav_maxerrors 199 | clamav_whitelist 200 ; 201 202 clamav_servers: 203 SERVERS EQSIGN { 204 cfg->clamav_servers_num = 0; 205 } clamav_server 206 | SERVERS EQPLUS clamav_server 207 ; 208 209 clamav_server: 210 clamav_params 211 | clamav_server COMMA clamav_params 212 | empty 213 ; 214 215 clamav_params: 216 clamav_addr { 217 if (!add_clamav_server (cfg, $1)) { 218 yyerror ("yyparse: add_clamav_server"); 219 YYERROR; 220 } 221 free ($1); 222 } 223 ; 224 clamav_addr: 225 STRING { 226 $$ = $1; 227 } 228 | QUOTEDSTRING { 229 $$ = $1; 230 } 231 | IPADDR{ 232 $$ = $1; 233 } 234 | DOMAIN_STR { 235 $$ = $1; 236 } 237 | HOSTPORT { 238 $$ = $1; 239 } 240 | FILENAME { 241 $$ = $1; 242 } 243 ; 244 clamav_error_time: 245 ERROR_TIME EQSIGN NUMBER { 246 cfg->clamav_error_time = $3; 247 } 248 ; 249 clamav_dead_time: 250 DEAD_TIME EQSIGN NUMBER { 251 cfg->clamav_dead_time = $3; 252 } 253 ; 254 clamav_maxerrors: 255 MAXERRORS EQSIGN NUMBER { 256 cfg->clamav_maxerrors = $3; 257 } 258 ; 259 clamav_connect_timeout: 260 CONNECT_TIMEOUT EQSIGN SECONDS { 261 cfg->clamav_connect_timeout = $3; 262 } 263 ; 264 clamav_port_timeout: 265 PORT_TIMEOUT EQSIGN SECONDS { 266 cfg->clamav_port_timeout = $3; 267 } 268 ; 269 clamav_results_timeout: 270 RESULTS_TIMEOUT EQSIGN SECONDS { 271 cfg->clamav_results_timeout = $3; 272 } 273 ; 274 clamav_whitelist: 275 WHITELIST EQSIGN clamav_ip_list 276 ; 277 278 clamav_ip_list: 279 clamav_ip 280 | clamav_ip_list COMMA clamav_ip 281 ; 282 283 clamav_ip: 284 ip_net { 285 if (add_ip_radix (&cfg->clamav_whitelist, $1) == 0) { 286 YYERROR; 287 } 288 } 289 ; 290 291 spamd: 292 SPAMD OBRACE spamdbody EBRACE 293 | SPAMD OBRACE empty EBRACE 294 ; 295 296 spamdbody: 297 spamdcmd SEMICOLON 298 | spamdbody spamdcmd SEMICOLON 299 ; 300 301 spamdcmd: 302 spamd_servers 303 | spamd_connect_timeout 304 | spamd_results_timeout 305 | spamd_error_time 306 | spamd_dead_time 307 | spamd_maxerrors 308 | spamd_reject_message 309 | spamd_whitelist 310 | extra_spamd_servers 311 | spamd_rspamd_metric 312 | diff_dir 313 | symbols_dir 314 | check_symbols 315 | spamd_soft_fail 316 | trace_symbol 317 | trace_addr 318 | spamd_spam_add_header 319 | spamd_spam_header 320 | spamd_spam_header_value 321 | spamd_greylist 322 | extended_spam_headers 323 | spamd_retry_count 324 | spamd_retry_timeout 325 | spamd_tempfail 326 | spamd_never_reject 327 | spam_bar_char 328 | spam_no_auth_header 329 | spamd_settings_id 330 | spamd_compression 331 | spamd_extended_rcpts 332 ; 333 334 diff_dir : 335 DIFF_DIR EQSIGN FILENAME { 336 struct stat st; 337 338 if (stat ($3, &st) == -1) { 339 yyerror ("yyparse: cannot stat directory \"%s\": %s", $3, strerror (errno)); 340 YYERROR; 341 } 342 if (!S_ISDIR (st.st_mode)) { 343 yyerror ("yyparse: \"%s\" is not a directory", $3); 344 YYERROR; 345 } 346 347 if (cfg->diff_dir) { 348 free (cfg->diff_dir); 349 } 350 351 cfg->diff_dir = $3; 352 } 353 ; 354 symbols_dir: 355 SYMBOLS_DIR EQSIGN FILENAME { 356 struct stat st; 357 358 if (stat ($3, &st) == -1) { 359 yyerror ("yyparse: cannot stat directory \"%s\": %s", $3, strerror (errno)); 360 YYERROR; 361 } 362 if (!S_ISDIR (st.st_mode)) { 363 yyerror ("yyparse: \"%s\" is not a directory", $3); 364 YYERROR; 365 } 366 367 if (cfg->symbols_dir) { 368 free (cfg->symbols_dir); 369 } 370 371 cfg->symbols_dir = $3; 372 } 373 ; 374 375 check_symbols: 376 CHECK_SYMBOLS EQSIGN QUOTEDSTRING { 377 free (cfg->check_symbols); 378 cfg->check_symbols = $3; 379 } 380 ; 381 382 383 spamd_servers: 384 SERVERS EQSIGN { 385 cfg->spamd_servers_num = 0; 386 } 387 spamd_server 388 | SERVERS EQPLUS spamd_server 389 ; 390 391 spamd_server: 392 spamd_params 393 | spamd_server COMMA spamd_params 394 | empty 395 ; 396 397 spamd_params: 398 spamd_addr { 399 if (!add_spamd_server (cfg, $1, 0)) { 400 yyerror ("yyparse: add_spamd_server"); 401 YYERROR; 402 } 403 free ($1); 404 } 405 ; 406 407 extra_spamd_servers: 408 ALSO_CHECK EQSIGN extra_spamd_server 409 ; 410 411 extra_spamd_server: 412 extra_spamd_params 413 | extra_spamd_server COMMA extra_spamd_params 414 ; 415 416 extra_spamd_params: 417 spamd_addr { 418 if (!add_spamd_server (cfg, $1, 1)) { 419 yyerror ("yyparse: add_spamd_server"); 420 YYERROR; 421 } 422 free ($1); 423 } 424 ; 425 426 spamd_addr: 427 STRING { 428 $$ = $1; 429 } 430 | QUOTEDSTRING { 431 $$ = $1; 432 } 433 | IPADDR{ 434 $$ = $1; 435 } 436 | DOMAIN_STR { 437 $$ = $1; 438 } 439 | HOSTPORT { 440 $$ = $1; 441 } 442 | FILENAME { 443 $$ = $1; 444 } 445 ; 446 spamd_error_time: 447 ERROR_TIME EQSIGN NUMBER { 448 cfg->spamd_error_time = $3; 449 } 450 ; 451 spamd_dead_time: 452 DEAD_TIME EQSIGN NUMBER { 453 cfg->spamd_dead_time = $3; 454 } 455 ; 456 spamd_maxerrors: 457 MAXERRORS EQSIGN NUMBER { 458 cfg->spamd_maxerrors = $3; 459 } 460 ; 461 spamd_connect_timeout: 462 CONNECT_TIMEOUT EQSIGN SECONDS { 463 cfg->spamd_connect_timeout = $3; 464 } 465 ; 466 spamd_results_timeout: 467 RESULTS_TIMEOUT EQSIGN SECONDS { 468 cfg->spamd_results_timeout = $3; 469 } 470 ; 471 spamd_reject_message: 472 REJECT_MESSAGE EQSIGN QUOTEDSTRING { 473 free (cfg->spamd_reject_message); 474 cfg->spamd_reject_message = $3; 475 } 476 ; 477 spamd_whitelist: 478 WHITELIST EQSIGN { 479 if (cfg->spamd_whitelist) { 480 radix_destroy_compressed (cfg->spamd_whitelist); 481 cfg->spamd_whitelist = NULL; 482 } 483 } spamd_ip_list 484 | WHITELIST EQPLUS spamd_ip_list 485 ; 486 487 spamd_ip_list: 488 spamd_ip 489 | spamd_ip_list COMMA spamd_ip 490 | empty 491 ; 492 493 spamd_ip: 494 ip_net { 495 if (add_ip_radix (&cfg->spamd_whitelist, $1) == 0) { 496 YYERROR; 497 } 498 } 499 ; 500 501 spamd_rspamd_metric: 502 RSPAMD_METRIC EQSIGN QUOTEDSTRING { 503 free (cfg->rspamd_metric); 504 cfg->rspamd_metric = $3; 505 } 506 ; 507 508 spamd_soft_fail: 509 SPAMD_SOFT_FAIL EQSIGN FLAG { 510 cfg->spamd_soft_fail = $3; 511 } 512 ; 513 514 spamd_never_reject: 515 SPAMD_NEVER_REJECT EQSIGN FLAG { 516 cfg->spamd_never_reject = $3; 517 } 518 ; 519 520 spamd_spam_add_header: 521 SPAMD_SPAM_ADD_HEADER EQSIGN FLAG { 522 cfg->spamd_spam_add_header = $3; 523 } 524 ; 525 526 extended_spam_headers: 527 EXTENDED_SPAM_HEADERS EQSIGN FLAG { 528 cfg->extended_spam_headers = $3; 529 } 530 ; 531 532 spamd_greylist: 533 SPAMD_GREYLIST EQSIGN FLAG { 534 cfg->spamd_greylist = $3; 535 } 536 ; 537 538 spamd_spam_header: 539 SPAM_HEADER EQSIGN QUOTEDSTRING { 540 free (cfg->spam_header); 541 cfg->spam_header = $3; 542 } 543 ; 544 545 spamd_spam_header_value: 546 SPAM_HEADER_VALUE EQSIGN QUOTEDSTRING { 547 free (cfg->spam_header_value); 548 cfg->spam_header_value = $3; 549 } 550 ; 551 552 trace_symbol: 553 TRACE_SYMBOL EQSIGN QUOTEDSTRING { 554 free (cfg->trace_symbol); 555 cfg->trace_symbol = $3; 556 } 557 ; 558 559 trace_addr: 560 TRACE_ADDR EQSIGN QUOTEDSTRING { 561 free (cfg->trace_addr); 562 cfg->trace_addr = $3; 563 } 564 ; 565 spamd_retry_timeout: 566 SPAMD_RETRY_TIMEOUT EQSIGN SECONDS { 567 cfg->spamd_retry_timeout = $3; 568 } 569 ; 570 spamd_retry_count: 571 SPAMD_RETRY_COUNT EQSIGN NUMBER { 572 cfg->spamd_retry_count = $3; 573 } 574 ; 575 spamd_tempfail: 576 SPAMD_TEMPFAIL EQSIGN FLAG { 577 cfg->spamd_temp_fail = $3; 578 } 579 ; 580 spam_bar_char: 581 SPAM_BAR_CHAR EQSIGN QUOTEDSTRING { 582 free (cfg->spam_bar_char); 583 cfg->spam_bar_char = $3; 584 } 585 ; 586 spam_no_auth_header: 587 SPAM_NO_AUTH_HEADER EQSIGN FLAG { 588 cfg->spam_no_auth_header = $3; 589 } 590 ; 591 592 spamd_settings_id: 593 SPAMD_SETTINGS_ID EQSIGN QUOTEDSTRING { 594 free (cfg->spamd_settings_id); 595 cfg->spamd_settings_id = $3; 596 } 597 ; 598 599 spamd_compression: 600 COMPRESSION EQSIGN FLAG { 601 cfg->compression_enable = $3; 602 } 603 ; 604 605 spamd_extended_rcpts: 606 EXTENDED_HEADERS_RCPT EQSIGN { 607 clear_rcpt_whitelist (&cfg->extended_rcpts); 608 } extended_rcpt_list 609 | EXTENDED_HEADERS_RCPT EQPLUS extended_rcpt_list 610 ; 611 extended_rcpt_list: 612 STRING { 613 add_rcpt_whitelist (&cfg->extended_rcpts, $1); 614 } 615 | QUOTEDSTRING { 616 add_rcpt_whitelist (&cfg->extended_rcpts, $1); 617 } 618 | extended_rcpt_list COMMA STRING { 619 add_rcpt_whitelist (&cfg->extended_rcpts, $3); 620 } 621 | extended_rcpt_list COMMA QUOTEDSTRING { 622 add_rcpt_whitelist (&cfg->extended_rcpts, $3); 623 } 624 | empty 625 ; 626 627 spf: 628 SPF EQSIGN spf_params 629 ; 630 spf_params: 631 spf_domain 632 | spf_params COMMA spf_domain 633 ; 634 635 spf_domain: 636 DOMAIN_STR { 637 yywarn ("spf support is removed from rmilter"); 638 } 639 | STRING { 640 yywarn ("spf support is removed from rmilter"); 641 } 642 | QUOTEDSTRING { 643 yywarn ("spf support is removed from rmilter"); 644 } 645 ; 646 647 bindsock: 648 BINDSOCK EQSIGN SOCKCRED { 649 cfg->sock_cred = $3; 650 } 651 | BINDSOCK EQSIGN QUOTEDSTRING { 652 cfg->sock_cred = $3; 653 } 654 ; 655 656 657 maxsize: 658 MAXSIZE EQSIGN SIZELIMIT { 659 cfg->sizelimit = $3; 660 } 661 | MAXSIZE EQSIGN NUMBER { 662 cfg->sizelimit = $3; 663 } 664 ; 665 usedcc: 666 USEDCC EQSIGN FLAG { 667 cfg->use_dcc = $3; 668 } 669 ; 670 671 greylisting: 672 GREYLISTING OBRACE greylistingbody EBRACE 673 | GREYLISTING OBRACE empty EBRACE 674 ; 675 676 greylistingbody: 677 greylistingcmd SEMICOLON 678 | greylistingbody greylistingcmd SEMICOLON 679 ; 680 681 greylistingcmd: 682 greylisting_whitelist 683 | greylisting_timeout 684 | greylisting_expire 685 | greylisting_whitelist_expire 686 | greylisted_message 687 | greylisting_enable 688 ; 689 690 greylisting_timeout: 691 TIMEOUT EQSIGN SECONDS { 692 /* This value is in seconds, not in milliseconds */ 693 cfg->greylisting_timeout = $3 / 1000; 694 } 695 ; 696 697 greylisting_expire: 698 EXPIRE EQSIGN SECONDS { 699 /* This value is in seconds, not in milliseconds */ 700 cfg->greylisting_expire = $3 / 1000; 701 } 702 ; 703 704 greylisting_whitelist_expire: 705 EXPIRE_WHITE EQSIGN SECONDS { 706 /* This value is in seconds, not in milliseconds */ 707 cfg->whitelisting_expire = $3 / 1000; 708 } 709 ; 710 711 greylisting_whitelist: 712 WHITELIST EQSIGN { 713 if (cfg->grey_whitelist_tree) { 714 radix_destroy_compressed (cfg->grey_whitelist_tree); 715 cfg->grey_whitelist_tree = NULL; 716 } 717 } 718 greylisting_ip_list 719 | WHITELIST EQPLUS greylisting_ip_list 720 ; 721 722 greylisting_ip_list: 723 greylisting_ip 724 | greylisting_ip_list COMMA greylisting_ip 725 ; 726 727 greylisting_ip: 728 ip_net { 729 if (add_ip_radix (&cfg->grey_whitelist_tree, $1) == 0) { 730 YYERROR; 731 } 732 } 733 ; 734 735 greylisted_message: 736 GREYLISTED_MESSAGE EQSIGN QUOTEDSTRING { 737 free (cfg->greylisted_message); 738 cfg->greylisted_message = $3; 739 } 740 ; 741 742 greylisting_enable: 743 ENABLE EQSIGN FLAG { 744 cfg->greylisting_enable = $3; 745 } 746 ; 747 748 ip_net: 749 IPADDR 750 | IPNETWORK 751 | QUOTEDSTRING 752 ; 753 754 cache: 755 MEMCACHED OBRACE cachebody EBRACE 756 | REDIS { cfg->cache_use_redis = 1; } OBRACE cachebody EBRACE 757 ; 758 759 cachebody: 760 cahcebody_commands 761 | empty 762 ; 763 cahcebody_commands: 764 cachecmd SEMICOLON 765 | cahcebody_commands cachecmd SEMICOLON 766 ; 767 768 cachecmd: 769 cache_grey_servers 770 | cache_white_servers 771 | cache_limits_servers 772 | cache_id_servers 773 | cache_spam_servers 774 | cache_copy_servers 775 | cache_connect_timeout 776 | cache_error_time 777 | cache_dead_time 778 | cache_maxerrors 779 | cache_protocol 780 | cache_id_prefix 781 | cache_grey_prefix 782 | cache_white_prefix 783 | cache_password 784 | cache_dbname 785 | cache_spam_channel 786 | cache_copy_channel 787 | cache_copy_probability 788 ; 789 790 cache_grey_servers: 791 SERVERS_GREY EQSIGN 792 { 793 cfg->cache_servers_grey_num = 0; 794 } 795 cache_grey_server 796 | SERVERS_GREY EQPLUS cache_grey_server 797 ; 798 799 cache_grey_server: 800 cache_grey_params 801 | cache_grey_server COMMA cache_grey_params 802 | empty 803 ; 804 805 cache_grey_params: 806 OBRACE cache_hosts COMMA cache_hosts EBRACE { 807 if (!add_cache_server (cfg, $2, $4, CACHE_SERVER_GREY)) { 808 yyerror ("yyparse: add_cache_server"); 809 YYERROR; 810 } 811 free ($2); 812 free ($4); 813 } 814 | cache_hosts { 815 if (!add_cache_server (cfg, $1, NULL, CACHE_SERVER_GREY)) { 816 yyerror ("yyparse: add_cache_server"); 817 YYERROR; 818 } 819 free ($1); 820 } 821 ; 822 823 cache_white_servers: 824 SERVERS_WHITE EQSIGN 825 { 826 cfg->cache_servers_white_num = 0; 827 } 828 cache_white_server 829 | SERVERS_WHITE EQPLUS cache_white_server 830 ; 831 832 cache_white_server: 833 cache_white_params 834 | cache_white_server COMMA cache_white_params 835 ; 836 837 cache_white_params: 838 OBRACE cache_hosts COMMA cache_hosts EBRACE { 839 if (!add_cache_server (cfg, $2, $4, CACHE_SERVER_WHITE)) { 840 yyerror ("yyparse: add_cache_server"); 841 YYERROR; 842 } 843 free ($2); 844 free ($4); 845 } 846 | cache_hosts { 847 if (!add_cache_server (cfg, $1, NULL, CACHE_SERVER_WHITE)) { 848 yyerror ("yyparse: add_cache_server"); 849 YYERROR; 850 } 851 free ($1); 852 } 853 ; 854 855 cache_limits_servers: 856 SERVERS_LIMITS EQSIGN 857 { 858 cfg->cache_servers_limits_num = 0; 859 } 860 cache_limits_server 861 | SERVERS_LIMITS EQPLUS cache_limits_server 862 ; 863 864 cache_limits_server: 865 cache_limits_params 866 | cache_limits_server COMMA cache_limits_params 867 | empty 868 ; 869 870 cache_limits_params: 871 cache_hosts { 872 if (!add_cache_server (cfg, $1, NULL, CACHE_SERVER_LIMITS)) { 873 yyerror ("yyparse: add_cache_server"); 874 YYERROR; 875 } 876 free ($1); 877 } 878 ; 879 880 cache_id_servers: 881 SERVERS_ID EQSIGN 882 { 883 cfg->cache_servers_id_num = 0; 884 } 885 cache_id_server 886 | SERVERS_ID EQPLUS cache_id_server 887 ; 888 889 cache_id_server: 890 cache_id_params 891 | cache_id_server COMMA cache_id_params 892 | empty 893 ; 894 895 cache_id_params: 896 cache_hosts { 897 if (!add_cache_server (cfg, $1, NULL, CACHE_SERVER_ID)) { 898 yyerror ("yyparse: add_cache_server"); 899 YYERROR; 900 } 901 free ($1); 902 } 903 ; 904 905 cache_copy_servers: 906 SERVERS_COPY EQSIGN 907 { 908 cfg->cache_servers_copy_num = 0; 909 } 910 cache_copy_server 911 | SERVERS_COPY EQPLUS cache_copy_server 912 ; 913 914 cache_copy_server: 915 cache_copy_params 916 | cache_copy_server COMMA cache_copy_params 917 | empty 918 ; 919 920 cache_copy_params: 921 cache_hosts { 922 if (!add_cache_server (cfg, $1, NULL, CACHE_SERVER_COPY)) { 923 yyerror ("yyparse: add_cache_server"); 924 YYERROR; 925 } 926 free ($1); 927 } 928 ; 929 930 cache_spam_servers: 931 SERVERS_SPAM EQSIGN 932 { 933 cfg->cache_servers_spam_num = 0; 934 } 935 cache_spam_server 936 | SERVERS_SPAM EQPLUS cache_spam_server 937 ; 938 939 cache_spam_server: 940 cache_spam_params 941 | cache_spam_server COMMA cache_spam_params 942 | empty 943 ; 944 945 cache_spam_params: 946 cache_hosts { 947 if (!add_cache_server (cfg, $1, NULL, CACHE_SERVER_SPAM)) { 948 yyerror ("yyparse: add_cache_server"); 949 YYERROR; 950 } 951 free ($1); 952 } 953 ; 954 955 cache_hosts: 956 STRING 957 | QUOTEDSTRING 958 | IPADDR 959 | DOMAIN_STR 960 | HOSTPORT 961 ; 962 cache_error_time: 963 ERROR_TIME EQSIGN NUMBER { 964 cfg->cache_error_time = $3; 965 } 966 ; 967 cache_dead_time: 968 DEAD_TIME EQSIGN NUMBER { 969 cfg->cache_dead_time = $3; 970 } 971 ; 972 cache_maxerrors: 973 MAXERRORS EQSIGN NUMBER { 974 cfg->cache_maxerrors = $3; 975 } 976 ; 977 cache_connect_timeout: 978 CONNECT_TIMEOUT EQSIGN SECONDS { 979 cfg->cache_connect_timeout = $3; 980 } 981 ; 982 983 cache_protocol: 984 PROTOCOL EQSIGN STRING { 985 /* Do nothing now*/ 986 } 987 ; 988 cache_id_prefix: 989 ID_PREFIX EQSIGN QUOTEDSTRING { 990 free (cfg->id_prefix); 991 cfg->id_prefix = $3; 992 } 993 ; 994 995 cache_grey_prefix: 996 GREY_PREFIX EQSIGN QUOTEDSTRING { 997 free (cfg->grey_prefix); 998 cfg->grey_prefix = $3; 999 } 1000 ; 1001 1002 cache_white_prefix: 1003 WHITE_PREFIX EQSIGN QUOTEDSTRING { 1004 free (cfg->white_prefix); 1005 cfg->white_prefix = $3; 1006 } 1007 ; 1008 1009 cache_password: 1010 PASSWORD EQSIGN QUOTEDSTRING { 1011 free (cfg->cache_password); 1012 cfg->cache_password = $3; 1013 } 1014 ; 1015 1016 cache_dbname: 1017 DBNAME EQSIGN QUOTEDSTRING { 1018 free (cfg->cache_dbname); 1019 cfg->cache_dbname = $3; 1020 } 1021 ; 1022 1023 cache_copy_channel: 1024 COPY_CHANNEL EQSIGN QUOTEDSTRING { 1025 free (cfg->cache_copy_channel); 1026 cfg->cache_copy_channel = $3; 1027 } 1028 ; 1029 1030 cache_copy_probability: 1031 COPY_PROBABILITY EQSIGN prob_num { 1032 if ($3 < 0) { 1033 YYERROR; 1034 } 1035 if ($3 > 1.0) { 1036 if ($3 > 100.0) { 1037 YYERROR; 1038 } 1039 cfg->cache_copy_prob = $3 / 100.0; 1040 } 1041 else { 1042 cfg->cache_copy_prob = $3; 1043 } 1044 } 1045 ; 1046 prob_num: 1047 NUMBER { $$ = (double)$1; } 1048 | FLOAT 1049 ; 1050 cache_spam_channel: 1051 SPAM_CHANNEL EQSIGN QUOTEDSTRING { 1052 free (cfg->cache_spam_channel); 1053 cfg->cache_spam_channel = $3; 1054 } 1055 ; 1056 1057 limits: 1058 LIMITS OBRACE limitsbody EBRACE 1059 | LIMITS OBRACE empty EBRACE 1060 ; 1061 1062 limitsbody: 1063 limitcmd SEMICOLON 1064 | limitsbody limitcmd SEMICOLON 1065 ; 1066 limitcmd: 1067 limit_to 1068 | limit_to_ip 1069 | limit_to_ip_from 1070 | limit_whitelist 1071 | limit_whitelist_rcpt 1072 | limit_bounce_addrs 1073 | limit_bounce_to 1074 | limit_bounce_to_ip 1075 | limit_enable 1076 ; 1077 1078 limit_to: 1079 LIMIT_TO EQSIGN BUCKET { 1080 cfg->limit_to.burst = $3.burst; 1081 cfg->limit_to.rate = $3.rate; 1082 } 1083 ; 1084 limit_to_ip: 1085 LIMIT_TO_IP EQSIGN BUCKET { 1086 cfg->limit_to_ip.burst = $3.burst; 1087 cfg->limit_to_ip.rate = $3.rate; 1088 } 1089 ; 1090 limit_to_ip_from: 1091 LIMIT_TO_IP_FROM EQSIGN BUCKET { 1092 cfg->limit_to_ip_from.burst = $3.burst; 1093 cfg->limit_to_ip_from.rate = $3.rate; 1094 } 1095 ; 1096 limit_whitelist: 1097 LIMIT_WHITELIST EQSIGN { 1098 if (cfg->limit_whitelist_tree) { 1099 radix_destroy_compressed (cfg->limit_whitelist_tree); 1100 cfg->limit_whitelist_tree = NULL; 1101 } 1102 } 1103 whitelist_ip_list 1104 | LIMIT_WHITELIST EQPLUS whitelist_ip_list 1105 ; 1106 whitelist_ip_list: 1107 ip_net { 1108 if (add_ip_radix (&cfg->limit_whitelist_tree, $1) == 0) { 1109 YYERROR; 1110 } 1111 } 1112 | whitelist_ip_list COMMA ip_net { 1113 if (add_ip_radix (&cfg->limit_whitelist_tree, $3) == 0) { 1114 YYERROR; 1115 } 1116 } 1117 | empty 1118 ; 1119 1120 limit_whitelist_rcpt: 1121 LIMIT_WHITELIST_RCPT EQSIGN { 1122 clear_rcpt_whitelist (&cfg->wlist_rcpt_limit); 1123 } whitelist_rcpt_list 1124 | LIMIT_WHITELIST_RCPT EQPLUS whitelist_rcpt_list 1125 ; 1126 whitelist_rcpt_list: 1127 STRING { 1128 add_rcpt_whitelist (&cfg->wlist_rcpt_limit, $1); 1129 } 1130 | QUOTEDSTRING { 1131 add_rcpt_whitelist (&cfg->wlist_rcpt_limit, $1); 1132 } 1133 | whitelist_rcpt_list COMMA STRING { 1134 add_rcpt_whitelist (&cfg->wlist_rcpt_limit, $3); 1135 } 1136 | whitelist_rcpt_list COMMA QUOTEDSTRING { 1137 add_rcpt_whitelist (&cfg->wlist_rcpt_limit, $3); 1138 } 1139 | empty 1140 ; 1141 1142 limit_bounce_addrs: 1143 LIMIT_BOUNCE_ADDRS EQSIGN { 1144 struct addr_list_entry *t, *tmp; 1145 1146 HASH_ITER (hh, cfg->bounce_addrs, t, tmp) { 1147 HASH_DEL (cfg->bounce_addrs, t); 1148 free (t->addr); 1149 free (t); 1150 } 1151 } bounce_addr_list 1152 | LIMIT_BOUNCE_ADDRS EQPLUS bounce_addr_list 1153 ; 1154 bounce_addr_list: 1155 bounce_addr { 1156 struct addr_list_entry *t; 1157 t = calloc (1, sizeof (struct addr_list_entry)); 1158 t->addr = strdup ($1); 1159 t->len = strlen (t->addr); 1160 HASH_ADD_KEYPTR(hh, cfg->bounce_addrs, t->addr, t->len, t); 1161 } 1162 | bounce_addr_list COMMA bounce_addr { 1163 struct addr_list_entry *t; 1164 t = calloc (1, sizeof (struct addr_list_entry)); 1165 t->addr = strdup ($3); 1166 t->len = strlen (t->addr); 1167 HASH_ADD_KEYPTR(hh, cfg->bounce_addrs, t->addr, t->len, t); 1168 } 1169 | empty 1170 ; 1171 1172 bounce_addr: 1173 STRING 1174 | QUOTEDSTRING 1175 1176 limit_bounce_to: 1177 LIMIT_BOUNCE_TO EQSIGN BUCKET { 1178 cfg->limit_bounce_to.burst = $3.burst; 1179 cfg->limit_bounce_to.rate = $3.rate; 1180 } 1181 ; 1182 1183 limit_bounce_to_ip: 1184 LIMIT_BOUNCE_TO_IP EQSIGN BUCKET { 1185 cfg->limit_bounce_to_ip.burst = $3.burst; 1186 cfg->limit_bounce_to_ip.rate = $3.rate; 1187 } 1188 ; 1189 1190 limit_enable: 1191 ENABLE EQSIGN FLAG { 1192 cfg->ratelimit_enable = $3; 1193 } 1194 ; 1195 1196 whitelist: 1197 WHITELIST EQSIGN { 1198 clear_rcpt_whitelist (&cfg->wlist_rcpt_global); 1199 } whitelist_list 1200 | WHITELIST EQPLUS whitelist_list 1201 ; 1202 whitelist_list: 1203 STRING { 1204 add_rcpt_whitelist (&cfg->wlist_rcpt_global, $1); 1205 } 1206 | QUOTEDSTRING { 1207 add_rcpt_whitelist (&cfg->wlist_rcpt_global, $1); 1208 } 1209 | whitelist_list COMMA STRING { 1210 add_rcpt_whitelist (&cfg->wlist_rcpt_global, $3); 1211 } 1212 | whitelist_list COMMA QUOTEDSTRING { 1213 add_rcpt_whitelist (&cfg->wlist_rcpt_global, $3); 1214 } 1215 | empty 1216 ; 1217 1218 1219 dkim: 1220 DKIM_SECTION OBRACE dkimbody EBRACE 1221 | DKIM_SECTION OBRACE empty EBRACE 1222 ; 1223 1224 dkimbody: 1225 dkimcmd SEMICOLON 1226 | dkimbody dkimcmd SEMICOLON 1227 ; 1228 1229 dkimcmd: 1230 dkim_key 1231 | dkim_domain 1232 | dkim_header_canon 1233 | dkim_body_canon 1234 | dkim_sign_alg 1235 | dkim_auth_only 1236 | dkim_fold_header 1237 | dkim_sign_networks 1238 | dkim_enable 1239 | dkim_rspamd_sign 1240 ; 1241 1242 dkim_domain: 1243 DKIM_DOMAIN OBRACE dkim_domain_body EBRACE { 1244 if (cur_domain == NULL || cur_domain->domain == NULL || 1245 cur_domain->selector == NULL) { 1246 yyerror ("yyparse: incomplete dkim definition"); 1247 YYERROR; 1248 } 1249 if (!cur_domain->is_loaded) { 1250 /* Assume it as wildcard domain */ 1251 cur_domain->is_wildcard = 1; 1252 } 1253 1254 1255 rmilter_str_lc (cur_domain->domain, strlen (cur_domain->domain)); 1256 HASH_ADD_KEYPTR (hh, cfg->dkim_domains, cur_domain->domain, 1257 strlen (cur_domain->domain), cur_domain); 1258 cur_domain = NULL; 1259 } 1260 ; 1261 1262 dkim_domain_body: 1263 dkim_domain_cmd SEMICOLON 1264 | dkim_domain_body dkim_domain_cmd SEMICOLON 1265 ; 1266 1267 dkim_domain_cmd: 1268 dkim_key 1269 | dkim_domain 1270 | dkim_selector 1271 ; 1272 1273 dkim_key: 1274 DKIM_KEY EQSIGN FILENAME { 1275 struct stat st; 1276 int fd; 1277 if (cur_domain == NULL) { 1278 cur_domain = malloc (sizeof (struct dkim_domain_entry)); 1279 memset (cur_domain, 0, sizeof (struct dkim_domain_entry)); 1280 } 1281 if (stat ($3, &st) != -1 && S_ISREG (st.st_mode)) { 1282 cur_domain->keylen = st.st_size; 1283 if ((fd = open ($3, O_RDONLY)) != -1) { 1284 if ((cur_domain->key = mmap (NULL, cur_domain->keylen, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { 1285 yyerror ("yyparse: cannot mmap: %s, %s", $3, strerror (errno)); 1286 close (fd); 1287 YYERROR; 1288 } 1289 else { 1290 cur_domain->is_loaded = 1; 1291 } 1292 close (fd); 1293 } 1294 else { 1295 yyerror ("yyparse: cannot open: %s, %s", $3, strerror (errno)); 1296 YYERROR; 1297 } 1298 } 1299 cur_domain->keyfile = strdup ($3); 1300 } 1301 | DKIM_KEY EQSIGN QUOTEDSTRING { 1302 struct stat st; 1303 int fd; 1304 if (cur_domain == NULL) { 1305 cur_domain = malloc (sizeof (struct dkim_domain_entry)); 1306 memset (cur_domain, 0, sizeof (struct dkim_domain_entry)); 1307 } 1308 if (stat ($3, &st) != -1 && S_ISREG (st.st_mode)) { 1309 cur_domain->keylen = st.st_size; 1310 if ((fd = open ($3, O_RDONLY)) != -1) { 1311 if ((cur_domain->key = mmap (NULL, cur_domain->keylen, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { 1312 yyerror ("yyparse: cannot mmap: %s, %s", $3, strerror (errno)); 1313 close (fd); 1314 YYERROR; 1315 } 1316 else { 1317 cur_domain->is_loaded = 1; 1318 } 1319 close (fd); 1320 } 1321 else { 1322 yyerror ("yyparse: cannot open: %s, %s", $3, strerror (errno)); 1323 YYERROR; 1324 } 1325 } 1326 cur_domain->keyfile = strdup ($3); 1327 } 1328 ; 1329 1330 dkim_domain: 1331 DKIM_DOMAIN EQSIGN QUOTEDSTRING { 1332 1333 if (cur_domain == NULL) { 1334 cur_domain = malloc (sizeof (struct dkim_domain_entry)); 1335 memset (cur_domain, 0, sizeof (struct dkim_domain_entry)); 1336 } 1337 else { 1338 free (cur_domain->domain); 1339 } 1340 1341 cur_domain->domain = $3; 1342 } 1343 ; 1344 1345 dkim_selector: 1346 DKIM_SELECTOR EQSIGN QUOTEDSTRING { 1347 1348 if (cur_domain == NULL) { 1349 cur_domain = malloc (sizeof (struct dkim_domain_entry)); 1350 memset (cur_domain, 0, sizeof (struct dkim_domain_entry)); 1351 } 1352 else { 1353 free (cur_domain->selector); 1354 } 1355 cur_domain->selector = $3; 1356 } 1357 ; 1358 1359 dkim_header_canon: 1360 DKIM_HEADER_CANON EQSIGN DKIM_SIMPLE { 1361 cfg->dkim_relaxed_header = 0; 1362 } 1363 | DKIM_HEADER_CANON EQSIGN DKIM_RELAXED { 1364 cfg->dkim_relaxed_header = 1; 1365 } 1366 ; 1367 1368 dkim_body_canon: 1369 DKIM_BODY_CANON EQSIGN DKIM_SIMPLE { 1370 cfg->dkim_relaxed_body = 0; 1371 } 1372 | DKIM_BODY_CANON EQSIGN DKIM_RELAXED { 1373 cfg->dkim_relaxed_body = 1; 1374 } 1375 ; 1376 1377 dkim_sign_alg: 1378 DKIM_SIGN_ALG EQSIGN DKIM_SHA1 { 1379 cfg->dkim_sign_sha256 = 0; 1380 } 1381 | DKIM_SIGN_ALG EQSIGN DKIM_SHA256 { 1382 cfg->dkim_sign_sha256 = 1; 1383 } 1384 ; 1385 1386 dkim_auth_only: 1387 DKIM_AUTH_ONLY EQSIGN FLAG { 1388 cfg->dkim_auth_only = $3; 1389 } 1390 ; 1391 1392 dkim_fold_header: 1393 DKIM_FOLD_HEADER EQSIGN FLAG { 1394 cfg->dkim_fold_header = $3; 1395 } 1396 ; 1397 dkim_sign_networks: 1398 DKIM_SIGN_NETWORKS EQSIGN { 1399 if (cfg->dkim_ip_tree) { 1400 radix_destroy_compressed (cfg->dkim_ip_tree); 1401 cfg->dkim_ip_tree = NULL; 1402 } 1403 } dkim_ip_list 1404 | DKIM_SIGN_NETWORKS EQPLUS dkim_ip_list 1405 ; 1406 dkim_ip_list: 1407 ip_net { 1408 if (add_ip_radix (&cfg->dkim_ip_tree, $1) == 0) { 1409 YYERROR; 1410 } 1411 } 1412 | dkim_ip_list COMMA ip_net { 1413 if (add_ip_radix (&cfg->dkim_ip_tree, $3) == 0) { 1414 YYERROR; 1415 } 1416 } 1417 | empty 1418 ; 1419 1420 dkim_enable: 1421 ENABLE EQSIGN FLAG { 1422 cfg->dkim_enable = $3; 1423 } 1424 ; 1425 1426 dkim_rspamd_sign: 1427 DKIM_RSPAMD_SIGN EQSIGN FLAG { 1428 cfg->rspamd_dkim_sign = $3; 1429 } 1430 ; 1431 1432 use_redis: 1433 USE_REDIS EQSIGN FLAG { 1434 cfg->cache_use_redis = $3; 1435 } 1436 ; 1437 1438 our_networks: 1439 OUR_NETWORKS EQSIGN { 1440 if (cfg->our_networks) { 1441 radix_destroy_compressed (cfg->our_networks); 1442 cfg->our_networks = NULL; 1443 } 1444 }our_networks_list 1445 | OUR_NETWORKS EQPLUS our_networks_list 1446 ; 1447 1448 our_networks_list: 1449 our_networks_elt 1450 | our_networks_list COMMA our_networks_elt 1451 | empty 1452 ; 1453 1454 our_networks_elt: 1455 ip_net { 1456 if (add_ip_radix (&cfg->our_networks, $1) == 0) { 1457 YYERROR; 1458 } 1459 } 1460 ; 1461 %% 1462 /* 1463 * vi:ts=4 1464 */ 1465