head 1.113; access; symbols milter-greylist-4-5-13:1.113 milter-greylist-4-5-12:1.111 milter-greylist-4-5-11:1.111 milter-greylist-4-5-10:1.111 milter-greylist-4-9-10:1.111 milter-greylist-4-5-8:1.111 milter-greylist-4-5-9:1.111 milter-greylist-4-5-7:1.111 milter-greylist-4-5-6:1.111 milter-greylist-4-5:1.111 milter-greylist-4-5-5:1.110 milter-greylist-4-5-4:1.110 milter-greylist-4-5-3:1.108 milter-greylist-4-5-2:1.107 milter-greylist-4-5-1:1.107 milter-greylist-4-4-3:1.106 milter-greylist-4-4-2:1.105 milter-greylist-4-4-1:1.105 milter-greylist-4-4:1.105 milter-greylist-4-4-rc1:1.105 milter-greylist-4-4-alpha4:1.105 milter-greylist-4-4-alpha3:1.105 milter-greylist-4-4-alpha2:1.103 milter-greylist-4-4-alpha1:1.102 milter-greylist-4-2-7:1.89.2.2 milter-greylist-4-3-9:1.97 milter-greylist-4-2-6:1.89.2.2 milter-gresylit-4-2-6:1.89.2.2 milter-greylist-4-3-8:1.97 milter-greylist-4-3-7:1.97 milter-greylist-4-2-5:1.89.2.2 milter-greylist-4-3-6:1.97 milter-greylist-4-2-4:1.89.2.2 milter-greylist-4-3-5:1.96 milter-greylist-4-3-4:1.94 milter-greylist-4-2-3:1.89.2.1 milter-greylist-4-3-3:1.93 rmilter-greylist-4-2-3:1.89.2.1 milter-greylist-4-3-2:1.90 milter-greylist-4-3-1:1.90 milter-greylist-2-2-2:1.89 milter-greylist-4-2-2:1.89 milter-greylist-4-2-1:1.89 milter-greylist-4-2:1.89 milter-greylist-4-2-rc1:1.89 milter-greylist-4-2-beta1:1.89 milter-greylist-4-2-branch:1.89.0.2 milter-greylist-4-2-base:1.89 milter-greylist-4-2-0-base:1.89 milter-greylist-4-1-12:1.89 milter-greylist-4-1-11:1.88 milter-greylist-4-1-10:1.87 milter-greylist-4-1-9:1.87 milter-greylist-4-1-8:1.86 milter-greylist-4-1-7:1.84 milter-greylist-4-1-6:1.81 milter-greylist-4-0-1:1.72.2.1 milter-greylist-4-0-1-rc1:1.72.2.1 milter-greylist-4-1-5:1.76 milter-greylist-4-1-4:1.76 milter-greylist-4-1-3:1.75 milter-greylist-4-1-2:1.75 milter-greylist-4-1-1:1.74 milter-greylist-4-0-branch:1.72.0.2 milter-greylist-4-0-base:1.72 milter-greylist-4-0:1.72 milter-greylist-4-0-rc2:1.72 milter-greylist-4-0-rc1:1.72 milter-greylist-4-0-beta4:1.72 milter-greylist-4-0-beta3:1.71 milter-greylist-4-0-beta2:1.70 milter-greylist-4-0-beta1:1.68 milter-greylist-4-0-alpha6:1.64 milter-greylist-4-0-alpha5:1.63 milter-greylist-4-0-alpha4:1.61 milter-greylist-4-0-alpha3:1.61 milter-greylist-4-0-alpha2:1.61 milter-greylist-4-0-alpha1:1.60 milter-greylist-3-1-8:1.59 milter-greylist-3-1-7:1.58 milter-greylist-3-1-6:1.54 milter-greylist-1-3-6:1.54 milter-greylist-3-1-5:1.53 milter-greylist-3-1-5-alpha1:1.52 milter-greylist-3-0-1-beta1:1.33.2.3 milter-greylist-3-1-4:1.47 milter-greylist-3-1-3:1.42 milter-greylist-3-1-2:1.41 milter-greylist-3-1-1:1.36 milter-greylist-3-0:1.33.2.3 milter-greylist-3-0-rc7:1.33.2.3 milter-greylist-3-0-rc6:1.33.2.3 milter-greylist-3-0-rc5:1.33.2.3 milter-greylist-3-0-rc4:1.33.2.2 milter-greylist-3-0-rc3:1.33.2.1 milter-greylist-3-0-rc2:1.33.2.1 milter-greylist-3-0-rc1:1.33.2.1 milter-greylist-3-0-alpha6:1.33.2.1 milter-greylist-3-0-branch:1.33.0.2 milter-greylist-3-0-base:1.33 milter-greylist-3-0-alpha5:1.33 milter-greylist-3-0-alpha4:1.33 milter-greylist-3-0-alpha3:1.33 milter-greylist-3-0-alpha2:1.31 milter-greylist-3-0-alpha1:1.29 milter-greylist-2-1-12:1.29 milter-greylist-2-1-11:1.27 milter-greylist-2-1-10:1.25 milter-greylist-2-1-9:1.24 milter-greylist-2-1-9a1:1.22 milter-greylist-2-1-8:1.22 milter-greylist-2-1-7:1.21 milter-greylist-2-1-6:1.14 milter-greylist-2-1-5:1.13 milter-greylist-2-1-4:1.13 milter-greylist-2-1-3:1.10 milter-greylist-2-1-2:1.10 milter-greylist-2-1-1:1.10 milter-greylist-2-0-2:1.9 milter-greylist-2-0-1:1.9 milter-greylist-2-0-1-b1:1.9 milter-greylist-2-0-release:1.9 milter-greylist-2-0-rc5:1.9 milter-greylist-2-0-rc4:1.8 milter-greylist-2-0-rc3:1.7 milter-grey-list-2-0-rc3:1.7 milter-grey-list-2-0-rc2:1.7 milter-grey-list-2-0-rc1:1.5 milter-greylist-2-0-beta7:1.5 milter-greylist-2-0-beta6:1.5 milter-gre-ylist-2-0-beta5:1.5 milter-greylist-2-0-beta5:1.5 milter-greylist-2-0-beta4:1.5 milter-greylist-2-0-beta3:1.5 milter-greylist-2-0-beta2:1.2 milter-greylist-2-0:1.2.0.2 milter-greylist-2-0-base:1.2 milter-greylist-2-0-beta1:1.2 milter-greylist-1-7-5:1.1 before_delayed_tempfail:1.1 milter-greylist-1-7-4:1.1 milter-greylist-1-7-3:1.1 milter-greylist-1-7-2:1.1; locks; strict; comment @ * @; 1.113 date 2015.06.16.12.27.29; author manu; state Exp; branches; next 1.112; 1.112 date 2015.03.05.04.40.08; author manu; state Exp; branches; next 1.111; 1.111 date 2013.09.01.04.59.42; author manu; state Exp; branches; next 1.110; 1.110 date 2013.08.27.13.50.44; author manu; state Exp; branches; next 1.109; 1.109 date 2013.08.18.11.06.57; author manu; state Exp; branches; next 1.108; 1.108 date 2013.08.18.04.45.30; author manu; state Exp; branches; next 1.107; 1.107 date 2013.05.19.05.53.34; author manu; state Exp; branches; next 1.106; 1.106 date 2013.01.19.16.01.15; author manu; state Exp; branches; next 1.105; 1.105 date 2012.09.20.08.31.49; author manu; state Exp; branches; next 1.104; 1.104 date 2012.09.19.02.04.38; author manu; state Exp; branches; next 1.103; 1.103 date 2012.02.24.16.40.08; author manu; state Exp; branches; next 1.102; 1.102 date 2012.02.21.05.53.43; author manu; state Exp; branches; next 1.101; 1.101 date 2012.02.20.13.49.52; author manu; state Exp; branches; next 1.100; 1.100 date 2012.02.20.13.47.21; author manu; state Exp; branches; next 1.99; 1.99 date 2012.02.18.16.09.29; author manu; state Exp; branches; next 1.98; 1.98 date 2012.02.18.05.14.24; author manu; state Exp; branches; next 1.97; 1.97 date 2010.04.12.12.04.41; author manu; state Exp; branches; next 1.96; 1.96 date 2010.01.12.11.18.39; author manu; state Exp; branches; next 1.95; 1.95 date 2009.10.31.21.28.03; author manu; state Exp; branches; next 1.94; 1.94 date 2009.09.07.12.56.54; author manu; state Exp; branches; next 1.93; 1.93 date 2009.08.14.00.09.02; author manu; state Exp; branches; next 1.92; 1.92 date 2009.07.05.21.40.21; author manu; state Exp; branches; next 1.91; 1.91 date 2009.06.08.23.40.06; author manu; state Exp; branches; next 1.90; 1.90 date 2009.04.16.12.33.19; author manu; state Exp; branches; next 1.89; 1.89 date 2009.02.09.04.12.07; author manu; state Exp; branches 1.89.2.1; next 1.88; 1.88 date 2009.02.08.20.26.20; author manu; state Exp; branches; next 1.87; 1.87 date 2009.01.02.00.45.09; author manu; state Exp; branches; next 1.86; 1.86 date 2008.11.26.11.07.54; author manu; state Exp; branches; next 1.85; 1.85 date 2008.11.26.05.20.13; author manu; state Exp; branches; next 1.84; 1.84 date 2008.11.10.11.16.14; author manu; state Exp; branches; next 1.83; 1.83 date 2008.11.06.11.23.53; author manu; state Exp; branches; next 1.82; 1.82 date 2008.09.30.03.56.03; author manu; state Exp; branches; next 1.81; 1.81 date 2008.09.26.23.35.44; author manu; state Exp; branches; next 1.80; 1.80 date 2008.09.26.17.00.51; author manu; state Exp; branches; next 1.79; 1.79 date 2008.09.07.00.13.34; author manu; state Exp; branches; next 1.78; 1.78 date 2008.08.23.11.04.06; author manu; state Exp; branches; next 1.77; 1.77 date 2008.08.21.21.05.35; author manu; state Exp; branches; next 1.76; 1.76 date 2008.08.03.05.00.06; author manu; state Exp; branches; next 1.75; 1.75 date 2008.04.24.11.05.50; author manu; state Exp; branches; next 1.74; 1.74 date 2007.11.11.11.57.19; author manu; state Exp; branches; next 1.73; 1.73 date 2007.11.06.11.39.33; author manu; state Exp; branches; next 1.72; 1.72 date 2007.10.05.10.47.48; author manu; state Exp; branches 1.72.2.1; next 1.71; 1.71 date 2007.09.20.11.07.23; author manu; state Exp; branches; next 1.70; 1.70 date 2007.09.18.20.43.16; author manu; state Exp; branches; next 1.69; 1.69 date 2007.09.13.02.58.25; author manu; state Exp; branches; next 1.68; 1.68 date 2007.07.23.20.12.26; author manu; state Exp; branches; next 1.67; 1.67 date 2007.07.14.16.03.43; author manu; state Exp; branches; next 1.66; 1.66 date 2007.07.14.03.49.22; author manu; state Exp; branches; next 1.65; 1.65 date 2007.07.08.21.02.28; author manu; state Exp; branches; next 1.64; 1.64 date 2007.05.21.00.22.55; author manu; state Exp; branches; next 1.63; 1.63 date 2007.05.09.19.55.29; author manu; state Exp; branches; next 1.62; 1.62 date 2007.05.09.19.46.40; author manu; state Exp; branches; next 1.61; 1.61 date 2007.04.16.02.39.10; author manu; state Exp; branches; next 1.60; 1.60 date 2007.03.26.19.29.04; author manu; state Exp; branches; next 1.59; 1.59 date 2007.03.22.05.39.16; author manu; state Exp; branches; next 1.58; 1.58 date 2007.03.11.13.24.24; author manu; state Exp; branches; next 1.57; 1.57 date 2007.03.04.15.24.39; author manu; state Exp; branches; next 1.56; 1.56 date 2007.03.01.04.07.57; author manu; state Exp; branches; next 1.55; 1.55 date 2007.02.24.22.10.21; author manu; state Exp; branches; next 1.54; 1.54 date 2007.02.14.05.39.16; author manu; state Exp; branches; next 1.53; 1.53 date 2007.02.05.06.05.34; author manu; state Exp; branches; next 1.52; 1.52 date 2007.02.02.07.00.06; author manu; state Exp; branches; next 1.51; 1.51 date 2007.02.02.02.10.23; author manu; state Exp; branches; next 1.50; 1.50 date 2007.01.31.06.07.50; author manu; state Exp; branches; next 1.49; 1.49 date 2007.01.29.04.57.18; author manu; state Exp; branches; next 1.48; 1.48 date 2007.01.28.02.16.33; author manu; state Exp; branches; next 1.47; 1.47 date 2007.01.16.05.10.37; author manu; state Exp; branches; next 1.46; 1.46 date 2007.01.10.10.54.26; author manu; state Exp; branches; next 1.45; 1.45 date 2007.01.09.22.22.43; author manu; state Exp; branches; next 1.44; 1.44 date 2007.01.04.23.01.46; author manu; state Exp; branches; next 1.43; 1.43 date 2007.01.01.08.08.41; author manu; state Exp; branches; next 1.42; 1.42 date 2006.12.30.23.34.35; author manu; state Exp; branches; next 1.41; 1.41 date 2006.12.29.20.38.17; author manu; state Exp; branches; next 1.40; 1.40 date 2006.12.29.18.32.44; author manu; state Exp; branches; next 1.39; 1.39 date 2006.12.26.21.21.52; author manu; state Exp; branches; next 1.38; 1.38 date 2006.12.20.21.57.52; author manu; state Exp; branches; next 1.37; 1.37 date 2006.12.06.15.02.41; author manu; state Exp; branches; next 1.36; 1.36 date 2006.10.08.13.21.09; author manu; state Exp; branches; next 1.35; 1.35 date 2006.10.02.17.03.57; author manu; state Exp; branches; next 1.34; 1.34 date 2006.09.04.21.28.18; author manu; state Exp; branches; next 1.33; 1.33 date 2006.08.27.20.54.40; author manu; state Exp; branches 1.33.2.1; next 1.32; 1.32 date 2006.08.27.16.02.25; author manu; state Exp; branches; next 1.31; 1.31 date 2006.08.20.06.38.43; author manu; state Exp; branches; next 1.30; 1.30 date 2006.08.20.05.52.20; author manu; state Exp; branches; next 1.29; 1.29 date 2006.08.01.21.29.36; author manu; state Exp; branches; next 1.28; 1.28 date 2006.08.01.17.08.15; author manu; state Exp; branches; next 1.27; 1.27 date 2006.08.01.14.55.20; author manu; state Exp; branches; next 1.26; 1.26 date 2006.07.31.17.09.41; author manu; state Exp; branches; next 1.25; 1.25 date 2006.07.28.16.44.17; author manu; state Exp; branches; next 1.24; 1.24 date 2006.07.28.15.53.30; author manu; state Exp; branches; next 1.23; 1.23 date 2006.07.28.15.41.51; author manu; state Exp; branches; next 1.22; 1.22 date 2006.07.27.20.08.32; author manu; state Exp; branches; next 1.21; 1.21 date 2006.07.27.09.37.24; author manu; state Exp; branches; next 1.20; 1.20 date 2006.07.27.08.53.16; author manu; state Exp; branches; next 1.19; 1.19 date 2006.07.26.21.41.00; author manu; state Exp; branches; next 1.18; 1.18 date 2006.07.26.13.26.02; author manu; state Exp; branches; next 1.17; 1.17 date 2006.07.26.08.22.41; author manu; state Exp; branches; next 1.16; 1.16 date 2006.07.26.07.54.38; author manu; state Exp; branches; next 1.15; 1.15 date 2006.07.26.07.31.17; author manu; state Exp; branches; next 1.14; 1.14 date 2006.07.24.22.49.43; author manu; state Exp; branches; next 1.13; 1.13 date 2006.04.13.11.17.10; author manu; state Exp; branches; next 1.12; 1.12 date 2006.03.25.08.03.38; author manu; state Exp; branches; next 1.11; 1.11 date 2006.03.03.21.54.31; author manu; state Exp; branches; next 1.10; 1.10 date 2005.10.31.09.53.02; author manu; state Exp; branches; next 1.9; 1.9 date 2005.06.10.08.36.50; author manu; state Exp; branches; next 1.8; 1.8 date 2005.06.08.19.33.17; author manu; state Exp; branches; next 1.7; 1.7 date 2005.05.23.20.41.31; author manu; state Exp; branches; next 1.6; 1.6 date 2005.05.22.10.12.54; author manu; state Exp; branches; next 1.5; 1.5 date 2005.03.19.07.38.53; author manu; state Exp; branches; next 1.4; 1.4 date 2005.03.18.23.48.20; author manu; state Exp; branches; next 1.3; 1.3 date 2005.03.13.16.43.03; author manu; state Exp; branches; next 1.2; 1.2 date 2005.02.07.22.01.51; author manu; state Exp; branches; next 1.1; 1.1 date 2004.12.08.22.23.43; author manu; state Exp; branches; next ; 1.89.2.1 date 2009.08.14.00.11.03; author manu; state Exp; branches; next 1.89.2.2; 1.89.2.2 date 2010.04.14.04.41.22; author manu; state Exp; branches; next ; 1.72.2.1 date 2008.08.22.21.44.16; author manu; state Exp; branches; next 1.72.2.2; 1.72.2.2 date 2008.11.10.11.18.13; author manu; state Exp; branches; next ; 1.33.2.1 date 2006.09.04.22.07.21; author manu; state Exp; branches; next 1.33.2.2; 1.33.2.2 date 2006.10.02.17.02.42; author manu; state Exp; branches; next 1.33.2.3; 1.33.2.3 date 2006.10.08.13.21.13; author manu; state Exp; branches; next ; desc @@ 1.113 log @Support glob(7) pattern matching for properties @ text @/* $Id: acl.c,v 1.112 2015/03/05 04:40:08 manu Exp $ */ /* * Copyright (c) 2004-2012 Emmanuel Dreyfus * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Emmanuel Dreyfus * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #ifdef HAVE_SYS_CDEFS_H #include #ifdef __RCSID __RCSID("$Id: acl.c,v 1.112 2015/03/05 04:40:08 manu Exp $"); #endif #endif #if defined(HAVE_OLD_QUEUE_H) || !defined(HAVE_SYS_QUEUE_H) #include "queue.h" #else #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "spf.h" #include "acl.h" #include "store.h" #include "conf.h" #include "sync.h" #include "list.h" #include "ratelimit.h" #ifdef USE_DNSRBL #include "dnsrbl.h" #endif #ifdef USE_MX #include "mx.h" #endif #ifdef USE_CURL #include "urlcheck.h" #endif #ifdef USE_LDAP #include "ldapcheck.h" #endif #include "prop.h" #ifdef USE_GEOIP #include "geoip.h" #endif #ifdef USE_P0F #include "p0f.h" #endif #if (defined(HAVE_SPF) || defined(HAVE_SPF_ALT) || \ defined(HAVE_SPF2_10) || defined(HAVE_SPF2)) #include "spf.h" #endif #ifdef USE_DKIM #include "dkimcheck.h" #endif #ifdef USE_SPAMD #include "spamd.h" #endif #include "macro.h" #include "clock.h" #include "milter-greylist.h" #ifdef USE_DMALLOC #include #endif struct acllist acl_head; pthread_rwlock_t acl_lock; static struct acl_entry *gacl; int gneg; static int acl_actions(struct mlfi_priv *, acl_stage_t, struct acl_entry *, struct acl_param *, int); char *acl_print_netblock(acl_data_t *, char *, size_t); char *acl_print_string(acl_data_t *, char *, size_t); char *acl_print_regex(acl_data_t *, char *, size_t); char *acl_print_list(acl_data_t *, char *, size_t); char *acl_print_null(acl_data_t *, char *, size_t); char *acl_print_opnum(acl_data_t *, char *, size_t); char *acl_print_time(acl_data_t *, char *, size_t); int acl_opnum_cmp(int, enum operator, int); void acl_free_entry(struct acl_entry *); void acl_free_netblock(acl_data_t *); void acl_free_string(acl_data_t *); void acl_free_regex(acl_data_t *); void acl_add_netblock(acl_data_t *, void *); void acl_add_string(acl_data_t *, void *); void acl_add_regex(acl_data_t *, void *); void acl_add_body_string(acl_data_t *, void *); void acl_add_body_regex(acl_data_t *, void *); void acl_add_macro(acl_data_t *, void *); void acl_add_opnum(acl_data_t *, void *); void acl_add_opnum_body(acl_data_t *, void *); void acl_add_time(acl_data_t *, void *); void acl_add_list(acl_data_t *, void *); char *acl_print_macro(acl_data_t *, char *, size_t); void acl_add_ratelimit(acl_data_t *, void *); char *acl_print_ratelimit(acl_data_t *, char *, size_t); #ifdef USE_DNSRBL void acl_add_dnsrbl(acl_data_t *, void *); char *acl_print_dnsrbl(acl_data_t *, char *, size_t); #endif #ifdef USE_MX void acl_add_mx(acl_data_t *, void *); char *acl_print_mx(acl_data_t *, char *, size_t); #endif #ifdef USE_CURL void acl_add_urlcheck(acl_data_t *, void *); char *acl_print_urlcheck(acl_data_t *, char *, size_t); #endif #ifdef USE_LDAP void acl_add_ldapcheck(acl_data_t *, void *); char *acl_print_ldapcheck(acl_data_t *, char *, size_t); #endif void acl_add_prop_string(acl_data_t *, void *); void acl_add_prop_pop(acl_data_t *, void *); void acl_add_prop_opnum(acl_data_t *, void *); void acl_add_prop_regex(acl_data_t *, void *); char *acl_print_prop_string(acl_data_t *, char *, size_t); char *acl_print_prop_pop(acl_data_t *, char *, size_t); char *acl_print_prop_opnum(acl_data_t *, char *, size_t); char *acl_print_prop_regex(acl_data_t *, char *, size_t); void acl_free_prop_string(acl_data_t *); void acl_free_prop_pop(acl_data_t *); void acl_free_prop_opnum(acl_data_t *); void acl_free_prop_regex(acl_data_t *); #ifdef USE_NSUPDATE char *acl_print_nsupdate(acl_data_t *, char *, size_t); void acl_add_nsupdate(acl_data_t *, void *); #endif int acl_log_string(acl_data_t *, acl_stage_t, struct acl_param *, struct mlfi_priv *); struct acl_clause_rec acl_clause_rec[] = { /* Temporary types for lists */ { AC_LIST, MULTIPLE_OK, AS_NONE, "list", AT_LIST, AC_NONE, AC_NONE, EXF_NONE, acl_print_list, acl_add_list, NULL, acl_list_filter }, { AC_EMAIL, MULTIPLE_OK, AS_NONE, "email", AT_NONE, AC_NONE, AC_NONE, EXF_NONE, acl_print_string, acl_add_string, acl_free_string, NULL }, { AC_REGEX, MULTIPLE_OK, AS_NONE, "regex", AT_NONE, AC_NONE, AC_NONE, EXF_NONE, acl_print_regex, acl_add_regex, acl_free_regex, NULL }, { AC_STRING, MULTIPLE_OK, AS_NONE, "string", AT_NONE, AC_NONE, AC_NONE, EXF_NONE, acl_print_string, acl_add_string, acl_free_string, NULL }, /* Real types used in clauses */ { AC_NETBLOCK, UNIQUE, AS_ANY, "net", AT_NETBLOCK, AC_NETBLOCK_LIST, AC_NETBLOCK, EXF_ADDR, acl_print_netblock, acl_add_netblock, acl_free_netblock, acl_netblock_filter }, { AC_NETBLOCK_LIST, UNIQUE, AS_ANY, "net_list", AT_LIST, AC_NONE, AC_NONE, EXF_ADDR, acl_print_list, acl_add_list, NULL, acl_list_filter }, { AC_DOMAIN, UNIQUE, AS_ANY, "domain", AT_STRING, AC_DOMAIN_LIST, AC_DOMAIN, EXF_DOMAIN, acl_print_string, acl_add_string, acl_free_string, acl_domain_cmp }, { AC_DOMAIN_RE, UNIQUE, AS_ANY, "domain_re", AT_REGEX, AC_DOMAIN_LIST, AC_REGEX, EXF_DOMAIN, acl_print_regex, acl_add_regex, acl_free_regex, acl_domain_regexec }, { AC_DOMAIN_LIST, UNIQUE, AS_ANY, "domain_list", AT_LIST, AC_NONE, AC_NONE, EXF_DOMAIN, acl_print_list, acl_add_list, NULL, acl_list_filter }, { AC_HELO, UNIQUE, AS_RCPT, "helo", AT_STRING, AC_HELO_LIST, AC_STRING, EXF_HELO, acl_print_string, acl_add_string, acl_free_string, acl_helo_strstr }, { AC_HELO_RE, UNIQUE, AS_RCPT, "helo_re", AT_REGEX, AC_HELO_LIST, AC_REGEX, EXF_HELO, acl_print_regex, acl_add_regex, acl_free_regex, acl_helo_regexec }, { AC_HELO_LIST, UNIQUE, AS_RCPT, "helo_list", AT_LIST, AC_NONE, AC_NONE, EXF_HELO, acl_print_list, acl_add_list, NULL, acl_list_filter }, { AC_FROM, UNIQUE, AS_ANY, "from", AT_STRING, AC_FROM_LIST, AC_EMAIL, EXF_FROM, acl_print_string, acl_add_string, acl_free_string, acl_from_cmp }, { AC_FROM_RE, UNIQUE, AS_ANY, "from_re", AT_REGEX, AC_FROM_LIST, AC_REGEX, EXF_FROM, acl_print_regex, acl_add_regex, acl_free_regex, acl_from_regexec }, { AC_FROM_LIST, UNIQUE, AS_ANY, "from_list", AT_LIST, AC_NONE, AC_NONE, EXF_FROM, acl_print_list, acl_add_list, NULL, acl_list_filter }, { AC_RCPT, MULTIPLE_OK, AS_ANY, "rcpt", AT_STRING, AC_RCPT_LIST, AC_EMAIL, EXF_RCPT, acl_print_string, acl_add_string, acl_free_string, acl_rcpt_cmp }, { AC_RCPT_RE, MULTIPLE_OK, AS_ANY, "rcpt_re", AT_REGEX, AC_RCPT_LIST, AC_REGEX, EXF_RCPT, acl_print_regex, acl_add_regex, acl_free_regex, acl_rcpt_regexec }, { AC_RCPT_LIST, MULTIPLE_OK, AS_ANY, "rcpt_list", AT_LIST, AC_NONE, AC_NONE, EXF_RCPT, acl_print_list, acl_add_list, NULL, acl_list_filter }, { AC_BODY, MULTIPLE_OK, AS_DATA, "body", AT_STRING, AC_BODY_LIST, AC_STRING, EXF_BODY, acl_print_string, acl_add_body_string, acl_free_string, acl_body_strstr }, { AC_BODY_RE, MULTIPLE_OK, AS_DATA, "body_re", AT_REGEX, AC_BODY_LIST, AC_REGEX, EXF_BODY, acl_print_regex, acl_add_body_regex, acl_free_regex, acl_body_regexec }, { AC_BODY_LIST, MULTIPLE_OK, AS_DATA, "body_list", AT_LIST, AC_NONE, AC_NONE, EXF_BODY, acl_print_list, acl_add_list, NULL, acl_list_filter }, { AC_BODY_PROP, MULTIPLE_OK, AS_DATA, "body_prop", AT_STRING, AC_BODY_LIST, AC_STRING, EXF_BODY, acl_print_string, acl_add_body_string, acl_free_string, prop_body_validate }, { AC_HEADER, MULTIPLE_OK, AS_DATA, "header", AT_STRING, AC_HEADER_LIST, AC_STRING, EXF_HEADER, acl_print_string, acl_add_body_string, acl_free_string, acl_header_strstr }, { AC_HEADER_RE, MULTIPLE_OK, AS_DATA, "header_re", AT_REGEX, AC_HEADER_LIST, AC_REGEX, EXF_HEADER, acl_print_regex, acl_add_body_regex, acl_free_regex, acl_header_regexec }, { AC_HEADER_LIST, MULTIPLE_OK, AS_DATA, "header_list", AT_LIST, AC_NONE, AC_NONE, EXF_HEADER, acl_print_list, acl_add_list, NULL, acl_list_filter }, { AC_HEADER_PROP, MULTIPLE_OK, AS_DATA, "header_prop", AT_STRING, AC_HEADER_LIST, AC_STRING, EXF_HEADER, acl_print_string, acl_add_body_string, acl_free_string, prop_header_validate }, { AC_MACRO, MULTIPLE_OK, AS_ANY, "macro", AT_MACRO, AC_MACRO_LIST, AC_STRING, EXF_MACRO, acl_print_macro, acl_add_macro, NULL, macro_check }, { AC_MACRO_LIST, MULTIPLE_OK, AS_ANY, "macro_list", AT_LIST, AC_NONE, AC_NONE, EXF_MACRO, acl_print_list, acl_add_list, NULL, acl_list_filter }, { AC_RATELIMIT, MULTIPLE_OK, AS_ANY, "ratelimit", AT_RATELIMIT, AC_NONE, AC_STRING, 0, /* XXX */ acl_print_ratelimit, acl_add_ratelimit, NULL, ratelimit_validate }, #ifdef USE_DNSRBL { AC_DNSRBL, MULTIPLE_OK, AS_ANY, "dnsrbl", AT_DNSRBL, AC_DNSRBL_LIST, AC_STRING, EXF_DNSRBL, acl_print_dnsrbl, acl_add_dnsrbl, NULL, dnsrbl_check_source }, { AC_DNSRBL_LIST, MULTIPLE_OK, AS_ANY, "dnsrbl_list", AT_LIST, AC_NONE, AC_NONE, EXF_DNSRBL, acl_print_list, acl_add_list, NULL, acl_list_filter }, #endif #ifdef USE_MX { AC_MX, UNIQUE, AS_ANY, "mx", AT_MX, AC_NONE, AC_STRING, EXF_MX, acl_print_mx, acl_add_mx, NULL, mx_check }, #endif #ifdef USE_CURL { AC_URLCHECK, MULTIPLE_OK, AS_ANY, "urlcheck", AT_URLCHECK, AC_URLCHECK_LIST, AC_STRING, EXF_URLCHECK, acl_print_urlcheck, acl_add_urlcheck, NULL, urlcheck_validate }, { AC_URLCHECK_LIST, MULTIPLE_OK, AS_ANY, "urlcheck_list", AT_LIST, AC_NONE, AC_NONE, EXF_URLCHECK, acl_print_list, acl_add_list, NULL, acl_list_filter }, #endif #ifdef USE_LDAP { AC_LDAPCHECK, MULTIPLE_OK, AS_ANY, "ldapcheck", AT_LDAPCHECK, AC_NONE, AC_STRING, EXF_LDAPCHECK, acl_print_ldapcheck, acl_add_ldapcheck, NULL, ldapcheck_validate }, #endif { AC_PROP_STR, MULTIPLE_OK, AS_ANY, "prop", AT_PROP, AC_NONE, AC_PROP_STR, EXF_PROP, acl_print_prop_string, acl_add_prop_string, acl_free_prop_string, prop_string_validate }, { AC_PROP_GLOB, MULTIPLE_OK, AS_ANY, "glob_prop", AT_PROP, AC_NONE, AC_PROP_GLOB, EXF_PROP, acl_print_prop_string, acl_add_prop_string, acl_free_prop_string, prop_glob_validate }, { AC_PROP_PROP, MULTIPLE_OK, AS_ANY, "propprop", AT_PROP, AC_NONE, AC_PROP_PROP, EXF_PROP, acl_print_prop_pop, acl_add_prop_pop, acl_free_prop_pop, prop_pop_validate }, { AC_PROP_NUM, MULTIPLE_OK, AS_ANY, "prop_num", AT_PROP, AC_NONE, AC_PROP_NUM, EXF_PROP, acl_print_prop_opnum, acl_add_prop_opnum, acl_free_prop_opnum, prop_lhsnum_validate }, { AC_PROP_RE, MULTIPLE_OK, AS_ANY, "prop_re", AT_PROP, AC_NONE, AC_PROP_RE, EXF_PROP, acl_print_prop_regex, acl_add_prop_regex, acl_free_prop_regex, prop_regex_validate }, { AC_AUTH, MULTIPLE_OK, AS_ANY, "auth", AT_STRING, AC_AUTH_LIST, AC_STRING, EXF_AUTH, acl_print_string, acl_add_string, acl_free_string, acl_auth_strcmp }, { AC_AUTH_RE, MULTIPLE_OK, AS_ANY, "auth_re", AT_REGEX, AC_AUTH_LIST, AC_REGEX, EXF_AUTH, acl_print_regex, acl_add_regex, acl_free_regex, acl_auth_regexec }, { AC_AUTH_LIST, MULTIPLE_OK, AS_ANY, "auth_list", AT_LIST, AC_NONE, AC_NONE, EXF_AUTH, acl_print_list, acl_add_list, NULL, acl_list_filter }, { AC_TLS, MULTIPLE_OK, AS_ANY, "tls", AT_STRING, AC_TLS_LIST, AC_STRING, EXF_STARTTLS, acl_print_string, acl_add_string, acl_free_string, acl_tls_strcmp }, { AC_TLS_RE, MULTIPLE_OK, AS_ANY, "tls_re", AT_REGEX, AC_TLS_LIST, AC_REGEX, EXF_STARTTLS, acl_print_regex, acl_add_regex, acl_free_regex, acl_tls_regexec }, { AC_TLS_LIST, MULTIPLE_OK, AS_ANY, "tls_list", AT_LIST, AC_NONE, AC_NONE, EXF_STARTTLS, acl_print_list, acl_add_list, NULL, acl_list_filter }, #if (defined(HAVE_SPF) || defined(HAVE_SPF_ALT) || \ defined(HAVE_SPF2_10) || defined(HAVE_SPF2)) { AC_SPF, MULTIPLE_OK, AS_ANY, "spf", AT_SPF, AC_NONE, AC_SPF, EXF_SPF, acl_print_spf, acl_add_spf, NULL, spf_check }, #endif #ifdef USE_DKIM { AC_DKIM, MULTIPLE_OK, AS_DATA, "dkim", AT_DKIM, AC_NONE, AC_DKIM, EXF_DKIM, acl_print_dkim, acl_add_dkim, NULL, dkimcheck_validate }, #endif { AC_MSGSIZE, MULTIPLE_OK, AS_DATA, "msgsize", AT_OPNUM, AC_NONE, AC_MSGSIZE, EXF_MSGSIZE, acl_print_opnum, acl_add_opnum, NULL, acl_msgsize_cmp }, { AC_MSGSIZE_PROP, MULTIPLE_OK, AS_DATA, "msgsize_prop", AT_OPNUM, AC_NONE, AC_STRING_PROP, EXF_MSGSIZE, prop_opnum_print, prop_opnum_add, prop_opnum_free, prop_rhsnum_validate }, { AC_RCPTCOUNT, MULTIPLE_OK, AS_ANY, "rcptcount", AT_OPNUM, AC_NONE, AC_RCPTCOUNT, EXF_RCPTCOUNT, acl_print_opnum, acl_add_opnum_body, NULL, acl_rcptcount_cmp }, { AC_RCPTCOUNT_PROP, MULTIPLE_OK, AS_DATA, "rcptcount_prop", AT_OPNUM, AC_NONE, AC_STRING_PROP, EXF_RCPTCOUNT, acl_print_prop_string, acl_add_prop_string, acl_free_prop_string, prop_rhsnum_validate }, { AC_CLOCKSPEC, MULTIPLE_OK, AS_ANY, "time", AT_CLOCKSPEC, AC_NONE, AC_CLOCKSPEC, EXF_CLOCKSPEC, print_clockspec, add_clockspec, clockspec_free, clockspec_filter }, { AC_CLOCKSPEC_LIST, MULTIPLE_OK, AS_ANY, "time_list", AT_LIST, AC_NONE, AC_NONE, EXF_CLOCKSPEC, acl_print_list, acl_add_list, NULL, acl_list_filter }, #ifdef USE_GEOIP { AC_GEOIP, MULTIPLE_OK, AS_ANY, "geoip", AT_STRING, AC_GEOIP_LIST, AC_STRING, EXF_GEOIP, acl_print_string, acl_add_string, acl_free_string, geoip_filter }, { AC_GEOIP_LIST, MULTIPLE_OK, AS_ANY, "geoip_list", AT_LIST, AC_NONE, AC_NONE, EXF_GEOIP, acl_print_list, acl_add_list, NULL, acl_list_filter }, #endif #ifdef USE_P0F { AC_P0F, MULTIPLE_OK, AS_ANY, "p0f", AT_STRING, AC_P0F_LIST, AC_STRING, EXF_P0F, acl_print_string, acl_add_string, acl_free_string, p0f_cmp }, { AC_P0F_RE, UNIQUE, AS_ANY, "p0f_re", AT_REGEX, AC_P0F_LIST, AC_REGEX, EXF_DOMAIN, acl_print_regex, acl_add_regex, acl_free_regex, p0f_regexec }, { AC_P0F_LIST, MULTIPLE_OK, AS_ANY, "p0f_list", AT_LIST, AC_NONE, AC_NONE, EXF_P0F, acl_print_list, acl_add_list, NULL, acl_list_filter }, #endif #ifdef USE_SPAMD { AC_SA, MULTIPLE_OK, AS_DATA, "spamd", AT_NONE, AC_NONE, AC_NONE, EXF_SA, acl_print_null, NULL, NULL, spamd_isspam }, { AC_SASCORE, MULTIPLE_OK, AS_DATA, "spamd score", AT_OPNUM, AC_NONE, AC_NONE, EXF_SA, acl_print_opnum, acl_add_opnum, NULL, spamd_score }, { AC_SASCORE_PROP, MULTIPLE_OK, AS_DATA, "sascore_prop", AT_OPNUM, AC_NONE, AC_STRING_PROP, EXF_SA, acl_print_prop_string, acl_add_prop_string, acl_free_prop_string, prop_rhsnum_validate }, #endif /* USE_SPAMD */ #ifdef HAVE_DATA_CALLBACK { AC_TARPIT, UNIQUE, AS_ANY, "tarpit", AT_TIME, AC_NONE, AC_NONE, EXF_TARPIT, acl_print_time, acl_add_time, NULL, acl_tarpit_filter }, #endif #ifdef USE_NSUPDATE { AC_NSUPDATE, MULTIPLE_OK, AS_ANY, "nsupdate", AT_NSUPDATE, AC_NONE, AC_STRING, EXF_NONE, acl_print_nsupdate, acl_add_nsupdate, NULL, nsupdate_filter }, #endif { AC_EQSET, MULTIPLE_OK, AS_ANY, "set", AT_PROP, AC_NONE, AC_NONE, EXF_NONE, acl_print_prop_string, acl_add_prop_string, acl_free_prop_string, prop_eqset_string }, { AC_EQRSET, MULTIPLE_OK, AS_ANY, "rset", AT_PROP, AC_NONE, AC_NONE, EXF_NONE, acl_print_prop_string, acl_add_prop_string, acl_free_prop_string, prop_eqrset_string }, { AC_INCSET, MULTIPLE_OK, AS_ANY, "incset", AT_PROP, AC_NONE, AC_NONE, EXF_NONE, acl_print_prop_string, acl_add_prop_string, acl_free_prop_string, prop_incset_string }, { AC_INCRSET, MULTIPLE_OK, AS_ANY, "incrset", AT_PROP, AC_NONE, AC_NONE, EXF_NONE, acl_print_prop_string, acl_add_prop_string, acl_free_prop_string, prop_incrset_string }, { AC_DECSET, MULTIPLE_OK, AS_ANY, "decset", AT_PROP, AC_NONE, AC_NONE, EXF_NONE, acl_print_prop_string, acl_add_prop_string, acl_free_prop_string, prop_decset_string }, { AC_DECRSET, MULTIPLE_OK, AS_ANY, "decrset", AT_PROP, AC_NONE, AC_NONE, EXF_NONE, acl_print_prop_string, acl_add_prop_string, acl_free_prop_string, prop_decrset_string }, { AC_EQSETPROP, MULTIPLE_OK, AS_ANY, "setprop", AT_PROP, AC_NONE, AC_NONE, EXF_NONE, acl_print_prop_string, acl_add_prop_string, acl_free_prop_string, prop_eqset_prop }, { AC_EQRSETPROP, MULTIPLE_OK, AS_ANY, "rsetprop", AT_PROP, AC_NONE, AC_NONE, EXF_NONE, acl_print_prop_string, acl_add_prop_string, acl_free_prop_string, prop_eqrset_prop }, { AC_INCSETPROP, MULTIPLE_OK, AS_ANY, "incsetprop", AT_PROP, AC_NONE, AC_NONE, EXF_NONE, acl_print_prop_string, acl_add_prop_string, acl_free_prop_string, prop_incset_prop }, { AC_INCRSETPROP, MULTIPLE_OK, AS_ANY, "incrsetprop", AT_PROP, AC_NONE, AC_NONE, EXF_NONE, acl_print_prop_string, acl_add_prop_string, acl_free_prop_string, prop_incrset_prop }, { AC_DECSETPROP, MULTIPLE_OK, AS_ANY, "decsetprop", AT_PROP, AC_NONE, AC_NONE, EXF_NONE, acl_print_prop_string, acl_add_prop_string, acl_free_prop_string, prop_decset_prop }, { AC_DECRSETPROP, MULTIPLE_OK, AS_ANY, "decrsetprop", AT_PROP, AC_NONE, AC_NONE, EXF_NONE, acl_print_prop_string, acl_add_prop_string, acl_free_prop_string, prop_decrset_prop }, { AC_LOG, MULTIPLE_OK, AS_ANY, "log", AT_STRING, AC_NONE, AC_NONE, EXF_NONE, acl_print_string, acl_add_string, acl_free_string, acl_log_string }, }; struct { acl_stage_t ss_stage; char *ss_string; } stage_string_rec[] = { { AS_NONE, "NONE" }, { AS_RCPT, "RCPT" }, { AS_DATA, "DATA" }, { AS_ANY, "ANY" }, }; char * stage_string(stage) acl_stage_t stage; { int i; int count = sizeof(stage_string_rec) / sizeof(*stage_string_rec); for (i = 0; i < count; i++) if (stage_string_rec[i].ss_stage == stage) return stage_string_rec[i].ss_string; mg_log(LOG_ERR, "unexpected ACL stage %d", stage); exit(EX_SOFTWARE); /* NOTREACHED */ return NULL; } int acl_opnum_cmp(val1, op, val2) int val1; enum operator op; int val2; { switch(op) { case OP_EQ: return (val1 == val2); break; case OP_NE: return (val1 != val2); break; case OP_LT: return (val1 < val2); break; case OP_GT: return (val1 > val2); break; case OP_LE: return (val1 <= val2); break; case OP_GE: return (val1 >= val2); break; default: mg_log(LOG_ERR, "unexpected operator"); exit(EX_SOFTWARE); break; } /* NOTREACHED */ return 0; } int acl_rcptcount_cmp(ad, stage, ap, priv) acl_data_t *ad; acl_stage_t stage; struct acl_param *ap; struct mlfi_priv *priv; { if (acl_opnum_cmp(priv->priv_rcptcount, ad->opnum.op, ad->opnum.num)) return 1; return 0; } int acl_msgsize_cmp(ad, stage, ap, priv) acl_data_t *ad; acl_stage_t stage; struct acl_param *ap; struct mlfi_priv *priv; { if (acl_opnum_cmp(priv->priv_msgcount, ad->opnum.op, ad->opnum.num)) return 1; return 0; } int acl_domain_cmp(ad, stage, ap, priv) acl_data_t *ad; acl_stage_t stage; struct acl_param *ap; struct mlfi_priv *priv; { char *host = priv->priv_hostname; char *domain = ad->string; int hidx, didx; if ((host[0] == '\0') && domain[0] == '\0') return 1; if ((host[0] == '\0') || domain[0] == '\0') return 0; hidx = strlen(host) - 1; didx = strlen(domain) - 1; while ((hidx >= 0) && (didx >= 0)) { if (tolower((int)host[hidx]) != tolower((int)domain[didx])) { return (0); } hidx--; didx--; } if (didx >= 0) return (0); if ( (conf.c_domainexact == 1) &&(hidx >= 0) && (host[hidx] != '.')) { mg_log(LOG_INFO, "domainexact option overrides %s suffix " "match of %s", domain, host); return (0); } return (1); } int acl_header_strstr(ad, stage, ap, priv) acl_data_t *ad; acl_stage_t stage; struct acl_param *ap; struct mlfi_priv *priv; { struct line *l; if (stage != AS_DATA) { mg_log(LOG_ERR, "header filter called at non DATA stage"); exit(EX_SOFTWARE); } TAILQ_FOREACH(l, &priv->priv_header, l_list) if (strstr(l->l_line, ad->string) != NULL) return 1; return 0; } int acl_body_strstr(ad, stage, ap, priv) acl_data_t *ad; acl_stage_t stage; struct acl_param *ap; struct mlfi_priv *priv; { struct line *l; if (stage != AS_DATA) { mg_log(LOG_ERR, "body filter called at non DATA stage"); exit(EX_SOFTWARE); } TAILQ_FOREACH(l, &priv->priv_body, l_list) if (strstr(l->l_line, ad->string) != NULL) return 1; return 0; } int acl_tarpit_filter(ad, stage, ap, priv) acl_data_t *ad; acl_stage_t stage; struct acl_param *ap; struct mlfi_priv *priv; { struct tuple_fields tuple; tuple.sa = SA(&priv->priv_addr); tuple.salen = priv->priv_addrlen; tuple.from = priv->priv_from; tuple.rcpt = priv->priv_cur_rcpt; ap->ap_tarpitted = mg_tarpit_check(&tuple); ap->ap_tarpit = ad->time; return ap->ap_tarpitted == (time_t)-1 || ap->ap_tarpitted > 0; } int myregexec(priv, ad, ap, string) struct mlfi_priv *priv; acl_data_t *ad; struct acl_param *ap; const char *string; { size_t len; int nmatch; regmatch_t *pmatch = NULL; int retval; int i; /* * Placeholder for information from regexec, +1 for \0 */ nmatch = ad->regex.nmatch + 1; if ((pmatch = malloc(nmatch * sizeof(*pmatch))) == NULL) { mg_log(LOG_ERR, "malloc failed: %s", strerror(errno)); exit(EX_OSERR); } bzero(pmatch, nmatch * sizeof(*pmatch)); /* * The real regexec */ retval = regexec(ad->regex.re, string, nmatch, pmatch, 0); if (retval != 0) /* No match */ goto out; /* * Add room for matched parenthesized substrings */ len = (ap->ap_nmatch + ad->regex.nmatch) * sizeof(*ap->ap_pmatch);; if (len > 0) { if ((ap->ap_pmatch = realloc(ap->ap_pmatch, len)) == NULL) { mg_log(LOG_ERR, "realloc failed: %s", strerror(errno)); exit(EX_OSERR); } } /* Move the previous matches to the end of the array */ if (ap->ap_nmatch != 0) { memmove(&ap->ap_pmatch[ad->regex.nmatch], &ap->ap_pmatch[0], ap->ap_nmatch * sizeof(char *)); } bzero(&ap->ap_pmatch[0], ad->regex.nmatch * sizeof(char *)); ap->ap_nmatch += ad->regex.nmatch; /* * Gather the strings, skipping the first one (\0) */ for (i = 1; i < nmatch; i++) { if (pmatch[i].rm_so == -1) { mg_log(LOG_DEBUG, "unexpected void backreference no %d " "in regex %s against \"%s\"", i, ad->regex.re_copy, string); break; } len = pmatch[i].rm_eo - pmatch[i].rm_so + 1; if ((ap->ap_pmatch[i - 1] = malloc(len)) == NULL) { mg_log(LOG_ERR, "malloc failed: %s", strerror(errno)); exit(EX_OSERR); } memcpy(ap->ap_pmatch[i - 1], string + pmatch[i].rm_so, len - 1); ap->ap_pmatch[i - 1][len - 1] = '\0'; if (conf.c_debug) mg_log(LOG_DEBUG, "regex /%s/ against \"%s\": match[%d] = \"%s\"", ad->regex.re_copy, string, i, ap->ap_pmatch[i - 1]); } out: if (pmatch != NULL) free(pmatch); #if 0 if (conf.c_debug) { int i; for (i = 0; i < ap->ap_nmatch; i++) mg_log(LOG_DEBUG, " match[%d] = \"%s\"", i, ap->ap_pmatch[i]); } #endif return retval; } int acl_helo_regexec(ad, stage, ap, priv) acl_data_t *ad; acl_stage_t stage; struct acl_param *ap; struct mlfi_priv *priv; { if (myregexec(priv, ad, ap, priv->priv_helo) == 0) return 1; return 0; } int acl_from_regexec(ad, stage, ap, priv) acl_data_t *ad; acl_stage_t stage; struct acl_param *ap; struct mlfi_priv *priv; { if (myregexec(priv, ad, ap, priv->priv_from) == 0) return 1; return 0; } int acl_auth_regexec(ad, stage, ap, priv) acl_data_t *ad; acl_stage_t stage; struct acl_param *ap; struct mlfi_priv *priv; { char *auth_authen; auth_authen = smfi_getsymval(priv->priv_ctx, "{auth_authen}"); if (auth_authen == NULL) return 0; if (myregexec(priv, ad, ap, auth_authen) == 0) return 1; return 0; } int acl_tls_regexec(ad, stage, ap, priv) acl_data_t *ad; acl_stage_t stage; struct acl_param *ap; struct mlfi_priv *priv; { char *verify; char *dn; if (((verify = smfi_getsymval(priv->priv_ctx, "{verify}")) == NULL) || (strcmp(verify, "OK") != 0) || ((dn = smfi_getsymval(priv->priv_ctx, "{cert_subject}")) == NULL)) return 0; if (myregexec(priv, ad, ap, dn) == 0) return 1; return 0; } int acl_rcpt_regexec(ad, stage, ap, priv) acl_data_t *ad; acl_stage_t stage; struct acl_param *ap; struct mlfi_priv *priv; { if (stage == AS_RCPT) { if (myregexec(priv, ad, ap, priv->priv_cur_rcpt) == 0) return 1; } else { struct rcpt *r; LIST_FOREACH(r, &priv->priv_rcpt, r_list) if (myregexec(priv, ad, ap, r->r_addr) == 0) return 1; } return 0; } int acl_domain_regexec(ad, stage, ap, priv) acl_data_t *ad; acl_stage_t stage; struct acl_param *ap; struct mlfi_priv *priv; { if (myregexec(priv, ad, ap, priv->priv_hostname) == 0) return 1; return 0; } int acl_header_regexec(ad, stage, ap, priv) acl_data_t *ad; acl_stage_t stage; struct acl_param *ap; struct mlfi_priv *priv; { struct line *l; if (stage != AS_DATA) { mg_log(LOG_ERR, "header filter called at non DATA stage"); exit(EX_SOFTWARE); } TAILQ_FOREACH(l, &priv->priv_header, l_list) if (myregexec(priv, ad, ap, l->l_line) == 0) return 1; return 0; } int acl_helo_strstr(ad, stage, ap, priv) acl_data_t *ad; acl_stage_t stage; struct acl_param *ap; struct mlfi_priv *priv; { char *test_helo; char lh_priv[ADDRLEN + 1]; char lh_test[ADDRLEN + 1]; int i, res; res = 0; test_helo = fstring_expand(priv, NULL, ad->string, NULL); /* Convert domain-names (ASCII) to same-case for comparison */ for (i = 0; i < sizeof(lh_priv) && priv->priv_helo[i]; i++) lh_priv[i] = tolower((int)(priv->priv_helo[i])); lh_priv[i] = '\0'; for (i = 0; i < sizeof(lh_test) && test_helo[i]; i++) lh_test[i] = tolower((int)(test_helo[i])); lh_test[i] = '\0'; /* * Note that for historical reasons (maybe considered a bug, * but maybe some deployments now rely on this behavior) * strstr() is used rather than strcmp(), allowing substring * matches to be treated as good hits. * Earlier versions did only the strstr(priv_helo,test_helo). */ if ((strstr(lh_priv, lh_test) != NULL) || (strstr(lh_test, lh_priv) != NULL)) res = 1; if (conf.c_debug) mg_log(LOG_DEBUG, "acl_helo_strstr: \"%s\"/\"%s\" " "(lowercase of \"%s\"/\"%s\") => %s\n", lh_priv, lh_test, priv->priv_helo, test_helo, res ? "MATCHED" : "MISMATCH"); free(test_helo); return res; } int acl_from_cmp(ad, stage, ap, priv) acl_data_t *ad; acl_stage_t stage; struct acl_param *ap; struct mlfi_priv *priv; { char *from = ad->string; if (emailcmp(priv->priv_from, from) == 0) return 1; return 0; } int acl_rcpt_cmp(ad, stage, ap, priv) acl_data_t *ad; acl_stage_t stage; struct acl_param *ap; struct mlfi_priv *priv; { char *rcpt = ad->string; if (stage == AS_RCPT) { if (emailcmp(priv->priv_cur_rcpt, rcpt) == 0) return 1; } else { struct rcpt *r; LIST_FOREACH(r, &priv->priv_rcpt, r_list) if (emailcmp(r->r_addr, rcpt) == 0) return 1; } return 0; } int acl_auth_strcmp(ad, stage, ap, priv) acl_data_t *ad; acl_stage_t stage; struct acl_param *ap; struct mlfi_priv *priv; { char *auth_authen; auth_authen = smfi_getsymval(priv->priv_ctx, "{auth_authen}"); if (auth_authen == NULL) return 0; if (strcmp(auth_authen, ad->string) == 0) return 1; return 0; } int acl_tls_strcmp(ad, stage, ap, priv) acl_data_t *ad; acl_stage_t stage; struct acl_param *ap; struct mlfi_priv *priv; { char *verify; char *dn; if (((verify = smfi_getsymval(priv->priv_ctx, "{verify}")) == NULL) || (strcmp(verify, "OK") != 0) || ((dn = smfi_getsymval(priv->priv_ctx, "{cert_subject}")) == NULL)) return 0; if (strcmp(dn, ad->string) == 0) return 1; return 0; } int acl_list_filter(ad, stage, ap, priv) acl_data_t *ad; acl_stage_t stage; struct acl_param *ap; struct mlfi_priv *priv; { struct all_list_entry *ale; struct list_entry *le; int retval; ale = ad->list; TAILQ_FOREACH(le, &ale->al_head, l_list) { retval = (*le->l_acr->acr_filter)(&le->l_data, stage, ap, priv); if (retval != 0) return retval; } return 0; } int acl_body_regexec(ad, stage, ap, priv) acl_data_t *ad; acl_stage_t stage; struct acl_param *ap; struct mlfi_priv *priv; { struct line *l; if (stage != AS_DATA) { mg_log(LOG_ERR, "body filter called at non DATA stage"); exit(EX_SOFTWARE); } TAILQ_FOREACH(l, &priv->priv_body, l_list) if (myregexec(priv, ad, ap, l->l_line) == 0) return 1; return 0; } struct acl_clause_rec * acl_list_item_fixup(item_type, list_type) acl_clause_t item_type; acl_clause_t list_type; { struct acl_clause_rec *cur_acr; int i; int count = sizeof(acl_clause_rec) / sizeof(*acl_clause_rec); for (i = 0; i < count; i++) { cur_acr = &acl_clause_rec[i]; if ((cur_acr->acr_list_type == list_type) && (cur_acr->acr_item_type == item_type)) return cur_acr; } return NULL; } struct acl_clause_rec * get_acl_clause_rec(type) acl_clause_t type; { int i; int count = sizeof(acl_clause_rec) / sizeof(*acl_clause_rec); for (i = 0; i < count; i++) if (acl_clause_rec[i].acr_type == type) return &acl_clause_rec[i]; mg_log(LOG_ERR, "unexpected acl clause type %d", type); exit(EX_SOFTWARE); /* NOTREACHED */ return NULL; } char * acl_print_string(ad, buf, len) acl_data_t *ad; char *buf; size_t len; { snprintf(buf, len, "\"%s\"", ad->string); return buf; } char * acl_print_regex(ad, buf, len) acl_data_t *ad; char *buf; size_t len; { snprintf(buf, len, "%s", ad->regex.re_copy); return buf; } char * acl_print_list(ad, buf, len) acl_data_t *ad; char *buf; size_t len; { snprintf(buf, len, "\"%s\"", ad->list->al_name); return buf; } char * acl_print_null(ad, buf, len) acl_data_t *ad; char *buf; size_t len; { if (len > 0) buf[0] = '\0'; return buf; } static char * acl_print_op(op) enum operator op; { struct { enum operator op; char *str; } op_to_str[] = { { OP_EQ, "==" }, { OP_NE, "!=" }, { OP_GT, ">" }, { OP_LT, "<" }, { OP_GE, ">=" }, { OP_LE, "<=" }, }; int i; for (i = 0; i < sizeof(op_to_str) / sizeof(*op_to_str); i++) { if (op_to_str[i].op == op) return op_to_str[i].str; } mg_log(LOG_ERR, "unexpected operator"); exit(EX_SOFTWARE); } char * acl_print_opnum(ad, buf, len) acl_data_t *ad; char *buf; size_t len; { snprintf(buf, len, "%s %d", acl_print_op(ad->opnum.op), ad->opnum.num); return buf; } char * acl_print_time(ad, buf, len) acl_data_t *ad; char *buf; size_t len; { snprintf(buf, len, "%ld", (long)ad->time); return buf; } void acl_add_string(ad, data) acl_data_t *ad; void *data; { char *string = data; if ((ad->string = strdup(string)) == NULL) { mg_log(LOG_ERR, "acl strdup failed: %s", strerror(errno)); exit(EX_OSERR); } return; } void acl_add_body_string(ad, data) acl_data_t *ad; void *data; { if (conf.c_maxpeek == 0) conf.c_maxpeek = -1; acl_add_string(ad, data); return; } void acl_add_body_regex(ad, data) acl_data_t *ad; void *data; { if (conf.c_maxpeek == 0) conf.c_maxpeek = -1; acl_add_regex(ad, data); return; } #define ERRLEN 1024 void acl_add_regex(ad, data) acl_data_t *ad; void *data; { char *regexstr = data; regex_t *regex; char errstr[ERRLEN + 1]; char *cp; int skip; int error; int flags; if ((regex = malloc(sizeof(*regex))) == NULL) { mg_log(LOG_ERR, "acl malloc failed: %s", strerror(errno)); exit(EX_OSERR); } ad->regex.re = regex; if ((ad->regex.re_copy = strdup(regexstr)) == NULL) { mg_log(LOG_ERR, "acl strdup failed: %s", strerror(errno)); exit(EX_OSERR); } /* Remove leading and trailing / */ if (regexstr[0] == '/') regexstr++; if ((strlen(regexstr) > 0) && (regexstr[strlen(regexstr) - 1] == '/')) regexstr[strlen(regexstr) - 1] = '\0'; /* Change escaped / into / */ for (cp = regexstr; *cp; cp++) { if ((*cp == '\\') && (*(cp + 1) == '/')) memmove(cp, cp + 1, strlen(cp + 1) + 1); } flags = (REG_ICASE | REG_NEWLINE); if (conf.c_extendedregex) flags |= REG_EXTENDED; if ((error = regcomp(regex, regexstr, flags)) != 0) { regerror(error, regex, errstr, ERRLEN); mg_log(LOG_ERR, "bad regular expression \"%s\": %s", regexstr, errstr); exit(EX_OSERR); } /* Cout how many back-references we have */ skip = 0; ad->regex.nmatch = 0; for (cp = regexstr; *cp; cp++) { if (skip) continue; if (cp[0] == '(') ad->regex.nmatch++; } return; } void acl_add_time(ad, data) acl_data_t *ad; void *data; { time_t *t = (time_t *)data; ad->time = *t; return; } void acl_free_string(ad) acl_data_t *ad; { free(ad->string); return; } void acl_free_regex(ad) acl_data_t *ad; { regfree(ad->regex.re); free(ad->regex.re_copy); return; } static struct acl_entry * acl_init_entry(void) { struct acl_entry *acl; if ((acl = malloc(sizeof(*acl))) == NULL) { mg_log(LOG_ERR, "ACL malloc failed: %s", strerror(errno)); exit(EX_OSERR); } memset(acl, 0, sizeof(*acl)); acl->a_delay = -1; acl->a_autowhite = -1; acl->a_tarpit = -1; acl->a_tarpit_scope = -1; /* * First gacl initialzation is done before conf is * valid. We therefore have to set to 0 and have * maxpeek global setting overwriting gacl->a_maxpeek * in acl_maxpeek_fixup() */ acl->a_maxpeek = (&conf != NULL) ? conf.c_maxpeek : 0; TAILQ_INIT(&acl->a_clause); return acl; } void acl_init(void) { int error; TAILQ_INIT(&acl_head); if ((error = pthread_rwlock_init(&acl_lock, NULL)) != 0) { mg_log(LOG_ERR, "pthread_rwlock_init failed: %s", strerror(error)); exit(EX_OSERR); } gacl = acl_init_entry(); gneg = PLAIN; return; } void acl_free_entry(acl) struct acl_entry *acl; { struct acl_clause *ac; while (!TAILQ_EMPTY(&acl->a_clause)) { ac = TAILQ_FIRST(&acl->a_clause); TAILQ_REMOVE(&acl->a_clause, ac, ac_list); if (ac->ac_acr->acr_free) (*ac->ac_acr->acr_free)(&ac->ac_data); free(ac); } if (acl->a_code != NULL) free(acl->a_code); if (acl->a_ecode != NULL) free(acl->a_ecode); if (acl->a_msg != NULL) free(acl->a_msg); if (acl->a_report != NULL) free(acl->a_report); if (acl->a_addheader != NULL) free(acl->a_addheader); if (acl->a_addfooter != NULL) free(acl->a_addfooter); if (acl->a_subjtag != NULL) free(acl->a_subjtag); free(acl); return; } void acl_drop(void) { gacl->a_flags |= A_DROP_ACL; return; } void acl_add_flushaddr(void) { gacl->a_flags |= A_FLUSHADDR; return; } void acl_add_nolog(void) { gacl->a_flags |= A_NOLOG; return; } void acl_add_netblock(ad, data) acl_data_t *ad; void *data; { struct acl_netblock_data *and = data; struct sockaddr *sa; socklen_t salen; int cidr; ipaddr mask; int maxcidr, masklen; #ifdef AF_INET6 int i; #endif sa = and->addr; salen = and->salen; cidr = and->cidr; switch (sa->sa_family) { case AF_INET: maxcidr = 32; masklen = sizeof(mask.in4); break; #ifdef AF_INET6 case AF_INET6: maxcidr = 128; masklen = sizeof(mask.in6); break; #endif default: mg_log(LOG_ERR, "bad address family in acl list line %d", conf_line); exit(EX_DATAERR); } if (cidr > maxcidr || cidr < 0) { mg_log(LOG_ERR, "bad mask in acl list line %d", conf_line); exit(EX_DATAERR); } switch (sa->sa_family) { case AF_INET: prefix2mask4(cidr, &mask.in4); SADDR4(sa)->s_addr &= mask.in4.s_addr; break; #ifdef AF_INET6 case AF_INET6: prefix2mask6(cidr, &mask.in6); for (i = 0; i < 16; i += 4) *(uint32_t *)&SADDR6(sa)->s6_addr[i] &= *(uint32_t *)&mask.in6.s6_addr[i]; break; #endif } if ((ad->netblock.addr = malloc(salen)) == NULL) { mg_log(LOG_ERR, "acl malloc failed: %s", strerror(errno)); exit(EX_OSERR); } if ((ad->netblock.mask = malloc(sizeof(*ad->netblock.mask))) == NULL) { mg_log(LOG_ERR, "acl malloc failed: %s", strerror(errno)); exit(EX_OSERR); } ad->netblock.salen = salen; ad->netblock.cidr = cidr; memcpy(ad->netblock.addr, sa, salen); memcpy(ad->netblock.mask, &mask, masklen); return; } void acl_free_netblock(ad) acl_data_t *ad; { free(ad->netblock.addr); free(ad->netblock.mask); return; } char * acl_print_netblock(ad, buf, len) acl_data_t *ad; char *buf; size_t len; { char addrstr[IPADDRSTRLEN]; char maskstr[IPADDRSTRLEN]; iptostring(ad->netblock.addr, ad->netblock.salen, addrstr, sizeof(addrstr)); inet_ntop(ad->netblock.addr->sa_family, ad->netblock.mask, maskstr, sizeof(maskstr)); snprintf(buf, len, "%s/%s", addrstr, maskstr); return buf; } int acl_netblock_filter(ad, stage, ap, priv) acl_data_t *ad; acl_stage_t stage; struct acl_param *ap; struct mlfi_priv *priv; { struct sockaddr *sa; sa = SA(&priv->priv_addr); if (ip_match(sa, ad->netblock.addr, ad->netblock.mask)) return 1; return 0; } void acl_add_ratelimit(ad, data) acl_data_t *ad; void *data; { char *ratelimit = data; if ((ad->ratelimit_conf = ratelimit_byname(ratelimit)) == NULL) { mg_log(LOG_ERR, "unknown ratelimit class \"%s\"", ratelimit); exit(EX_DATAERR); } return; } char * acl_print_ratelimit(ad, buf, len) acl_data_t *ad; char *buf; size_t len; { snprintf(buf, len, "\"%s\"", ad->ratelimit_conf->rc_name); return buf; } #ifdef USE_DNSRBL void acl_add_dnsrbl(ad, data) acl_data_t *ad; void *data; { char *dnsrbl = data; if ((ad->dnsrbl = dnsrbl_byname(dnsrbl)) == NULL) { mg_log(LOG_ERR, "unknown DNSRBL \"%s\"", dnsrbl); exit(EX_DATAERR); } return; } char * acl_print_dnsrbl(ad, buf, len) acl_data_t *ad; char *buf; size_t len; { snprintf(buf, len, "\"%s\"", ad->dnsrbl->d_name); return buf; } #endif #ifdef USE_MX void acl_add_mx(ad, data) acl_data_t *ad; void *data; { ad->mx_cidr = *(int *)data; return; } char * acl_print_mx(ad, buf, len) acl_data_t *ad; char *buf; size_t len; { snprintf(buf, len, "/%d", ad->mx_cidr); return buf; } #endif #ifdef USE_CURL void acl_add_urlcheck(ad, data) acl_data_t *ad; void *data; { char *urlcheck = data; if ((ad->urlcheck = urlcheck_byname(urlcheck)) == NULL) { mg_log(LOG_ERR, "unknown URL check \"%s\"", urlcheck); exit(EX_DATAERR); } return; } char * acl_print_urlcheck(ad, buf, len) acl_data_t *ad; char *buf; size_t len; { snprintf(buf, len, "\"%s\"", ad->urlcheck->u_name); return buf; } #endif #ifdef USE_LDAP void acl_add_ldapcheck(ad, data) acl_data_t *ad; void *data; { char *name = data; if ((ad->ldapcheck = ldapcheck_byname(name)) == NULL) { mg_log(LOG_ERR, "unknown LDAP check \"%s\"", name); exit(EX_DATAERR); } return; } char * acl_print_ldapcheck(ad, buf, len) acl_data_t *ad; char *buf; size_t len; { snprintf(buf, len, "\"%s\"", ad->ldapcheck->lce_url); return buf; } #endif void acl_add_prop_string(ad, data) acl_data_t *ad; void *data; { struct prop_data *upd; upd = (struct prop_data *)data; if ((ad->prop = malloc(sizeof(*ad->prop))) == NULL) { mg_log(LOG_ERR, "acl malloc failed: %s", strerror(errno)); exit(EX_OSERR); } if ((ad->prop->upd_name = strdup(upd->upd_name + 1)) == NULL) { mg_log(LOG_ERR, "acl strdup failed: %s", strerror(errno)); exit(EX_OSERR); } if ((ad->prop->upd_data = malloc(sizeof(acl_data_t))) == NULL) { mg_log(LOG_ERR, "acl malloc failed: %s", strerror(errno)); exit(EX_OSERR); } memset(ad->prop->upd_data, 0, sizeof(acl_data_t)); acl_add_string((void *)ad->prop->upd_data, upd->upd_data); return; } void acl_add_prop_pop(ad, data) acl_data_t *ad; void *data; { struct acl_prop_pop *apop = (struct acl_prop_pop *)data; if ((ad->apop = malloc(sizeof(*ad->apop))) == NULL) { mg_log(LOG_ERR, "acl malloc failed: %s", strerror(errno)); exit(EX_OSERR); } if ((ad->apop->apop_rhs = strdup(apop->apop_rhs)) == NULL) { mg_log(LOG_ERR, "acl strdup failed: %s", strerror(errno)); exit(EX_OSERR); } ad->apop->apop_op = apop->apop_op; if ((ad->apop->apop_lhs = strdup(apop->apop_lhs)) == NULL) { mg_log(LOG_ERR, "acl strdup failed: %s", strerror(errno)); exit(EX_OSERR); } } void acl_add_prop_opnum(ad, data) acl_data_t *ad; void *data; { struct prop_data *upd; upd = (struct prop_data *)data; if ((ad->prop = malloc(sizeof(*ad->prop))) == NULL) { mg_log(LOG_ERR, "acl malloc failed: %s", strerror(errno)); exit(EX_OSERR); } if ((ad->prop->upd_name = strdup(upd->upd_name + 1)) == NULL) { mg_log(LOG_ERR, "acl strdup failed: %s", strerror(errno)); exit(EX_OSERR); } if ((ad->prop->upd_data = malloc(sizeof(acl_data_t))) == NULL) { mg_log(LOG_ERR, "acl malloc failed: %s", strerror(errno)); exit(EX_OSERR); } memset(ad->prop->upd_data, 0, sizeof(acl_data_t)); acl_add_opnum((void *)ad->prop->upd_data, upd->upd_data); return; } void acl_add_prop_regex(ad, data) acl_data_t *ad; void *data; { struct prop_data *upd; upd = (struct prop_data *)data; if ((ad->prop = malloc(sizeof(*ad->prop))) == NULL) { mg_log(LOG_ERR, "acl malloc failed: %s", strerror(errno)); exit(EX_OSERR); } if ((ad->prop->upd_name = strdup(upd->upd_name + 1)) == NULL) { mg_log(LOG_ERR, "acl strdup failed: %s", strerror(errno)); exit(EX_OSERR); } if ((ad->prop->upd_data = malloc(sizeof(acl_data_t))) == NULL) { mg_log(LOG_ERR, "acl malloc failed: %s", strerror(errno)); exit(EX_OSERR); } memset(ad->prop->upd_data, 0, sizeof(acl_data_t)); acl_add_regex((void *)ad->prop->upd_data, upd->upd_data); return; } char * acl_print_prop_string(ad, buf, len) acl_data_t *ad; char *buf; size_t len; { size_t written; written = snprintf(buf, len, "$%s ", ad->prop->upd_name); acl_print_string(ad->prop->upd_data, buf + written, len - written); return buf; } char * acl_print_prop_pop(ad, buf, len) acl_data_t *ad; char *buf; size_t len; { snprintf(buf, len, "$%s %s $%s ", ad->apop->apop_lhs, acl_print_op(ad->apop->apop_op), ad->apop->apop_rhs); return buf; } char * acl_print_prop_opnum(ad, buf, len) acl_data_t *ad; char *buf; size_t len; { size_t written; written = snprintf(buf, len, "$%s ", ad->prop->upd_name); acl_print_opnum(ad->prop->upd_data, buf + written, len - written); return buf; } char * acl_print_prop_regex(ad, buf, len) acl_data_t *ad; char *buf; size_t len; { size_t written; written = snprintf(buf, len, "$%s ", ad->prop->upd_name); acl_print_regex(ad->prop->upd_data, buf + written, len - written); return buf; } void acl_free_prop_string(ad) acl_data_t *ad; { acl_free_string((void *)&ad->prop->upd_data); free(ad->prop->upd_data); free(ad->prop->upd_name); free(ad->prop); return; } void acl_free_prop_opnum(ad) acl_data_t *ad; { free(ad->prop->upd_data); free(ad->prop->upd_name); free(ad->prop); return; } void acl_free_prop_pop(ad) acl_data_t *ad; { free(ad->apop->apop_rhs); free(ad->apop->apop_lhs); free(ad->apop); return; } void acl_free_prop_regex(ad) acl_data_t *ad; { acl_free_regex((void *)&ad->prop->upd_data); free(ad->prop->upd_data); free(ad->prop->upd_name); free(ad->prop); return; } #ifdef USE_NSUPDATE void acl_add_nsupdate(ad, data) acl_data_t *ad; void *data; { ad->nsupdate = (struct nsupdate_entry *)data; } char * acl_print_nsupdate(ad, buf, len) acl_data_t *ad; char *buf; size_t len; { (void)snprintf(buf, len, "$%s ", ad->nsupdate->nse_name); return buf; } #endif void acl_add_macro(ad, data) acl_data_t *ad; void *data; { char *macro = data; if ((ad->macro = macro_byname(macro)) == NULL) { mg_log(LOG_ERR, "unknown sm_macro \"%s\"", macro); exit(EX_DATAERR); } return; } char * acl_print_macro(ad, buf, len) acl_data_t *ad; char *buf; size_t len; { snprintf(buf, len, "\"%s\"", ad->macro->m_name); return buf; } void acl_negate_clause(void) { gneg = NEGATED; if (conf.c_debug || conf.c_acldebug) mg_log(LOG_DEBUG, "load negation"); return; } void acl_add_clause(type, data) acl_clause_t type; void *data; { struct acl_clause *ac; struct acl_clause *cac; struct acl_clause_rec *acr; acr = get_acl_clause_rec(type); if ((ac = malloc(sizeof(*ac))) == NULL) { mg_log(LOG_ERR, "acl malloc failed: %s", strerror(errno)); exit(EX_OSERR); } if (acr->acr_unicity == UNIQUE) { TAILQ_FOREACH(cac, &gacl->a_clause, ac_list) { if (cac->ac_type == type) { mg_log(LOG_ERR, "Multiple %s clauses in ACL line %d", acr->acr_name, conf_line); exit(EX_DATAERR); } } } ac->ac_type = type; ac->ac_negation = gneg; gneg = PLAIN; ac->ac_acr = acr; if (acr->acr_add != NULL) (*acr->acr_add)(&ac->ac_data, data); TAILQ_INSERT_TAIL(&gacl->a_clause, ac, ac_list); /* * Lists deserve a special treatment: the clause is parsed with * a generic type AC_LIST, and we need to lookup the real list type */ if (ac->ac_type == AC_LIST) { if (conf.c_debug || conf.c_acldebug) { char tmpbuf[64]; mg_log(LOG_DEBUG, "switching ACL clause %s from type %s to %s", (*acr->acr_print) (&ac->ac_data, tmpbuf, sizeof(tmpbuf)), acr->acr_name, ac->ac_data.list->al_acr->acr_name); } ac->ac_type = ac->ac_data.list->al_acr->acr_type; ac->ac_acr = ac->ac_data.list->al_acr; } if (conf.c_debug || conf.c_acldebug) { char tmpbuf[64]; mg_log(LOG_DEBUG, "load acl %s %s", acr->acr_name, (*acr->acr_print)(&ac->ac_data, tmpbuf, sizeof(tmpbuf))); } if (conf.c_maxpeek == 0) conf.c_maxpeek = -1; return; } struct acl_entry * acl_register_entry_first(acl_stage, acl_type)/* acllist must be write-locked */ acl_stage_t acl_stage; acl_type_t acl_type; { struct acl_entry *acl; struct acl_clause *ac; TAILQ_FOREACH(ac, &gacl->a_clause, ac_list) { if (ac->ac_acr->acr_stage == AS_ANY) continue; if (ac->ac_acr->acr_stage != acl_stage) { char b[1024]; mg_log(LOG_ERR, "%s %s clause should be used in %s " "stage and is present %s stage ACL line %d", ac->ac_acr->acr_name, (*ac->ac_acr->acr_print) (&ac->ac_data, b, sizeof(b)), stage_string(ac->ac_acr->acr_stage), stage_string(acl_stage), conf_line - 1); exit(EX_DATAERR); } } if (acl_stage == AS_DATA) { if (conf_dacl_end != 0) mg_log(LOG_WARNING, "ignored dacl entry after dacl " "default rule at line %d", conf_line - 1); if (conf_acl_end != 0) { conf_dacl_end = 1; conf_acl_end = 0; } } else { if (conf_racl_end != 0) mg_log(LOG_WARNING, "ignored racl entry after racl " "default rule at line %d", conf_line - 1); if (conf_acl_end != 0) { conf_racl_end = 1; conf_acl_end = 0; } } if (gacl->a_flags & A_DROP_ACL) { acl_free_entry(gacl); gacl = acl_init_entry(); if (conf.c_debug || conf.c_acldebug) mg_log(LOG_DEBUG, "Drop ACL %d", conf_line - 1); return NULL; } acl = gacl; acl->a_type = acl_type; acl->a_stage = acl_stage; acl->a_line = conf_line - 1; TAILQ_INSERT_HEAD(&acl_head, acl, a_list); gacl = acl_init_entry(); if (conf.c_debug || conf.c_acldebug) { switch(acl_type) { case A_GREYLIST: mg_log(LOG_DEBUG, "register acl first GREYLIST"); break; case A_WHITELIST: mg_log(LOG_DEBUG, "register acl first WHITELIST"); break; case A_BLACKLIST: mg_log(LOG_DEBUG, "register acl first BLACKLIST"); break; case A_CONTINUE: mg_log(LOG_DEBUG, "register acl first CONTINUE"); break; default: mg_log(LOG_ERR, "unexpected acl_type %d", acl_type); exit(EX_SOFTWARE); break; } } return acl; } struct acl_entry * acl_register_entry_last(acl_stage, acl_type)/* acllist must be write-locked */ acl_stage_t acl_stage; acl_type_t acl_type; { struct acl_entry *acl; struct acl_clause *ac; TAILQ_FOREACH(ac, &gacl->a_clause, ac_list) { if (ac->ac_acr->acr_stage == AS_ANY) continue; if (ac->ac_acr->acr_stage != acl_stage) { char b[1024]; mg_log(LOG_ERR, "%s %s clause should be used in %s " "stage and is present %s stage ACL line %d", ac->ac_acr->acr_name, (*ac->ac_acr->acr_print) (&ac->ac_data, b, sizeof(b)), stage_string(ac->ac_acr->acr_stage), stage_string(acl_stage), conf_line - 1); exit(EX_DATAERR); } } if (acl_stage == AS_DATA) { if (conf_dacl_end != 0) mg_log(LOG_WARNING, "ignored dacl entry after dacl " "default rule at line %d", conf_line - 1); if (conf_acl_end != 0) { conf_dacl_end = 1; conf_acl_end = 0; } } else { if (conf_racl_end != 0) mg_log(LOG_WARNING, "ignored racl entry after racl " "default rule at line %d", conf_line - 1); if (conf_acl_end != 0) { conf_racl_end = 1; conf_acl_end = 0; } } if (gacl->a_flags & A_DROP_ACL) { acl_free_entry(gacl); gacl = acl_init_entry(); if (conf.c_debug || conf.c_acldebug) mg_log(LOG_DEBUG, "Drop ACL %d", conf_line - 1); return NULL; } acl = gacl; acl->a_stage = acl_stage; acl->a_type = acl_type; acl->a_line = conf_line - 1; TAILQ_INSERT_TAIL(&acl_head, acl, a_list); gacl = acl_init_entry(); if (conf.c_debug || conf.c_acldebug) { switch(acl_type) { case A_GREYLIST: mg_log(LOG_DEBUG, "register acl last GREYLIST"); break; case A_WHITELIST: mg_log(LOG_DEBUG, "register acl last WHITELIST"); break; case A_BLACKLIST: mg_log(LOG_DEBUG, "register acl last BLACKLIST"); break; case A_CONTINUE: mg_log(LOG_DEBUG, "register acl last CONTINUE"); break; default: mg_log(LOG_ERR, "unexpected acl_type %d", acl_type); exit(EX_SOFTWARE); break; } } return acl; } static int acl_actions(priv, stage, acl, ap, retval) struct mlfi_priv *priv; acl_stage_t stage; struct acl_entry *acl; struct acl_param *ap; int retval; { struct sockaddr *sa; socklen_t salen; char addrstr[IPADDRSTRLEN]; sa = SA(&priv->priv_addr); salen = priv->priv_addrlen; if (retval == 0) retval = EXF_DEFAULT; switch (ap->ap_type) { case A_GREYLIST: retval |= EXF_GREYLIST; break; case A_WHITELIST: retval |= EXF_WHITELIST; break; case A_BLACKLIST: retval |= EXF_BLACKLIST; break; case A_CONTINUE: break; default: mg_log(LOG_ERR, "corrupted acl list"); exit(EX_SOFTWARE); break; } priv->priv_sr.sr_acl_line = acl->a_line; priv->priv_sr.sr_delay = (ap->ap_delay != -1) ? ap->ap_delay : conf.c_delay; priv->priv_sr.sr_autowhite = (ap->ap_autowhite != -1) ? ap->ap_autowhite : conf.c_autowhite_validity; priv->priv_sr.sr_tarpit = (ap->ap_tarpit != -1) ? ap->ap_tarpit : conf.c_tarpit; priv->priv_sr.sr_tarpit_scope = (ap->ap_tarpit_scope != -1) ? ap->ap_tarpit_scope : conf.c_tarpit_scope; if (ap->ap_tarpitted > priv->priv_max_tarpitted) priv->priv_max_tarpitted = ap->ap_tarpitted; if (ap->ap_tarpitted > priv->priv_total_tarpitted) priv->priv_total_tarpitted = ap->ap_tarpitted; if (ap->ap_id) { priv->priv_sr.sr_acl_id = strdup(ap->ap_id); if (priv->priv_sr.sr_acl_id == NULL) { mg_log(LOG_ERR, "strdup failed: %s", strerror(errno)); exit(EX_OSERR); } } if (ap->ap_code) { priv->priv_sr.sr_code = strdup(ap->ap_code); if (priv->priv_sr.sr_code == NULL) { mg_log(LOG_ERR, "strdup failed: %s", strerror(errno)); exit(EX_OSERR); } } if (ap->ap_ecode) { priv->priv_sr.sr_ecode = strdup(ap->ap_ecode); if (priv->priv_sr.sr_ecode == NULL) { mg_log(LOG_ERR, "strdup failed: %s", strerror(errno)); exit(EX_OSERR); } } if (ap->ap_msg) { priv->priv_sr.sr_msg = strdup(ap->ap_msg); if (priv->priv_sr.sr_msg == NULL) { mg_log(LOG_ERR, "strdup failed"); exit(EX_OSERR); } } if (ap->ap_report) { priv->priv_sr.sr_report = strdup(ap->ap_report); if (priv->priv_sr.sr_report == NULL) { mg_log(LOG_ERR, "strdup failed"); exit(EX_OSERR); } } if (ap->ap_addheader) { priv->priv_sr.sr_addheader = strdup(ap->ap_addheader); if (priv->priv_sr.sr_addheader == NULL) { mg_log(LOG_ERR, "strdup failed"); exit(EX_OSERR); } } if (ap->ap_addfooter) { priv->priv_sr.sr_addfooter = strdup(ap->ap_addfooter); if (priv->priv_sr.sr_addfooter == NULL) { mg_log(LOG_ERR, "strdup failed"); exit(EX_OSERR); } (void)fstring_escape(priv->priv_sr.sr_addfooter); } if (ap->ap_subjtag) { priv->priv_sr.sr_subjtag = strdup(ap->ap_subjtag); if (priv->priv_sr.sr_subjtag == NULL) { mg_log(LOG_ERR, "strdup failed"); exit(EX_OSERR); } } if (stage == AS_RCPT) priv->priv_maxpeek = ap->ap_maxpeek; priv->priv_sr.sr_nmatch = ap->ap_nmatch; priv->priv_sr.sr_pmatch = ap->ap_pmatch; /* Free temporary memory if nescessary */ if (ap->ap_flags & A_FREE_ID) free(ap->ap_id); if (ap->ap_flags & A_FREE_CODE) free(ap->ap_code); if (ap->ap_flags & A_FREE_ECODE) free(ap->ap_ecode); if (ap->ap_flags & A_FREE_MSG) free(ap->ap_msg); if (ap->ap_flags & A_FREE_REPORT) free(ap->ap_report); if (ap->ap_flags & A_FREE_ADDHEADER) free(ap->ap_addheader); if (ap->ap_flags & A_FREE_ADDFOOTER) free(ap->ap_addfooter); if (ap->ap_flags & A_FREE_SUBJTAG) free(ap->ap_subjtag); if (ap->ap_flags & A_FLUSHADDR) { struct tuple_fields tuple; tuple.sa = sa; tuple.salen = salen; tuple.queueid = priv->priv_queueid; tuple.acl_line = acl->a_line; mg_tuple_remove(&tuple); } if (ap->ap_flags & A_NOLOG) retval |= EXF_NOLOG; if (conf.c_debug || conf.c_acldebug) { char aclstr[HDRLEN + 1]; iptostring(sa, salen, addrstr, sizeof(addrstr)); mg_log(LOG_DEBUG, "Mail from=%s, rcpt=%s, addr=%s[%s] " "is matched by entry %s", priv->priv_from, (priv->priv_cur_rcpt[0] != '\0') ? priv->priv_cur_rcpt : "(nil)", priv->priv_hostname, addrstr, acl_entry(aclstr, HDRLEN, acl)); } return retval; } int acl_filter(stage, ctx, priv) acl_stage_t stage; SMFICTX *ctx; struct mlfi_priv *priv; { struct sockaddr *sa; socklen_t salen; char *hostname; char *from; char *queueid; struct acl_entry *acl; char addrstr[IPADDRSTRLEN]; char whystr[HDRLEN]; char tmpstr[HDRLEN]; char *aclstr; int error = -1; long long retval = 0; long long noretval = 0; char *notstr = " not"; char *vstr = ""; int found; int testmode = conf.c_testmode; struct acl_param ap; char *cur_rcpt; struct acl_clause *ac; #ifdef USE_GEOIP const char *ccode = "??"; #endif sa = SA(&priv->priv_addr); salen = priv->priv_addrlen; hostname = priv->priv_hostname; from = priv->priv_from; queueid = priv->priv_queueid; cur_rcpt = priv->priv_cur_rcpt; #ifdef USE_GEOIP if (priv->priv_ccode != NULL) { ccode = priv->priv_ccode; } #endif ACL_RDLOCK; ap.ap_nmatch = 0; ap.ap_pmatch = NULL; /* * Run through all ACL entries */ TAILQ_FOREACH(acl, &acl_head, a_list) { if (acl->a_stage != stage) continue; /* * Keep track of current ACL for %cA and %ca format strings */ priv->priv_acl = acl; retval = 0; noretval = 0; found = -1; ap.ap_type = acl->a_type; ap.ap_delay = acl->a_delay; ap.ap_autowhite = acl->a_autowhite; ap.ap_tarpit = acl->a_tarpit; ap.ap_tarpitted = -1; ap.ap_tarpit_scope = acl->a_tarpit_scope; ap.ap_flags = acl->a_flags; ap.ap_id = acl->a_id; ap.ap_code = acl->a_code; ap.ap_ecode = acl->a_ecode; ap.ap_msg = acl->a_msg; ap.ap_report = acl->a_report; ap.ap_addheader = acl->a_addheader; ap.ap_addfooter = acl->a_addfooter; ap.ap_subjtag = acl->a_subjtag; ap.ap_maxpeek = acl->a_maxpeek; /* * Free pointers to stored parenthesized substrings * before each ACL entry. */ if (ap.ap_pmatch) { int i; for (i = 0; i < ap.ap_nmatch; i++) if (ap.ap_pmatch[i] != NULL) free(ap.ap_pmatch[i]); free(ap.ap_pmatch); } ap.ap_nmatch = 0; ap.ap_pmatch = NULL; /* * Run through all clauses of ACL entry */ TAILQ_FOREACH(ac, &acl->a_clause, ac_list) { if ((found = (*ac->ac_acr->acr_filter) (&ac->ac_data, stage, &ap, priv)) == -1) goto out; if (ac->ac_negation == NEGATED) found = (found == 0) ? 1 : 0; /* * All clauses of an ACL entry need to match, so * exit when not found. */ if (found == 0) break; retval |= ac->ac_acr->acr_exf; if (ac->ac_negation == NEGATED) noretval |= ac->ac_acr->acr_exf; } /* * If the ACl matched, apply actions. * Then exit evaluation if it was not a continue ACL */ if (found != 0) { retval = acl_actions(priv, stage, acl, &ap, retval); if (ap.ap_type != A_CONTINUE) break; } } if (acl == NULL) { /* * No match: use the default action */ if (testmode) retval = EXF_WHITELIST; else if (stage == AS_DATA) retval = EXF_WHITELIST | EXF_NOLOG; else retval = EXF_GREYLIST; retval |= EXF_DEFAULT; priv->priv_sr.sr_delay = conf.c_delay; priv->priv_sr.sr_autowhite = conf.c_autowhite_validity; priv->priv_sr.sr_tarpit = conf.c_tarpit; priv->priv_sr.sr_tarpit_scope = conf.c_tarpit_scope; } if ((retval & EXF_NOLOG) == 0 && retval & EXF_WHITELIST) { whystr[0] = '\0'; if (retval & EXF_ADDR) { iptostring(sa, salen, addrstr, sizeof(addrstr)); snprintf(tmpstr, sizeof(tmpstr), "address %s is whitelisted", addrstr); ADD_REASON(whystr, tmpstr); } if (retval & EXF_DNSRBL) { iptostring(sa, salen, addrstr, sizeof(addrstr)); snprintf(tmpstr, sizeof(tmpstr), "address %s is%s in DNSRBL", addrstr, (noretval & EXF_DNSRBL) ? notstr : vstr); ADD_REASON(whystr, tmpstr); } if (retval & EXF_MX) { iptostring(sa, salen, addrstr, sizeof(addrstr)); snprintf(tmpstr, sizeof(tmpstr), "address %s %s MX record", addrstr, (noretval & EXF_MX) ? "does not match" : "matches"); ADD_REASON(whystr, tmpstr); } if (retval & EXF_URLCHECK) { iptostring(sa, salen, addrstr, sizeof(addrstr)); snprintf(tmpstr, sizeof(tmpstr), "URL check%s passed", (noretval & EXF_URLCHECK) ? notstr : vstr); ADD_REASON(whystr, tmpstr); } if (retval & EXF_DOMAIN) { snprintf(tmpstr, sizeof(tmpstr), "sender DNS name %s is whitelisted", hostname); ADD_REASON(whystr, tmpstr); } if (retval & EXF_FROM) { snprintf(tmpstr, sizeof(tmpstr), "sender %s is whitelisted", from); ADD_REASON(whystr, tmpstr); } if (retval & EXF_RCPT) { if (cur_rcpt[0] != '\0') { snprintf(tmpstr, sizeof(tmpstr), "recipient %s is whitelisted", cur_rcpt); } else { snprintf(tmpstr, sizeof(tmpstr), "at least one recipient is whitelisted"); } ADD_REASON(whystr, tmpstr); } if (retval & EXF_MACRO) { snprintf(tmpstr, sizeof(tmpstr), "macro rule is%s satisfied", (noretval & EXF_MACRO) ? notstr : vstr); ADD_REASON(whystr, tmpstr); } #ifdef USE_GEOIP if (retval & EXF_GEOIP) { snprintf(tmpstr, sizeof(tmpstr), "geoip ccode %s is%s whitelisted", ccode, (noretval & EXF_GEOIP) ? notstr : vstr); ADD_REASON(whystr, tmpstr); } #endif #if (defined(HAVE_SPF) || defined(HAVE_SPF_ALT) || \ defined(HAVE_SPF2_10) || defined(HAVE_SPF2)) if (retval & EXF_SPF) { snprintf(tmpstr, sizeof(tmpstr), "sender is%s SPF-compliant", (noretval & EXF_SPF) ? notstr : vstr); ADD_REASON(whystr, tmpstr); } #endif #ifdef USE_DKIM if (retval & EXF_DKIM) { snprintf(tmpstr, sizeof(tmpstr), "sender is%s DKIM-compliant", (noretval & EXF_DKIM) ? notstr : vstr); ADD_REASON(whystr, tmpstr); } #endif if (retval & EXF_TARPIT) { snprintf(tmpstr, sizeof(tmpstr), "tarpit is%s requested", (noretval & EXF_TARPIT) ? notstr : vstr); ADD_REASON(whystr, tmpstr); } if (retval & EXF_DEFAULT) { ADD_REASON(whystr, "this is the default action"); } iptostring(sa, salen, addrstr, sizeof(addrstr)); aclstr = fstring_expand(priv, NULL, "%a", NULL); snprintf(tmpstr, sizeof(tmpstr), "(from=%s, rcpt=%s, addr=%s[%s]) ACL %s", from, (cur_rcpt[0] != '\0') ? cur_rcpt : "(nil)", hostname, addrstr, aclstr); free(aclstr); ADD_REASON(whystr, tmpstr); mg_log(LOG_INFO, "%s: skipping greylist because %s", queueid, whystr); } error = 0; out: ACL_UNLOCK; priv->priv_sr.sr_whitelist = retval; return error; } int emailcmp(big, little) char *big; char *little; { int i; int retval = -1; char *cbig; char *clittle; char *ocbig; char *oclittle; if ((cbig = malloc(strlen(big) + 1)) == NULL) { mg_log(LOG_ERR, "malloc failed: %s", strerror(errno)); exit(EX_OSERR); } ocbig = cbig; strcpy(cbig, big); if ((clittle = malloc(strlen(little) + 1)) == NULL) { mg_log(LOG_ERR, "malloc failed: %s", strerror(errno)); exit(EX_OSERR); } oclittle = clittle; strcpy(clittle, little); /* Strip leading <, tabs and spaces */ while (strchr("< \t", cbig[0]) != NULL) cbig++; while (strchr("< \t", clittle[0]) != NULL) clittle++; /* Strip trailing >, tabs and spaces */ i = strlen(cbig) - 1; while ((i >= 0) && (strchr("> \t", cbig[i]) != NULL)) cbig[i--] = '\0'; i = strlen(clittle) - 1; while ((i >= 0) && (strchr("> \t", clittle[i]) != NULL)) clittle[i--] = '\0'; while (cbig[0] && clittle[0]) { if (tolower((int)cbig[0]) != tolower((int)clittle[0])) break; cbig++; clittle++; } if (cbig[0] || clittle[0]) retval = -1; else retval = 0; free(ocbig); free(oclittle); return retval; } void acl_clear(void) { /* acllist must be write locked */ struct acl_entry *acl; while (!TAILQ_EMPTY(&acl_head)) { acl = TAILQ_FIRST(&acl_head); TAILQ_REMOVE(&acl_head, acl, a_list); acl_free_entry(acl); } return; } char * acl_entry(entrystr, len, acl) char *entrystr; size_t len; struct acl_entry *acl; { char tempstr[HDRLEN]; int def = 1; struct acl_clause *ac; switch (acl->a_stage) { case AS_RCPT: snprintf(entrystr, len, "racl %d ", acl->a_line); break; case AS_DATA: snprintf(entrystr, len, "dacl %d ", acl->a_line); break; default: mg_log(LOG_ERR, "unexpected stage %d", acl->a_stage); exit(EX_SOFTWARE); break; } switch (acl->a_type) { case A_GREYLIST: mystrlcat(entrystr, "greylist ", len); break; case A_WHITELIST: mystrlcat(entrystr, "whitelist ", len); break; case A_BLACKLIST: mystrlcat(entrystr, "blacklist ", len); break; case A_CONTINUE: mystrlcat(entrystr, "continue ", len); break; default: mg_log(LOG_ERR, "corrupted acl list"); exit(EX_SOFTWARE); break; } if (acl->a_id) { snprintf(tempstr, sizeof(tempstr), "\"%s\" ", acl->a_id); mystrlcat(entrystr, tempstr, len); } TAILQ_FOREACH(ac, &acl->a_clause, ac_list) { char tempstr2[HDRLEN]; acl_data_t *ad; char *notstr = "not "; char *vstr = ""; ad = &ac->ac_data; snprintf(tempstr, sizeof(tempstr), "%s%s %s ", (ac->ac_negation == NEGATED) ? notstr : vstr, ac->ac_acr->acr_name, (*ac->ac_acr->acr_print)(ad, tempstr2, sizeof(tempstr2))); mystrlcat(entrystr, tempstr, len); def = 0; } if (acl->a_delay != -1) { snprintf(tempstr, sizeof(tempstr), "[delay %ld] ", (long)acl->a_delay); mystrlcat(entrystr, tempstr, len); } if (acl->a_autowhite != -1) { snprintf(tempstr, sizeof(tempstr), "[aw %ld] ", (long)acl->a_autowhite); mystrlcat(entrystr, tempstr, len); } if (acl->a_tarpit_scope != -1) { snprintf(tempstr, sizeof(tempstr), "[tarpit-scope \"%s\"] ", (acl->a_tarpit_scope == TAP_SESSION) ? "session" : "command"); mystrlcat(entrystr, tempstr, len); } if (acl->a_flags & A_FLUSHADDR) { snprintf(tempstr, sizeof(tempstr), "[flushaddr] "); mystrlcat(entrystr, tempstr, len); } if (acl->a_flags & A_NOLOG) { snprintf(tempstr, sizeof(tempstr), "[nolog] "); mystrlcat(entrystr, tempstr, len); } if (acl->a_code) { snprintf(tempstr, sizeof(tempstr), "[code \"%s\"] ", acl->a_code); mystrlcat(entrystr, tempstr, len); } if (acl->a_ecode) { snprintf(tempstr, sizeof(tempstr), "[ecode \"%s\"] ", acl->a_ecode); mystrlcat(entrystr, tempstr, len); } if (acl->a_msg) { snprintf(tempstr, sizeof(tempstr), "[msg \"%s\"] ", acl->a_msg); mystrlcat(entrystr, tempstr, len); } if (acl->a_report) { snprintf(tempstr, sizeof(tempstr), "[report \"%s\"] ", acl->a_report); mystrlcat(entrystr, tempstr, len); } if (acl->a_addheader) { snprintf(tempstr, sizeof(tempstr), "[addheader \"%s\"] ", acl->a_addheader); mystrlcat(entrystr, tempstr, len); } if (acl->a_addfooter) { snprintf(tempstr, sizeof(tempstr), "[addfooter \"%s\"] ", acl->a_addfooter); mystrlcat(entrystr, tempstr, len); } if (acl->a_subjtag) { snprintf(tempstr, sizeof(tempstr), "[subjtag \"%s\"] ", acl->a_subjtag); mystrlcat(entrystr, tempstr, len); } if (acl->a_maxpeek) { snprintf(tempstr, sizeof(tempstr), "[maxpeek %d] ", acl->a_maxpeek); mystrlcat(entrystr, tempstr, len); } if (def) mystrlcat(entrystr, "default", len); return entrystr; } void acl_dump (void) { /* acllist must be write locked */ struct acl_entry *acl; char *entry; FILE *debug = NULL; /* * We log the ACL to syslogd * We can also write the ACL in a file because syslogd seems to lose * some debugging messages on FreeBSD 4.10 :-( * XXX This is disabled by default (#if 0 above) since it creates * security hazards: /tmp/access-list.debug could already exist and * be a link to some system file which would be overwritten. * Enable it if you need it, but you may be better changing the path */ #if 0 debug = Fopen("/tmp/access-list.debug", "w"); #endif ACL_RDLOCK; mg_log(LOG_INFO, "Access list dump:"); TAILQ_FOREACH(acl, &acl_head, a_list) { char aclstr[HDRLEN + 11]; entry = acl_entry(aclstr, HDRLEN, acl); mg_log(LOG_INFO, "%s", entry); if (debug != NULL) fprintf(debug, "%s", entry); } ACL_UNLOCK; if (debug != NULL) Fclose(debug); } void acl_add_delay(delay) time_t delay; { if (gacl->a_delay != -1) { mg_log(LOG_ERR, "delay specified twice in ACL line %d", conf_line); exit(EX_DATAERR); } gacl->a_delay = delay; if (conf.c_debug || conf.c_acldebug) mg_log(LOG_DEBUG, "load acl delay %ld", (long)delay); return; } void acl_add_autowhite(delay) time_t delay; { if (gacl->a_autowhite != -1) { mg_log(LOG_ERR, "autowhite specified twice in ACL line %d", conf_line); exit(EX_DATAERR); } gacl->a_autowhite = delay; if (conf.c_debug || conf.c_acldebug) mg_log(LOG_DEBUG, "load acl autowhite %ld", (long)delay); return; } void acl_add_tarpit_scope(scope) tarpit_scope_t scope; { if (gacl->a_tarpit_scope != -1) { mg_log(LOG_ERR, "tarpit_scope specified twice in ACL line %d", conf_line); exit(EX_DATAERR); } gacl->a_tarpit_scope = scope; if (conf.c_debug || conf.c_acldebug) mg_log(LOG_DEBUG, "load acl tarpit_scope %s", (scope == TAP_SESSION) ? "session" : "command"); return; } void acl_add_list(ad, data) acl_data_t *ad; void *data; { char *list = data; struct all_list_entry *ale; struct acl_clause *cac; if ((ale = all_list_byname(list)) == NULL) { mg_log(LOG_ERR, "nonexistent list \"%s\" line %d", list, conf_line); exit(EX_DATAERR); } TAILQ_FOREACH(cac, &gacl->a_clause, ac_list) { if (cac->ac_acr->acr_list_type != ale->al_acr->acr_type) continue; if (cac->ac_acr->acr_unicity == UNIQUE) { mg_log(LOG_ERR, "multiple %s statement (list \"%s\", line %d)", cac->ac_acr->acr_name, list, conf_line); exit(EX_DATAERR); } } ad->list = ale; return; } void acl_add_opnum_body(ad, data) acl_data_t *ad; void *data; { if (conf.c_maxpeek == 0) conf.c_maxpeek = -1; acl_add_opnum(ad, data); return; } void acl_add_opnum(ad, data) acl_data_t *ad; void *data; { struct acl_opnum_data *aod; aod = (struct acl_opnum_data *)data; ad->opnum.op = aod->op; ad->opnum.num = aod->num; } void acl_add_code(code) char *code; { if (gacl->a_code) { mg_log(LOG_ERR, "code specified twice in ACL line %d", conf_line); exit(EX_DATAERR); } if ((gacl->a_code = strdup(code)) == NULL) { mg_log(LOG_ERR, "malloc failed in ACL line %d", conf_line); exit(EX_OSERR); } if (conf.c_debug || conf.c_acldebug) mg_log(LOG_DEBUG, "load acl code \"%s\"", code); return; } void acl_add_id(id) char *id; { if (gacl->a_id) { mg_log(LOG_ERR, "id specified twice in ACL line %d", conf_line); exit(EX_DATAERR); } if ((gacl->a_id = strdup(id)) == NULL) { mg_log(LOG_ERR, "malloc failed in ACL line %d", conf_line); exit(EX_OSERR); } if (conf.c_debug || conf.c_acldebug) mg_log(LOG_DEBUG, "load acl id \"%s\"", id); return; } void acl_add_ecode(ecode) char *ecode; { if (gacl->a_ecode) { mg_log(LOG_ERR, "ecode specified twice in ACL line %d", conf_line); exit(EX_DATAERR); } if ((gacl->a_ecode = strdup(ecode)) == NULL) { mg_log(LOG_ERR, "malloc failed in ACL line %d", conf_line); exit(EX_OSERR); } if (conf.c_debug || conf.c_acldebug) mg_log(LOG_DEBUG, "load acl ecode \"%s\"", ecode); return; } void acl_add_msg(msg) char *msg; { if (gacl->a_msg) { mg_log(LOG_ERR, "msg specified twice in ACL line %d", conf_line); exit(EX_DATAERR); } if ((gacl->a_msg = strdup(msg)) == NULL) { mg_log(LOG_ERR, "malloc failed in ACL line %d", conf_line); exit(EX_OSERR); } if (conf.c_debug || conf.c_acldebug) mg_log(LOG_DEBUG, "load acl msg \"%s\"", msg); return; } void acl_add_report(report) char *report; { if (gacl->a_report) { mg_log(LOG_ERR, "report specified twice in ACL line %d", conf_line); exit(EX_DATAERR); } if ((gacl->a_report = strdup(report)) == NULL) { mg_log(LOG_ERR, "malloc failed in ACL line %d", conf_line); exit(EX_OSERR); } if (conf.c_debug || conf.c_acldebug) mg_log(LOG_DEBUG, "load acl report \"%s\"", report); return; } void acl_add_addheader(hdr) char *hdr; { if (gacl->a_addheader) { mg_log(LOG_ERR, "addheader specified twice in ACL line %d", conf_line); exit(EX_DATAERR); } if ((gacl->a_addheader = strdup(hdr)) == NULL) { mg_log(LOG_ERR, "malloc failed in ACL line %d", conf_line); exit(EX_OSERR); } if (conf.c_debug || conf.c_acldebug) mg_log(LOG_DEBUG, "load acl addheader \"%s\"", hdr); return; } void acl_add_addfooter(hdr) char *hdr; { if (gacl->a_addfooter) { mg_log(LOG_ERR, "addfooter specified twice in ACL line %d", conf_line); exit(EX_DATAERR); } if ((gacl->a_addfooter = strdup(hdr)) == NULL) { mg_log(LOG_ERR, "malloc failed in ACL line %d", conf_line); exit(EX_OSERR); } if (conf.c_debug || conf.c_acldebug) mg_log(LOG_DEBUG, "load acl addfooter \"%s\"", hdr); return; } void acl_add_subjtag(tag) char *tag; { if (gacl->a_subjtag) { mg_log(LOG_ERR, "subjtag specified twice in ACL line %d", conf_line); exit(EX_DATAERR); } if ((gacl->a_subjtag = strdup(tag)) == NULL) { mg_log(LOG_ERR, "malloc failed in ACL line %d", conf_line); exit(EX_OSERR); } if (conf.c_debug || conf.c_acldebug) mg_log(LOG_DEBUG, "load acl subjtag \"%s\"", tag); return; } void acl_add_maxpeek(maxpeek) int maxpeek; { gacl->a_maxpeek = maxpeek; if (conf.c_debug || conf.c_acldebug) mg_log(LOG_DEBUG, "load acl maxpeek %d", maxpeek); return; } void acl_maxpeek_fixup(maxpeek) int maxpeek; { gacl->a_maxpeek = maxpeek; return; } int acl_modify_by_prop(key, value, ap) char *key; char *value; struct acl_param *ap; { if (conf.c_acldebug) mg_log(LOG_DEBUG, "check got \"%s\" => \"%s\"", key, value); if (strcasecmp(key, "milterGreylistStatus") == 0) { if ((strcasecmp(value, "Ok") == 0) || (strcasecmp(value, "TRUE") == 0)) goto out; } if (strcasecmp(key, "milterGreylistAction") == 0) { if (strcasecmp(value, "greylist") == 0) ap->ap_type = A_GREYLIST; else if (strcasecmp(value, "blacklist") == 0) ap->ap_type = A_BLACKLIST; else if (strcasecmp(value, "whitelist") == 0) ap->ap_type = A_WHITELIST; else if (strcasecmp(value, "continue") == 0) ap->ap_type = A_CONTINUE; else mg_log(LOG_WARNING, "ignored greylist-type \"%s\"", value); goto out; } if (strcasecmp(key, "milterGreylistDelay") == 0) { ap->ap_delay = humanized_atoi(value); goto out; } if (strcasecmp(key, "milterGreylistAutowhite") == 0) { ap->ap_autowhite = humanized_atoi(value); goto out; } if (strcasecmp(key, "milterGreylistTarpit") == 0) { ap->ap_tarpit = humanized_atoi(value); goto out; } if (strcasecmp(key, "milterGreylistFlushAddr") == 0) { ap->ap_flags |= A_FLUSHADDR; goto out; } if (strcasecmp(key, "milterGreylistNoLog") == 0) { ap->ap_flags |= A_NOLOG; goto out; } if (strcasecmp(key, "milterGreylistCode") == 0) { if ((ap->ap_code = strdup(value)) == NULL) { mg_log(LOG_ERR, "strdup(\"%s\") failed: %s", key, strerror(errno)); exit(EX_OSERR); } ap->ap_flags |= A_FREE_CODE; goto out; } if (strcasecmp(key, "milterGreylistEcode") == 0) { if ((ap->ap_ecode = strdup(value)) == NULL) { mg_log(LOG_ERR, "strdup(\"%s\") failed: %s", key, strerror(errno)); exit(EX_OSERR); } ap->ap_flags |= A_FREE_ECODE; goto out; } if (strcasecmp(key, "milterGreylistMsg") == 0) { if ((ap->ap_msg = strdup(value)) == NULL) { mg_log(LOG_ERR, "strdup(\"%s\") failed: %s", key, strerror(errno)); exit(EX_OSERR); } ap->ap_flags |= A_FREE_MSG; goto out; } if (strcasecmp(key, "milterGreylistReport") == 0) { if ((ap->ap_report = strdup(value)) == NULL) { mg_log(LOG_ERR, "strdup(\"%s\") failed: %s", key, strerror(errno)); exit(EX_OSERR); } ap->ap_flags |= A_FREE_REPORT; goto out; } if (strcasecmp(key, "milterGreylistIgnore") == 0) goto out; if (conf.c_acldebug) mg_log(LOG_DEBUG, "acl_modify inexpected property " "\"%s\"=\"%s\"", key, value); return -1; out: if (conf.c_acldebug) mg_log(LOG_DEBUG, "modified acl property " "\"%s\"=\"%s\"", key, value); return 0; } int acl_log_string(ad, stage, ap, priv) acl_data_t *ad; acl_stage_t stage; struct acl_param *ap; struct mlfi_priv *priv; { char *string; string = fstring_expand(priv, NULL, ad->string, NULL); mg_log(LOG_INFO, string); free(string); /* always match */ return 1; } @ 1.112 log @Accept format strings in helo acl and compare without case (Jim Klimov) @ text @d1 1 a1 1 /* $Id: acl.c,v 1.111 2013/09/01 04:59:42 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.111 2013/09/01 04:59:42 manu Exp $"); d331 4 @ 1.111 log @ Add %cA and %ca to report current ACL line number and id Increase format string maximum length to 4096 Break long SMTP replies in mutiple lines @ text @d1 1 a1 1 /* $Id: acl.c,v 1.110 2013/08/27 13:50:44 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.110 2013/08/27 13:50:44 manu Exp $"); d910 16 a925 1 char *helo = ad->string; d927 22 a948 4 printf("-> %s/%s\n", priv->priv_helo, helo); if (strstr(priv->priv_helo, helo) != NULL) return 1; return 0; @ 1.110 log @Numeric operator tests for property versus number Numeric operator tests for property versus property @ text @d1 1 a1 1 /* $Id: acl.c,v 1.109 2013/08/18 11:06:57 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.109 2013/08/18 11:06:57 manu Exp $"); d2362 5 @ 1.109 log @Fix memory leak in log ACL clause @ text @d1 1 a1 1 /* $Id: acl.c,v 1.108 2013/08/18 04:45:30 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.108 2013/08/18 04:45:30 manu Exp $"); d157 2 d161 2 d165 2 d327 2 a328 2 { AC_PROP, MULTIPLE_OK, AS_ANY, "prop", AT_PROP, AC_NONE, AC_PROP, EXF_PROP, d331 8 d387 1 a387 1 prop_opnum_free, prop_opnum_validate }, d395 1 a395 1 acl_free_prop_string, prop_opnum_validate }, d438 1 a438 1 acl_free_prop_string, prop_opnum_validate }, d1117 3 a1119 5 char * acl_print_opnum(ad, buf, len) acl_data_t *ad; char *buf; size_t len; a1132 1 char *str = NULL; d1135 2 a1136 8 if (op_to_str[i].op == ad->opnum.op) { str = op_to_str[i].str; break; } } if (str == NULL) { mg_log(LOG_ERR, "unexpected operator"); exit(EX_SOFTWARE); d1139 12 a1150 1 snprintf(buf, len, "%s %d", str, ad->opnum.num); d1662 56 d1763 29 d1816 23 @ 1.108 log @set ACL clause to set/increment/decrement properties log ACL clause to send formatted string to syslog @ text @d1 1 a1 1 /* $Id: acl.c,v 1.107 2013/05/19 05:53:34 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.107 2013/05/19 05:53:34 manu Exp $"); d3113 1 @ 1.107 log @nsupdate support @ text @d1 1 a1 1 /* $Id: acl.c,v 1.106 2013/01/19 16:01:15 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.106 2013/01/19 16:01:15 manu Exp $"); a81 1 #if defined(USE_CURL) || defined(USE_LDAP) a82 1 #endif a155 1 #if defined(USE_CURL) || defined(USE_LDAP) a161 1 #endif d166 2 a256 1 #if defined(USE_CURL) || defined(USE_LDAP) a260 1 #endif a272 1 #if defined(USE_CURL) || defined(USE_LDAP) a276 1 #endif a320 1 #if defined(USE_CURL) || defined(USE_LDAP) a328 1 #endif a369 1 #if defined(USE_CURL) || defined(USE_LDAP) a373 1 #endif a377 1 #if defined(USE_CURL) || defined(USE_LDAP) a381 1 #endif a420 1 #if defined(USE_CURL) || defined(USE_LDAP) a424 1 #endif /* USE_CURL || USE_LDAP */ d438 52 a1616 1 #if defined(USE_CURL) || defined(USE_LDAP) a1726 2 #endif d3101 16 @ 1.106 log @More Solaris build fixes (Jim Klimov) @ text @d1 1 a1 1 /* $Id: acl.c,v 1.105 2012/09/20 08:31:49 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.105 2012/09/20 08:31:49 manu Exp $"); d166 4 d446 6 d1692 22 @ 1.105 log @- Format string substitution get %-encoding for urlcheck - Format string substitution get \-escapes and %-encoding for ldapcheck - bump to 4.4a3 @ text @d1 1 a1 1 /* $Id: acl.c,v 1.104 2012/09/19 02:04:38 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.104 2012/09/19 02:04:38 manu Exp $"); d41 1 a41 1 #ifdef HAVE_OLD_QUEUE_H @ 1.104 log @- Add subjtag clause in DATA stage ACL to add a tag to message subject - Allow comparison of msgsize, rcptcount & spamd, against values from LDAP @ text @d1 1 a1 1 /* $Id: acl.c,v 1.103 2012/02/24 16:40:08 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.103 2012/02/24 16:40:08 manu Exp $"); d2350 1 a2350 1 aclstr = fstring_expand(priv, NULL, "%a"); @ 1.103 log @Fix log format after priv->priv_cur_rcpt change (Bruncsak, Attila) @ text @d1 1 a1 1 /* $Id: acl.c,v 1.102 2012/02/21 05:53:43 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.102 2012/02/21 05:53:43 manu Exp $"); d374 6 d384 6 d429 7 a435 1 #endif d1298 2 a2042 1 mg_log(LOG_DEBUG, "===> %s", ap->ap_addheader); d2057 7 d2086 2 d2189 1 d2569 5 d2883 22 @ 1.102 log @p0f v3 support bump to 4.4a1 @ text @d1 1 a1 1 /* $Id: acl.c,v 1.97 2010/04/12 12:04:41 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.97 2010/04/12 12:04:41 manu Exp $"); d2081 1 a2081 1 (priv->priv_cur_rcpt) ? priv->priv_cur_rcpt : "(nil)", d2271 1 a2271 1 if (cur_rcpt != NULL) { d2324 1 a2324 1 (cur_rcpt != NULL) ? cur_rcpt : "(nil)", @ 1.101 log @Add continue type AC @ text @d4 1 a4 1 * Copyright (c) 2004-2007 Emmanuel Dreyfus @ 1.100 log @- Add a addfooter action clause in ACL, to add mail a footer - Allow per-dacl maxpeek setting, set by maxpeer action clause in racl - Add LDAP or CURL gathered property substitution in format strings @ text @d115 2 d1836 3 d1919 3 d1932 157 d2203 2 a2204 2 * We catch the first ACL entry that matches, so exit * evaluation loop when found. d2206 5 a2210 2 if (found != 0) break; d2213 1 a2213 136 if (acl) { if (retval == 0) retval = EXF_DEFAULT; switch (ap.ap_type) { case A_GREYLIST: retval |= EXF_GREYLIST; break; case A_WHITELIST: retval |= EXF_WHITELIST; break; case A_BLACKLIST: retval |= EXF_BLACKLIST; break; default: mg_log(LOG_ERR, "corrupted acl list"); exit(EX_SOFTWARE); break; } priv->priv_sr.sr_acl_line = acl->a_line; priv->priv_sr.sr_delay = (ap.ap_delay != -1) ? ap.ap_delay : conf.c_delay; priv->priv_sr.sr_autowhite = (ap.ap_autowhite != -1) ? ap.ap_autowhite : conf.c_autowhite_validity; priv->priv_sr.sr_tarpit = (ap.ap_tarpit != -1) ? ap.ap_tarpit : conf.c_tarpit; priv->priv_sr.sr_tarpit_scope = (ap.ap_tarpit_scope != -1) ? ap.ap_tarpit_scope : conf.c_tarpit_scope; if (ap.ap_tarpitted > priv->priv_max_tarpitted) priv->priv_max_tarpitted = ap.ap_tarpitted; if (ap.ap_tarpitted > priv->priv_total_tarpitted) priv->priv_total_tarpitted = ap.ap_tarpitted; if (ap.ap_id) { priv->priv_sr.sr_acl_id = strdup(ap.ap_id); if (priv->priv_sr.sr_acl_id == NULL) { mg_log(LOG_ERR, "strdup failed: %s", strerror(errno)); exit(EX_OSERR); } } if (ap.ap_code) { priv->priv_sr.sr_code = strdup(ap.ap_code); if (priv->priv_sr.sr_code == NULL) { mg_log(LOG_ERR, "strdup failed: %s", strerror(errno)); exit(EX_OSERR); } } if (ap.ap_ecode) { priv->priv_sr.sr_ecode = strdup(ap.ap_ecode); if (priv->priv_sr.sr_ecode == NULL) { mg_log(LOG_ERR, "strdup failed: %s", strerror(errno)); exit(EX_OSERR); } } if (ap.ap_msg) { priv->priv_sr.sr_msg = strdup(ap.ap_msg); if (priv->priv_sr.sr_msg == NULL) { mg_log(LOG_ERR, "strdup failed"); exit(EX_OSERR); } } if (ap.ap_report) { priv->priv_sr.sr_report = strdup(ap.ap_report); if (priv->priv_sr.sr_report == NULL) { mg_log(LOG_ERR, "strdup failed"); exit(EX_OSERR); } } if (ap.ap_addheader) { priv->priv_sr.sr_addheader = strdup(ap.ap_addheader); if (priv->priv_sr.sr_addheader == NULL) { mg_log(LOG_ERR, "strdup failed"); exit(EX_OSERR); } } if (ap.ap_addfooter) { priv->priv_sr.sr_addfooter = strdup(ap.ap_addfooter); if (priv->priv_sr.sr_addfooter == NULL) { mg_log(LOG_ERR, "strdup failed"); exit(EX_OSERR); } (void)fstring_escape(priv->priv_sr.sr_addfooter); } if (stage == AS_RCPT) priv->priv_maxpeek = ap.ap_maxpeek; priv->priv_sr.sr_nmatch = ap.ap_nmatch; priv->priv_sr.sr_pmatch = ap.ap_pmatch; /* Free temporary memory if nescessary */ if (ap.ap_flags & A_FREE_ID) free(ap.ap_id); if (ap.ap_flags & A_FREE_CODE) free(ap.ap_code); if (ap.ap_flags & A_FREE_ECODE) free(ap.ap_ecode); if (ap.ap_flags & A_FREE_MSG) free(ap.ap_msg); if (ap.ap_flags & A_FREE_REPORT) free(ap.ap_report); if (ap.ap_flags & A_FREE_ADDHEADER) free(ap.ap_addheader); if (ap.ap_flags & A_FREE_ADDFOOTER) free(ap.ap_addfooter); if (ap.ap_flags & A_FLUSHADDR) { struct tuple_fields tuple; tuple.sa = sa; tuple.salen = salen; tuple.queueid = queueid; tuple.acl_line = acl->a_line; mg_tuple_remove(&tuple); } if (ap.ap_flags & A_NOLOG) retval |= EXF_NOLOG; if (conf.c_debug || conf.c_acldebug) { char aclstr[HDRLEN + 1]; iptostring(sa, salen, addrstr, sizeof(addrstr)); mg_log(LOG_DEBUG, "Mail from=%s, rcpt=%s, addr=%s[%s] " "is matched by entry %s", from, (cur_rcpt != NULL) ? cur_rcpt : "(nil)", hostname, addrstr, acl_entry(aclstr, HDRLEN, acl)); } } else { d2447 3 d2891 2 @ 1.99 log @Add format string to report last matching LDAP or CURL propery Fix memory corruption bug Refactor prop_clear*() into a ingle function @ text @d1222 9 d1276 2 d1995 2 d2126 11 d2154 2 d2499 10 d2770 1 a2770 1 acl_add_addheader(hdr) d2791 42 @ 1.98 log @Allow filtering header and body against LDAP or CURL gathered properties Merge struct body and struct header into struct line, for the sake of code reusing @ text @@ 1.97 log @New rate limiting feature. Account by IP, by recipient, account by whatever you want! @ text @d1 1 a1 1 /* $Id: acl.c,v 1.96 2010/01/12 11:18:39 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.96 2010/01/12 11:18:39 manu Exp $"); d253 6 d271 6 d558 1 a558 1 struct header *h; d565 2 a566 2 TAILQ_FOREACH(h, &priv->priv_header, h_list) if (strstr(h->h_line, ad->string) != NULL) d578 1 a578 1 struct body *b; d585 2 a586 2 TAILQ_FOREACH(b, &priv->priv_body, b_list) if (strstr(b->b_lines, ad->string) != NULL) d808 1 a808 1 struct header *h; d815 2 a816 2 TAILQ_FOREACH(h, &priv->priv_header, h_list) if (myregexec(priv, ad, ap, h->h_line) == 0) d942 1 a942 1 struct body *b; d949 2 a950 2 TAILQ_FOREACH(b, &priv->priv_body, b_list) if (myregexec(priv, ad, ap, b->b_lines) == 0) @ 1.96 log @Fix dumpfile argument on command line (Ole Hansen) @ text @d1 1 a1 1 /* $Id: acl.c,v 1.95 2009/10/31 21:28:03 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.95 2009/10/31 21:28:03 manu Exp $"); d69 1 d138 2 d273 4 d1397 25 @ 1.95 log @Add mx ACL clause (Rudy Eschauzier) @ text @d1 1 a1 1 /* $Id: acl.c,v 1.94 2009/09/07 12:56:54 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.94 2009/09/07 12:56:54 manu Exp $"); d2167 8 a2174 3 if ((retval & EXF_RCPT) && (cur_rcpt != NULL)) { snprintf(tmpstr, sizeof(tmpstr), "recipient %s is whitelisted", cur_rcpt); @ 1.94 log @New tarpit feature (Kouhei Sutou) @ text @d1 1 a1 1 /* $Id: acl.c,v 1.93 2009/08/14 00:09:02 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.93 2009/08/14 00:09:02 manu Exp $"); d65 1 d72 3 d141 4 d280 6 d580 9 a588 4 ap->ap_tarpitted = pending_tarpitted(SA(&priv->priv_addr), priv->priv_addrlen, priv->priv_from, priv->priv_cur_rcpt); d1417 21 d1886 2 a1887 2 int retval = 0; int noretval = 0; d2087 10 a2096 2 if (ap.ap_flags & A_FLUSHADDR) pending_del_addr(sa, salen, queueid, acl->a_line); d2143 7 @ 1.93 log @Fix unallocated memory use for ldapcheck and urlcheck property matching @ text @d1 1 a1 1 /* $Id: acl.c,v 1.92 2009/07/05 21:40:21 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.92 2009/07/05 21:40:21 manu Exp $"); d116 1 d130 1 d383 6 d560 16 d1033 10 d1143 10 d1182 2 d1890 3 d1974 9 d2076 2 d2148 6 d2323 8 d2445 19 d2652 1 a2652 1 acl_modify_by_prop(key, value, ap) d2689 5 @ 1.92 log @typo @ text @d1 1 a1 1 /* $Id: acl.c,v 1.91 2009/06/08 23:40:06 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.91 2009/06/08 23:40:06 manu Exp $"); d1426 7 a1432 1 acl_add_string((void *)&ad->prop->upd_data, upd->upd_data); d1455 5 a1459 1 acl_add_regex((void *)&ad->prop->upd_data, upd->upd_data); d1461 2 d1475 1 a1475 2 acl_print_string((void *)&ad->prop->upd_data, buf + written, len - written); d1489 1 a1489 2 acl_print_regex((void *)&ad->prop->upd_data, buf + written, len - written); d1498 2 a1500 1 acl_free_string((void *)&ad->prop->upd_data); d1509 2 a1511 1 acl_free_regex((void *)&ad->prop->upd_data); @ 1.91 log @Allow ACL override by ldapcheck clauses (Piotr Wadas) @ text @d1 1 a1 1 /* $Id: acl.c,v 1.90 2009/04/16 12:33:19 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.90 2009/04/16 12:33:19 manu Exp $"); d2353 1 a2353 1 mg_log(LOG_DEBUG, "load acl delay %ld", (long)delay); @ 1.90 log @Log ACL id instead of line number (John Thiltges) @ text @d1 1 a1 1 /* $Id: acl.c,v 1.89 2009/02/09 04:12:07 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.89 2009/02/09 04:12:07 manu Exp $"); d2525 1 a2525 1 acl_add_addheader(hdr) d2545 103 @ 1.89 log @Roll back previous build fix, as it requires , a header that is not available anywhere. Change STAILQ_* to TAILQ_* instead @ text @d1 1 a1 1 /* $Id: acl.c,v 1.88 2009/02/08 20:26:20 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.88 2009/02/08 20:26:20 manu Exp $"); d1786 1 d2080 1 d2082 1 a2082 1 "(from=%s, rcpt=%s, addr=%s[%s]) ACL %d", from, d2084 2 a2085 1 hostname, addrstr, priv->priv_sr.sr_acl_line); @ 1.89.2.1 log @Fix unallocated memory use for ldapcheck and urlcheck property matching @ text @d1 1 a1 1 /* $Id: acl.c,v 1.89 2009/02/09 04:12:07 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.89 2009/02/09 04:12:07 manu Exp $"); d1426 1 a1426 7 if ((ad->prop->upd_data = malloc(sizeof(acl_data_t))) == NULL) { mg_log(LOG_ERR, "acl malloc failed: %s", strerror(errno)); exit(EX_OSERR); } memset(ad->prop->upd_data, 0, sizeof(acl_data_t)); acl_add_string((void *)ad->prop->upd_data, upd->upd_data); d1449 1 a1449 5 if ((ad->prop->upd_data = malloc(sizeof(acl_data_t))) == NULL) { mg_log(LOG_ERR, "acl malloc failed: %s", strerror(errno)); exit(EX_OSERR); } memset(ad->prop->upd_data, 0, sizeof(acl_data_t)); a1450 2 acl_add_regex((void *)ad->prop->upd_data, upd->upd_data); d1463 2 a1464 1 acl_print_string(ad->prop->upd_data, buf + written, len - written); d1478 2 a1479 1 acl_print_regex(ad->prop->upd_data, buf + written, len - written); d1488 1 a1489 2 free(ad->prop->upd_data); free(ad->prop->upd_name); d1498 1 a1499 2 free(ad->prop->upd_data); free(ad->prop->upd_name); @ 1.89.2.2 log @New ratelimit feature @ text @d1 1 a1 1 /* $Id: acl.c,v 1.89.2.1 2009/08/14 00:11:03 manu Exp $ */ d4 1 a4 1 * Copyright (c) 2004-2010 Emmanuel Dreyfus d37 1 a37 1 __RCSID("$Id: acl.c,v 1.89.2.1 2009/08/14 00:11:03 manu Exp $"); a67 1 #include "ratelimit.h" a130 2 void acl_add_ratelimit(acl_data_t *, void *); char *acl_print_ratelimit(acl_data_t *, char *, size_t); a259 4 { AC_RATELIMIT, MULTIPLE_OK, AS_ANY, "ratelimit", AT_RATELIMIT, AC_NONE, AC_STRING, 0, /* XXX */ acl_print_ratelimit, acl_add_ratelimit, NULL, ratelimit_validate }, a1324 25 void acl_add_ratelimit(ad, data) acl_data_t *ad; void *data; { char *ratelimit = data; if ((ad->ratelimit_conf = ratelimit_byname(ratelimit)) == NULL) { mg_log(LOG_ERR, "unknown ratelimit class \"%s\"", ratelimit); exit(EX_DATAERR); } return; } char * acl_print_ratelimit(ad, buf, len) acl_data_t *ad; char *buf; size_t len; { snprintf(buf, len, "\"%s\"", ad->ratelimit_conf->rc_name); return buf; } @ 1.88 log @Evaluate list clases in forward order (Rudy Eschauzier) Fix crashes on regex substring matches (Rudy Eschauzier) Bump to 4.1.11 @ text @d1 1 a1 1 /* $Id: acl.c,v 1.87 2009/01/02 00:45:09 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.87 2009/01/02 00:45:09 manu Exp $"); d864 1 a864 1 STAILQ_FOREACH(le, &ale->al_head, l_list) { @ 1.87 log @typo (from Rick Adams) @ text @d1 1 a1 1 /* $Id: acl.c,v 1.86 2008/11/26 11:07:54 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.86 2008/11/26 11:07:54 manu Exp $"); a564 17 * Add room for matched strings */ len = (ap->ap_nmatch + ad->regex.nmatch) * sizeof(*ap->ap_pmatch);; if (len > 0) { if ((ap->ap_pmatch = realloc(ap->ap_pmatch, len)) == NULL) { mg_log(LOG_ERR, "realloc failed: %s", strerror(errno)); exit(EX_OSERR); } } /* Move the previous matches to the end of the array */ if (ap->ap_nmatch != 0) { memmove(&ap->ap_pmatch[ad->regex.nmatch], &ap->ap_pmatch[0], ap->ap_nmatch * sizeof(char *)); bzero(&ap->ap_pmatch[0], ad->regex.nmatch * sizeof(char *)); } /* d582 20 a601 1 * Gather the strings, skiping the first one (\0) a625 2 ap->ap_nmatch += ad->regex.nmatch; d864 1 a864 1 LIST_FOREACH(le, &ale->al_head, l_list) { d1814 6 d1838 13 d1854 3 d1865 4 a1876 2 if (found == 0) continue; d1879 2 a1880 2 * We found an entry that matches, exit the evaluation * loop d1882 2 a1883 1 break; @ 1.86 log @Don't quit for unexistant backreferences. @ text @d1 1 a1 1 /* $Id: acl.c,v 1.85 2008/11/26 05:20:13 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.85 2008/11/26 05:20:13 manu Exp $"); d2340 1 a2340 1 mg_log(LOG_ERR, "inexistent list \"%s\" line %d", @ 1.85 log @Allow regex on properties Allow extended regex substitution Custom headers can now be added to the message Bump to 4.1.8 @ text @d1 1 a1 1 /* $Id: acl.c,v 1.84 2008/11/10 11:16:14 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.84 2008/11/10 11:16:14 manu Exp $"); d603 1 a603 1 mg_log(LOG_ERR, "unexpected void backreference no %d " d606 1 a606 1 exit(EX_SOFTWARE); @ 1.84 log @Fix memory leak @ text @d1 1 a1 1 /* $Id: acl.c,v 1.83 2008/11/06 11:23:53 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.83 2008/11/06 11:23:53 manu Exp $"); d291 2 a292 2 { AC_PROP, MULTIPLE_OK, AS_ANY, "propre", AT_PROP, AC_NONE, AC_PROPRE, EXF_PROP, d1101 1 a1101 1 if ((cp[0] == '\\') && (cp[0] != '\0') && (cp[1] == '(')) d1181 2 d1831 1 d1926 7 d1948 2 d2250 5 d2495 22 @ 1.83 log @Add option to match exact domain instead of substrings (Rick Adams) @ text @d1 1 a1 1 /* $Id: acl.c,v 1.82 2008/09/30 03:56:03 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.82 2008/09/30 03:56:03 manu Exp $"); a1660 4 if ((acl = malloc(sizeof(*acl))) == NULL) { mg_log(LOG_ERR, "ACL malloc failed: %s", strerror(errno)); exit(EX_OSERR); } d1666 1 a1666 1 gacl = acl_init_entry (); @ 1.82 log @Make implicit default rule at DATA stage silent (Greg Troxel) @ text @d1 1 a1 1 /* $Id: acl.c,v 1.81 2008/09/26 23:35:44 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.81 2008/09/26 23:35:44 manu Exp $"); d501 6 @ 1.81 log @Spamassassin support and DATA-stage greylisting (Manuel Badzong) @ text @d1 1 a1 1 /* $Id: acl.c,v 1.80 2008/09/26 17:00:51 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.80 2008/09/26 17:00:51 manu Exp $"); d1956 1 a1956 1 if (testmode || stage == AS_DATA) d1958 2 d1968 1 a1968 1 if (retval & EXF_WHITELIST) { @ 1.80 log @ Allow syslog facility to be configured (Joe Pruett) Allow logging to be disabled on a per-ACL basis (Joe Pruett)v @ text @d1 1 a1 1 /* $Id: acl.c,v 1.79 2008/09/07 00:13:34 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.79 2008/09/07 00:13:34 manu Exp $"); d93 3 d373 8 a1636 6 if (acl_type == A_GREYLIST) { mg_log(LOG_ERR, "greylist action in DATA stage ACL " "at line %d", conf_line - 1); exit(EX_DATAERR); } d1678 1 a1678 1 mg_log(LOG_ERR, "unecpected acl_type %d", acl_type); a1720 6 if (acl_type == A_GREYLIST) { mg_log(LOG_ERR, "greylist action in DATA stage ACL " "at line %d", conf_line - 1); exit(EX_DATAERR); } d1758 1 a1758 1 mg_log(LOG_ERR, "unecpected acl_type %d", acl_type); d1956 1 a1956 1 if (testmode) d1966 1 a1966 1 if (retval & EXF_WHITELIST && (! (retval & EXF_NOLOG))) { @ 1.79 log @Experimental p0f support Fix a memory leak in GeoIP code Fix a memory leak in DKIM code Bump to revision to 4.1.6 (but no tag yet) @ text @d1 1 a1 1 /* $Id: acl.c,v 1.78 2008/08/23 11:04:06 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.78 2008/08/23 11:04:06 manu Exp $"); d1182 6 d1941 3 d1967 1 a1967 1 if (retval & EXF_WHITELIST) { d2046 1 a2046 1 queueid, whystr); d2207 5 @ 1.78 log @Remove double include @ text @d1 1 a1 1 /* $Id: acl.c,v 1.77 2008/08/21 21:05:35 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.77 2008/08/21 21:05:35 manu Exp $"); d83 3 d356 14 @ 1.77 log @Exprimental DKIM support @ text @d1 1 a1 1 /* $Id: acl.c,v 1.76 2008/08/03 05:00:06 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.76 2008/08/03 05:00:06 manu Exp $"); a76 3 #ifdef USE_DKIM #include "dkimcheck.h" #endif @ 1.76 log @Native LDAP support through OpenLDAP bump to 4.1.4 @ text @d1 1 a1 1 /* $Id: acl.c,v 1.75 2008/04/24 11:05:50 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.75 2008/04/24 11:05:50 manu Exp $"); d77 3 d90 3 d324 6 d2004 8 @ 1.75 log @Fix bogus ACL when using features not compiled in @ text @d1 1 a1 1 /* $Id: acl.c,v 1.74 2007/11/11 11:57:19 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.74 2007/11/11 11:57:19 manu Exp $"); d74 6 d129 6 d270 8 d281 1 a281 1 acl_free_prop_string, urlcheck_prop_string_validate }, d285 1 a285 1 acl_free_prop_regex, urlcheck_prop_regex_validate }, d1326 28 d1355 1 d1361 1 a1361 1 struct urlcheck_prop_data *upd; d1363 1 a1363 1 upd = (struct urlcheck_prop_data *)data; d1375 1 a1375 1 acl_add_string((acl_data_t *)&ad->prop->upd_data, upd->upd_data); d1384 1 a1384 1 struct urlcheck_prop_data *upd; d1386 1 a1386 1 upd = (struct urlcheck_prop_data *)data; d1398 1 a1398 1 acl_add_regex((acl_data_t *)&ad->prop->upd_data, upd->upd_data); d1412 1 a1412 1 acl_print_string((acl_data_t *)&ad->prop->upd_data, d1427 1 a1427 1 acl_print_regex((acl_data_t *)&ad->prop->upd_data, d1438 1 a1438 1 acl_free_string((acl_data_t *)&ad->prop->upd_data); d1448 1 a1448 1 acl_free_regex((acl_data_t *)&ad->prop->upd_data); @ 1.74 log @Add ACL id string @ text @d1 1 a1 1 /* $Id: acl.c,v 1.73 2007/11/06 11:39:33 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.73 2007/11/06 11:39:33 manu Exp $"); d102 1 d1097 33 d1561 8 d1651 8 a2027 1 struct acl_clause *ac; d2032 1 a2032 18 while (!TAILQ_EMPTY(&acl->a_clause)) { ac = TAILQ_FIRST(&acl->a_clause); TAILQ_REMOVE(&acl->a_clause, ac, ac_list); if (ac->ac_acr->acr_free) (*ac->ac_acr->acr_free)(&ac->ac_data); free(ac); } if (acl->a_code != NULL) free(acl->a_code); if (acl->a_ecode != NULL) free(acl->a_ecode); if (acl->a_msg != NULL) free(acl->a_msg); if (acl->a_report != NULL) free(acl->a_report); free(acl); @ 1.73 log @Add SPF status selection to ACL @ text @d1 1 a1 1 /* $Id: acl.c,v 1.72 2007/10/05 10:47:48 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.72 2007/10/05 10:47:48 manu Exp $"); d1692 1 d1753 8 d1796 2 d2045 6 d2260 22 @ 1.72 log @ Missing bit for Solaris 256 stream workaround @ text @d1 1 a1 1 /* $Id: acl.c,v 1.71 2007/09/20 11:07:23 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.71 2007/09/20 11:07:23 manu Exp $"); d63 1 d292 3 a294 3 { AC_SPF, UNIQUE, AS_ANY, "spf", AT_NONE, AC_NONE, AC_SPF, EXF_SPF, acl_print_null, NULL, @ 1.72.2.1 log @Update Debian startup script (Adam Katz) Fix bogus ACL when using features not compiled in @ text @d1 1 a1 1 /* $Id: acl.c,v 1.72 2007/10/05 10:47:48 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.72 2007/10/05 10:47:48 manu Exp $"); a100 1 void acl_free_entry(struct acl_entry *); a1094 33 acl_free_entry(acl) struct acl_entry *acl; { struct acl_clause *ac; while (!TAILQ_EMPTY(&acl->a_clause)) { ac = TAILQ_FIRST(&acl->a_clause); TAILQ_REMOVE(&acl->a_clause, ac, ac_list); if (ac->ac_acr->acr_free) (*ac->ac_acr->acr_free)(&ac->ac_data); free(ac); } if (acl->a_code != NULL) free(acl->a_code); if (acl->a_ecode != NULL) free(acl->a_ecode); if (acl->a_msg != NULL) free(acl->a_msg); if (acl->a_report != NULL) free(acl->a_report); free(acl); return; } void acl_drop(void) { gacl->a_flags |= A_DROP_ACL; return; } void a1525 8 if (gacl->a_flags & A_DROP_ACL) { acl_free_entry(gacl); gacl = acl_init_entry(); if (conf.c_debug || conf.c_acldebug) mg_log(LOG_DEBUG, "Drop ACL %d", conf_line - 1); return NULL; } a1607 8 if (gacl->a_flags & A_DROP_ACL) { acl_free_entry(gacl); gacl = acl_init_entry(); if (conf.c_debug || conf.c_acldebug) mg_log(LOG_DEBUG, "Drop ACL %d", conf_line - 1); return NULL; } d1966 1 d1971 18 a1988 1 acl_free_entry(acl); @ 1.72.2.2 log @Fix memory leak @ text @d1 1 a1 1 /* $Id: acl.c,v 1.72.2.1 2008/08/22 21:44:16 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.72.2.1 2008/08/22 21:44:16 manu Exp $"); d1568 4 @ 1.71 log @Display ACL when matching whitelist ACL (Benoit Branciard) @ text @d1 1 a1 1 /* $Id: acl.c,v 1.70 2007/09/18 20:43:16 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.70 2007/09/18 20:43:16 manu Exp $"); d2110 1 a2110 1 debug = fopen("/tmp/access-list.debug", "w"); d2124 1 a2124 1 fclose(debug); @ 1.70 log @Treat protocol errors in urlcheck clauses as temporary failures @ text @d1 1 a1 1 /* $Id: acl.c,v 1.69 2007/09/13 02:58:25 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.69 2007/09/13 02:58:25 manu Exp $"); d1886 1 a1886 1 "(from=%s, rcpt=%s, addr=%s[%s])", from, d1888 1 a1888 1 hostname, addrstr); @ 1.69 log @Report missing SPF reasons in X-Greylist (Benoit Branciard) @ text @d1 1 a1 1 /* $Id: acl.c,v 1.68 2007/07/23 20:12:26 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.68 2007/07/23 20:12:26 manu Exp $"); d1636 1 a1636 1 void d1651 1 d1699 3 a1701 2 found = (*ac->ac_acr->acr_filter) (&ac->ac_data, stage, &ap, priv); d1894 2 d1900 1 a1900 1 return; @ 1.68 log @Allow rcpt clause in dacl statement, as documented @ text @d1 1 a1 1 /* $Id: acl.c,v 1.67 2007/07/14 16:03:43 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.67 2007/07/14 16:03:43 manu Exp $"); d1870 9 @ 1.67 log @Add "not" report for geoip @ text @d1 1 a1 1 /* $Id: acl.c,v 1.66 2007/07/14 03:49:22 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.66 2007/07/14 03:49:22 manu Exp $"); d648 9 a656 3 if (stage != AS_RCPT) { mg_log(LOG_ERR, "rcpt filter called at non RCPT stage"); exit(EX_SOFTWARE); a658 2 if (myregexec(priv, ad, ap, priv->priv_cur_rcpt) == 0) return 1; @ 1.66 log @Improve GeoIP status report in X-Greylist (Hideki ONO) @ text @d1 1 a1 1 /* $Id: acl.c,v 1.65 2007/07/08 21:02:28 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.65 2007/07/08 21:02:28 manu Exp $"); d1861 2 a1862 1 "geoip ccode %s is whitelisted", ccode); @ 1.65 log @Add hooks for libdmalloc @ text @d1 1 a1 1 /* $Id: acl.c,v 1.64 2007/05/21 00:22:55 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.64 2007/05/21 00:22:55 manu Exp $"); d1656 3 d1666 5 d1858 7 @ 1.64 log @Fix run-away string (AIDA Shinra) @ text @d1 1 a1 1 /* $Id: acl.c,v 1.63 2007/05/09 19:55:29 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.63 2007/05/09 19:55:29 manu Exp $"); d84 4 @ 1.63 log @Type mismatch (gcc should complain, why did it fail to do so?) @ text @d1 1 a1 1 /* $Id: acl.c,v 1.62 2007/05/09 19:46:40 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.62 2007/05/09 19:46:40 manu Exp $"); d895 2 @ 1.62 log @Fix build on Solaris (picky compiler) @ text @d1 1 a1 1 /* $Id: acl.c,v 1.61 2007/04/16 02:39:10 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.61 2007/04/16 02:39:10 manu Exp $"); d824 2 a825 2 acl_data_type_t item_type; acl_data_type_t list_type; @ 1.61 log @Fix build on Tru64 @ text @d1 1 a1 1 /* $Id: acl.c,v 1.60 2007/03/26 19:29:04 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.60 2007/03/26 19:29:04 manu Exp $"); d957 2 a958 1 return acl_add_string(ad, data); d969 2 a970 1 return acl_add_regex(ad, data); @ 1.60 log @Fix macro handling in ACL (AIDA Shinra) @ text @d1 1 a1 1 /* $Id: acl.c,v 1.59 2007/03/22 05:39:16 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.59 2007/03/22 05:39:16 manu Exp $"); d129 2 a130 2 *acl_print_list, *acl_add_list, NULL, *acl_list_filter }, d133 2 a134 2 *acl_print_string, *acl_add_string, *acl_free_string, NULL }, d137 2 a138 2 *acl_print_regex, *acl_add_regex, *acl_free_regex, NULL }, d141 2 a142 2 *acl_print_string, *acl_add_string, *acl_free_string, NULL }, d147 2 a148 2 *acl_print_netblock, *acl_add_netblock, *acl_free_netblock, *acl_netblock_filter }, d151 2 a152 2 *acl_print_list, *acl_add_list, NULL, *acl_list_filter }, d155 2 a156 2 *acl_print_string, *acl_add_string, *acl_free_string, *acl_domain_cmp }, d159 2 a160 2 *acl_print_regex, *acl_add_regex, *acl_free_regex, *acl_domain_regexec }, d163 2 a164 2 *acl_print_list, *acl_add_list, NULL, *acl_list_filter }, d167 2 a168 2 *acl_print_string, *acl_add_string, *acl_free_string, *acl_helo_strstr }, d171 2 a172 2 *acl_print_regex, *acl_add_regex, *acl_free_regex, *acl_helo_regexec }, d175 2 a176 2 *acl_print_list, *acl_add_list, NULL, *acl_list_filter }, d179 2 a180 2 *acl_print_string, *acl_add_string, *acl_free_string, *acl_from_cmp }, d183 2 a184 2 *acl_print_regex, *acl_add_regex, *acl_free_regex, *acl_from_regexec }, d187 2 a188 2 *acl_print_list, *acl_add_list, NULL, *acl_list_filter }, d191 2 a192 2 *acl_print_string, *acl_add_string, *acl_free_string, *acl_rcpt_cmp }, d195 2 a196 2 *acl_print_regex, *acl_add_regex, *acl_free_regex, *acl_rcpt_regexec }, d199 2 a200 2 *acl_print_list, *acl_add_list, NULL, *acl_list_filter }, d203 2 a204 2 *acl_print_string, *acl_add_body_string, *acl_free_string, *acl_body_strstr }, d207 2 a208 2 *acl_print_regex, *acl_add_body_regex, *acl_free_regex, *acl_body_regexec }, d211 2 a212 2 *acl_print_list, *acl_add_list, NULL, *acl_list_filter }, d215 2 a216 2 *acl_print_string, *acl_add_body_string, *acl_free_string, *acl_header_strstr }, d219 2 a220 2 *acl_print_regex, *acl_add_body_regex, *acl_free_regex, *acl_header_regexec }, d223 2 a224 2 *acl_print_list, *acl_add_list, NULL, *acl_list_filter }, d227 2 a228 2 *acl_print_macro, *acl_add_macro, NULL, *macro_check }, d231 2 a232 2 *acl_print_list, *acl_add_list, NULL, *acl_list_filter }, d236 2 a237 2 *acl_print_dnsrbl, *acl_add_dnsrbl, NULL, *dnsrbl_check_source }, d240 2 a241 2 *acl_print_list, *acl_add_list, NULL, *acl_list_filter }, d246 2 a247 2 *acl_print_urlcheck, *acl_add_urlcheck, NULL, *urlcheck_validate }, d250 2 a251 2 *acl_print_list, *acl_add_list, NULL, *acl_list_filter }, d254 2 a255 2 *acl_print_prop_string, *acl_add_prop_string, acl_free_prop_string, *urlcheck_prop_string_validate }, d258 2 a259 2 *acl_print_prop_regex, *acl_add_prop_regex, acl_free_prop_regex, *urlcheck_prop_regex_validate }, d263 2 a264 2 *acl_print_string, *acl_add_string, *acl_free_string, *acl_auth_strcmp }, d267 2 a268 2 *acl_print_regex, *acl_add_regex, *acl_free_regex, *acl_auth_regexec }, d271 2 a272 2 *acl_print_list, *acl_add_list, NULL, *acl_list_filter }, d275 2 a276 2 *acl_print_string, *acl_add_string, *acl_free_string, *acl_tls_strcmp }, d279 2 a280 2 *acl_print_regex, *acl_add_regex, *acl_free_regex, *acl_tls_regexec }, d283 2 a284 2 *acl_print_list, *acl_add_list, NULL, *acl_list_filter }, d289 2 a290 2 *acl_print_null, NULL, NULL, *spf_check }, d294 2 a295 2 *acl_print_opnum, *acl_add_opnum, NULL, *acl_msgsize_cmp }, d298 2 a299 2 *acl_print_opnum, *acl_add_opnum_body, NULL, *acl_rcptcount_cmp }, d302 2 a303 2 *print_clockspec, *add_clockspec, *clockspec_free, *clockspec_filter }, d306 2 a307 2 *acl_print_list, *acl_add_list, NULL, *acl_list_filter }, d311 2 a312 2 *acl_print_string, *acl_add_string, *acl_free_string, *geoip_filter }, d315 2 a316 2 *acl_print_list, *acl_add_list, NULL, *acl_list_filter }, @ 1.59 log @Allow filtering on the HELO string @ text @d1 1 a1 1 /* $Id: acl.c,v 1.58 2007/03/11 13:24:24 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.58 2007/03/11 13:24:24 manu Exp $"); d231 2 a232 2 *acl_print_macro, *acl_add_macro, NULL, *macro_check }, d234 1 a234 1 { AC_DNSRBL, MULTIPLE_OK, AS_ANY, "macro", d238 1 a238 1 { AC_DNSRBL_LIST, MULTIPLE_OK, AS_ANY, "macro_list", @ 1.58 log @Allow escaping on " in strings and / in regex @ text @d1 1 a1 1 /* $Id: acl.c,v 1.57 2007/03/04 15:24:39 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.57 2007/03/04 15:24:39 manu Exp $"); d165 12 d576 12 d687 15 @ 1.57 log @Instead of breaking the body line by line, use REG_NEWLINE @ text @d1 1 a1 1 /* $Id: acl.c,v 1.56 2007/03/01 04:07:57 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.56 2007/03/01 04:07:57 manu Exp $"); d956 1 d962 6 @ 1.56 log @Allow loading regex in lists of body clauses Fix crashes when handling preperties in ACL @ text @d1 1 a1 1 /* $Id: acl.c,v 1.55 2007/02/24 22:10:21 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.55 2007/02/24 22:10:21 manu Exp $"); d943 1 d961 5 a965 2 if ((error = regcomp(regex, regexstr, (conf.c_extendedregex ? REG_EXTENDED : 0) | REG_ICASE)) != 0) { @ 1.55 log @Allow reusing in the ACL of properties gathered from urlcheck @ text @d1 1 a1 1 /* $Id: acl.c,v 1.54 2007/02/14 05:39:16 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.54 2007/02/14 05:39:16 manu Exp $"); d1229 1 a1229 1 acl_add_string((acl_data_t *)ad->prop->upd_data, upd->upd_data); d1252 1 a1252 1 acl_add_regex((acl_data_t *)ad->prop->upd_data, upd->upd_data); d1266 1 a1266 1 acl_print_string((acl_data_t *)ad->prop->upd_data, d1281 1 a1281 1 acl_print_regex((acl_data_t *)ad->prop->upd_data, d1292 1 a1292 1 acl_free_string((acl_data_t *)ad->prop->upd_data); d1302 1 a1302 1 acl_free_regex((acl_data_t *)ad->prop->upd_data); @ 1.54 log @Fix a crash when using regex without grouping () @ text @d1 1 a1 1 /* $Id: acl.c,v 1.53 2007/02/05 06:05:34 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.53 2007/02/05 06:05:34 manu Exp $"); d117 6 d240 8 d470 1 a470 1 static int d1011 1 a1011 1 LIST_INIT(&acl->a_clause); d1209 99 d1363 1 a1363 1 LIST_FOREACH(cac, &gacl->a_clause, ac_list) { d1379 1 a1379 1 LIST_INSERT_HEAD(&gacl->a_clause, ac, ac_list); d1422 1 a1422 1 LIST_FOREACH(ac, &gacl->a_clause, ac_list) { d1504 1 a1504 1 LIST_FOREACH(ac, &gacl->a_clause, ac_list) { d1627 1 a1627 1 LIST_FOREACH(ac, &acl->a_clause, ac_list) { d1881 3 a1883 3 while (!LIST_EMPTY(&acl->a_clause)) { ac = LIST_FIRST(&acl->a_clause); LIST_REMOVE(ac, ac_list); d1942 1 a1942 1 LIST_FOREACH(ac, &acl->a_clause, ac_list) { d2087 1 a2087 1 LIST_FOREACH(cac, &gacl->a_clause, ac_list) { @ 1.53 log @%g for substitution by regex back references %I for susbtitution by sender IP masked by a CIDR @ text @d1 1 a1 1 /* $Id: acl.c,v 1.52 2007/02/02 07:00:06 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.52 2007/02/02 07:00:06 manu Exp $"); d473 5 a477 3 if ((ap->ap_pmatch = realloc(ap->ap_pmatch, len)) == NULL) { mg_log(LOG_ERR, "realloc failed: %s", strerror(errno)); exit(EX_OSERR); @ 1.52 log @Add GeoIP support @ text @d1 1 a1 1 /* $Id: acl.c,v 1.51 2007/02/02 02:10:23 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.51 2007/02/02 02:10:23 manu Exp $"); d456 91 d554 1 a554 2 if (regexec(ad->regex.re, priv->priv_from, 0, NULL, 0) == 0) d572 1 a572 1 if(regexec(ad->regex.re, auth_authen, 0, NULL, 0) == 0) d592 1 a592 1 if(regexec(ad->regex.re, dn, 0, NULL, 0) == 0) d609 1 a609 2 if (regexec(ad->regex.re, priv->priv_cur_rcpt, 0, NULL, 0) == 0) d621 1 a621 2 if (regexec(ad->regex.re, priv->priv_hostname, 0, NULL, 0) == 0) d641 1 a641 2 if (regexec(ad->regex.re, h->h_line, 0, NULL, 0) == 0) d760 1 a760 2 if (regexec(ad->regex.re, b->b_lines, 0, NULL, 0) == 0) d924 2 d952 10 d1509 2 d1594 3 @ 1.51 log @Add a time clause to match against time sets @ text @d1 1 a1 1 /* $Id: acl.c,v 1.50 2007/01/31 06:07:50 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.50 2007/01/31 06:07:50 manu Exp $"); d73 3 d282 10 @ 1.50 log @Fix display problem for netblocks @ text @d1 1 a1 1 /* $Id: acl.c,v 1.49 2007/01/29 04:57:18 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.49 2007/01/29 04:57:18 manu Exp $"); d78 1 d271 8 @ 1.49 log @msg clauses in ACL can use format strings substitution Add an ACL clause to customize X-Greylist header @ text @d1 1 a1 1 /* $Id: acl.c,v 1.48 2007/01/28 02:16:33 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.48 2007/01/28 02:16:33 manu Exp $"); d997 1 a997 1 &ad->netblock.mask, @ 1.48 log @ACL clauses can now be negated @ text @d1 1 a1 1 /* $Id: acl.c,v 1.47 2007/01/16 05:10:37 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.47 2007/01/16 05:10:37 manu Exp $"); d1388 1 d1461 8 a1468 2 mg_log(LOG_ERR, "strdup failed: %s", strerror(errno)); d1480 2 d1487 2 d1493 1 a1493 1 hostname, addrstr, acl_entry(acl)); d1655 2 d1664 3 a1666 1 acl_entry(acl) a1668 1 static char entrystr[HDRLEN]; d1675 1 a1675 1 snprintf(entrystr, HDRLEN, "racl %d ", acl->a_line); d1678 1 a1678 1 snprintf(entrystr, HDRLEN, "dacl %d ", acl->a_line); d1688 1 a1688 1 mystrlcat(entrystr, "greylist ", sizeof(entrystr)); d1691 1 a1691 1 mystrlcat(entrystr, "whitelist ", sizeof(entrystr)); d1694 1 a1694 1 mystrlcat(entrystr, "blacklist ", sizeof(entrystr)); d1713 1 a1713 1 mystrlcat(entrystr, tempstr, sizeof(entrystr)); d1720 1 a1720 1 mystrlcat(entrystr, tempstr, sizeof(entrystr)); d1726 1 a1726 1 mystrlcat(entrystr, tempstr, sizeof(entrystr)); d1731 1 a1731 1 mystrlcat(entrystr, tempstr, sizeof(entrystr)); d1737 1 a1737 1 mystrlcat(entrystr, tempstr, sizeof(entrystr)); d1743 1 a1743 1 mystrlcat(entrystr, tempstr, sizeof(entrystr)); d1749 7 a1755 1 mystrlcat(entrystr, tempstr, sizeof(entrystr)); d1759 1 a1759 1 mystrlcat(entrystr, "default", sizeof(entrystr)); d1784 3 a1786 1 entry = acl_entry(acl); d1953 22 @ 1.47 log @Use TAILQ_* instead of SIMPLEQ_*, as the SIMPLEQ_* definition is not the same on different systems. @ text @d1 1 a1 1 /* $Id: acl.c,v 1.46 2007/01/10 10:54:26 manu Exp $ */ d4 1 a4 1 * Copyright (c) 2004 Emmanuel Dreyfus d37 1 a37 1 __RCSID("$Id: acl.c,v 1.46 2007/01/10 10:54:26 manu Exp $"); d84 1 d118 1 a118 1 AT_LIST, AC_NONE, AC_NONE, d122 1 a122 1 AT_NONE, AC_NONE, AC_NONE, d126 1 a126 1 AT_NONE, AC_NONE, AC_NONE, d130 1 a130 1 AT_NONE, AC_NONE, AC_NONE, d136 1 a136 1 AT_NETBLOCK, AC_NETBLOCK_LIST, AC_NETBLOCK, d140 1 a140 1 AT_LIST, AC_NONE, AC_NONE, d144 1 a144 1 AT_STRING, AC_DOMAIN_LIST, AC_DOMAIN, d148 1 a148 1 AT_REGEX, AC_DOMAIN_LIST, AC_REGEX, d152 1 a152 1 AT_LIST, AC_NONE, AC_NONE, d156 1 a156 1 AT_STRING, AC_FROM_LIST, AC_EMAIL, d160 1 a160 1 AT_REGEX, AC_FROM_LIST, AC_REGEX, d164 1 a164 1 AT_LIST, AC_NONE, AC_NONE, d168 1 a168 1 AT_STRING, AC_RCPT_LIST, AC_EMAIL, d172 1 a172 1 AT_REGEX, AC_RCPT_LIST, AC_REGEX, d176 1 a176 1 AT_LIST, AC_NONE, AC_NONE, d180 1 a180 1 AT_STRING, AC_BODY_LIST, AC_STRING, d184 1 a184 1 AT_REGEX, AC_BODY_LIST, AC_REGEX, d188 1 a188 1 AT_LIST, AC_NONE, AC_NONE, d192 1 a192 1 AT_STRING, AC_HEADER_LIST, AC_STRING, d196 1 a196 1 AT_REGEX, AC_HEADER_LIST, AC_REGEX, d200 1 a200 1 AT_LIST, AC_NONE, AC_NONE, d204 1 a204 1 AT_MACRO, AC_MACRO_LIST, AC_STRING, d208 1 a208 1 AT_LIST, AC_NONE, AC_NONE, d213 1 a213 1 AT_DNSRBL, AC_DNSRBL_LIST, AC_STRING, d217 1 a217 1 AT_LIST, AC_NONE, AC_NONE, d223 1 a223 1 AT_URLCHECK, AC_URLCHECK_LIST, AC_STRING, d227 1 a227 1 AT_LIST, AC_NONE, AC_NONE, d232 1 a232 1 AT_STRING, AC_AUTH_LIST, AC_STRING, d236 1 a236 1 AT_REGEX, AC_AUTH_LIST, AC_REGEX, d240 1 a240 1 AT_LIST, AC_NONE, AC_NONE, d244 1 a244 1 AT_STRING, AC_TLS_LIST, AC_STRING, d248 1 a248 1 AT_REGEX, AC_TLS_LIST, AC_REGEX, d252 1 a252 1 AT_LIST, AC_NONE, AC_NONE, d258 1 a258 1 AT_NONE, AC_NONE, AC_SPF, d263 1 a263 1 AT_OPNUM, AC_NONE, AC_MSGSIZE, d267 1 a267 1 AT_OPNUM, AC_NONE, AC_RCPTCOUNT, d341 1 a341 1 return EXF_RCPTCOUNT; d354 1 a354 1 return EXF_MSGSIZE; d409 1 a409 1 return EXF_HEADER; d429 1 a429 1 return EXF_BODY; d443 1 a443 1 return EXF_FROM; d461 1 a461 1 return EXF_AUTH; d481 1 a481 1 return EXF_STARTTLS; d499 1 a499 1 return EXF_RCPT; d512 1 a512 1 return EXF_DOMAIN; d533 1 a533 1 return EXF_HEADER; d547 1 a547 1 return EXF_FROM; d562 1 a562 1 return EXF_RCPT; d568 1 a568 1 return EXF_RCPT; d588 1 a588 1 return EXF_AUTH; d609 1 a609 1 return EXF_STARTTLS; d653 1 a653 1 return EXF_BODY; d891 1 d1017 1 a1017 1 return EXF_ADDR; d1101 11 d1139 2 d1339 1 a1339 1 int d1354 4 a1357 1 int retval; d1378 1 d1390 7 a1396 2 if ((found = (*ac->ac_acr->acr_filter) (&ac->ac_data, stage, &ap, priv)) == 0) d1399 4 a1402 1 retval |= found; d1509 2 a1510 1 "address %s is whitelisted by DNSRBL", addrstr); d1516 2 a1517 1 "URL check passed"); d1537 2 a1538 1 "macro rule is satisfied"); d1555 4 a1558 1 return retval; d1691 2 d1695 2 a1696 1 snprintf(tempstr, sizeof(tempstr), "%s %s ", @ 1.46 log @Add msgsize and rcptcount clauses to ACL Allow rcpt clause at DATA stage ACL @ text @d1 1 a1 1 /* $Id: acl.c,v 1.45 2007/01/09 22:22:43 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.45 2007/01/09 22:22:43 manu Exp $"); d406 1 a406 1 SIMPLEQ_FOREACH(h, &priv->priv_header, h_list) d426 1 a426 1 SIMPLEQ_FOREACH(b, &priv->priv_body, b_list) d529 1 a529 1 SIMPLEQ_FOREACH(h, &priv->priv_header, h_list) d649 1 a649 1 SIMPLEQ_FOREACH(b, &priv->priv_body, b_list) @ 1.45 log @Add SPF, SMTP AUTH and STARTTLS to the ACL. This has not been tested at all, but at least it should not break existing setups if people do not use the new features. @ text @d1 1 a1 1 /* $Id: acl.c,v 1.44 2007/01/04 23:01:46 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.44 2007/01/04 23:01:46 manu Exp $"); d90 2 d101 2 d166 1 a166 1 { AC_RCPT, UNIQUE, AS_RCPT, "rcpt", d170 1 a170 1 { AC_RCPT_RE, UNIQUE, AS_RCPT, "rcpt_re", d174 1 a174 1 { AC_RCPT_LIST, UNIQUE, AS_RCPT, "rcpt_list", d261 8 d298 60 d559 9 a567 3 if (stage != AS_RCPT) { mg_log(LOG_ERR, "rcpt filter called at non RCPT stage"); exit(EX_SOFTWARE); a569 2 if (emailcmp(priv->priv_cur_rcpt, rcpt) == 0) return EXF_RCPT; d734 36 d1805 25 @ 1.44 log @Optionnaly post the message body to an URL check at DATA stage (see postmsg in greylist.conf(5) @ text @d1 1 a1 1 /* $Id: acl.c,v 1.43 2007/01/01 08:08:41 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.43 2007/01/01 08:08:41 manu Exp $"); d73 4 d89 1 d226 31 d375 38 d498 40 d649 9 d1015 2 a1016 1 (*acr->acr_add)(&ac->ac_data, data); @ 1.43 log @Add substitutions for sendmail macro and strftime in URL checks @ text @d1 1 a1 1 /* $Id: acl.c,v 1.42 2006/12/30 23:34:35 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.42 2006/12/30 23:34:35 manu Exp $"); d298 1 a298 1 LIST_FOREACH(h, &priv->priv_header, h_list) d318 1 a318 1 LIST_FOREACH(b, &priv->priv_body, b_list) d383 1 a383 1 LIST_FOREACH(h, &priv->priv_header, h_list) d459 1 a459 1 LIST_FOREACH(b, &priv->priv_body, b_list) @ 1.42 log @Fix various bugs (regex searches, lists matches, uninitialized memory) @ text @d1 1 a1 1 /* $Id: acl.c,v 1.41 2006/12/29 20:38:17 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.41 2006/12/29 20:38:17 manu Exp $"); d321 1 @ 1.41 log @Fix crash on config reload @ text @d1 1 a1 1 /* $Id: acl.c,v 1.40 2006/12/29 18:32:44 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.40 2006/12/29 18:32:44 manu Exp $"); d436 1 a436 1 retval = (*le->l_acr->acr_filter)(ad, stage, ap, priv); d587 10 a604 5 if ((ad->regex.re_copy = strdup(regexstr)) == NULL) { mg_log(LOG_ERR, "acl strdup failed: %s", strerror(errno)); exit(EX_OSERR); } d635 1 a635 1 memset(acl, 0, sizeof (acl)); d725 4 d733 1 a733 1 memcpy(&ad->netblock.mask, &mask, masklen); d743 1 @ 1.40 log @Major refactoring of ACL code. Remove a lot of duplicate code. Allow multiple macro, dnsrbl, urlcheck, body and header clauses in ACL @ text @d1 1 a1 1 /* $Id: acl.c,v 1.39 2006/12/26 21:21:52 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.39 2006/12/26 21:21:52 manu Exp $"); d79 1 a79 1 static struct acl_entry gacl; d620 16 a635 6 static void acl_init_entry(void) { memset(&gacl, 0, sizeof (gacl)); gacl.a_delay = -1; gacl.a_autowhite = -1; LIST_INIT(&gacl.a_clause); d648 1 a648 1 acl_init_entry(); d655 1 a655 1 gacl.a_flags |= A_FLUSHADDR; d869 1 a869 1 LIST_FOREACH(cac, &gacl.a_clause, ac_list) { d882 1 a882 1 LIST_INSERT_HEAD(&gacl.a_clause, ac, ac_list); d925 1 a925 1 LIST_FOREACH(ac, &gacl.a_clause, ac_list) { d971 1 a971 1 memcpy(acl, &gacl, sizeof(*acl)); d976 1 a976 1 acl_init_entry (); d1007 1 a1007 1 LIST_FOREACH(ac, &gacl.a_clause, ac_list) { d1049 1 a1049 5 if ((acl = malloc(sizeof(*acl))) == NULL) { mg_log(LOG_ERR, "ACL malloc failed: %s", strerror(errno)); exit(EX_OSERR); } *acl = gacl; d1054 1 a1054 1 acl_init_entry(); a1349 1 a1366 3 TAILQ_INIT(&acl_head); acl_init_entry(); d1495 1 a1495 1 if (gacl.a_delay != -1) { d1501 1 a1501 1 gacl.a_delay = delay; d1513 1 a1513 1 if (gacl.a_autowhite != -1) { d1519 1 a1519 1 gacl.a_autowhite = delay; d1542 1 a1542 1 LIST_FOREACH(cac, &gacl.a_clause, ac_list) { d1562 1 a1562 1 if (gacl.a_code) { d1568 1 a1568 1 if ((gacl.a_code = strdup(code)) == NULL) { d1584 1 a1584 1 if (gacl.a_ecode) { d1590 1 a1590 1 if ((gacl.a_ecode = strdup(ecode)) == NULL) { d1606 1 a1606 1 if (gacl.a_msg) { d1612 1 a1612 1 if ((gacl.a_msg = strdup(msg)) == NULL) { @ 1.39 log @Allow header and body searches in DATA-stage ACL Allow CIDR match for DNSRBL (not tested) @ text @d1 1 a1 1 /* $Id: acl.c,v 1.38 2006/12/20 21:57:52 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.38 2006/12/20 21:57:52 manu Exp $"); d81 539 d621 2 a622 2 acl_init_entry (void) { memset (&gacl, 0, sizeof (gacl)); d625 1 d650 5 a654 1 acl_add_netblock(sa, salen, cidr) a657 1 { a658 2 char addrstr[IPADDRSTRLEN]; char maskstr[IPADDRSTRLEN]; d664 4 a667 6 if (gacl.a_addr != NULL) { mg_log(LOG_ERR, "addr specified twice in ACL line %d", conf_line); exit(EX_DATAERR); } d706 1 a706 2 if ((gacl.a_addr = malloc(salen)) == NULL || (gacl.a_mask = malloc(masklen)) == NULL) { d711 4 a714 11 gacl.a_addrlen = salen; memcpy(gacl.a_addr, sa, salen); memcpy(gacl.a_mask, &mask, masklen); if (conf.c_debug || conf.c_acldebug) { iptostring(gacl.a_addr, gacl.a_addrlen, addrstr, sizeof(addrstr)); inet_ntop(gacl.a_addr->sa_family, gacl.a_mask, maskstr, sizeof(maskstr)); mg_log(LOG_DEBUG, "load acl net %s/%s", addrstr, maskstr); } d720 2 a721 2 acl_add_from(email) char *email; d723 1 a723 16 if (gacl.a_from != NULL || gacl.a_from_re != NULL || gacl.a_fromlist != NULL ) { mg_log(LOG_ERR, "from specified twice in ACL line %d", conf_line); exit(EX_DATAERR); } if ((gacl.a_from = strdup(email)) == NULL) { mg_log(LOG_ERR, "acl malloc failed: %s", strerror(errno)); exit(EX_OSERR); } if (conf.c_debug || conf.c_acldebug) mg_log(LOG_DEBUG, "load acl from %s", email); d727 5 a731 4 #ifdef USE_DNSRBL void acl_add_dnsrbl(dnsrbl) char *dnsrbl; d733 10 a742 16 if (gacl.a_dnsrbl != NULL || gacl.a_dnsrbllist != NULL) { mg_log(LOG_ERR, "dnsrbl specified twice in ACL line %d", conf_line); exit(EX_DATAERR); } if ((gacl.a_dnsrbl = dnsrbl_byname(dnsrbl)) == NULL) { mg_log(LOG_ERR, "unknown DNSRBL \"%s\"", dnsrbl); exit(EX_DATAERR); } if (conf.c_debug || conf.c_acldebug) mg_log(LOG_DEBUG, "load acl dnsrbl %s", dnsrbl); return; a743 1 #endif d745 6 a750 4 #ifdef USE_CURL void acl_add_urlcheck(urlcheck) char *urlcheck; d752 1 a752 14 if (gacl.a_urlcheck != NULL || gacl.a_urlchecklist != NULL) { mg_log(LOG_ERR, "urlcheck specified twice in ACL line %d", conf_line); exit(EX_DATAERR); } if ((gacl.a_urlcheck = urlcheck_byname(urlcheck)) == NULL) { mg_log(LOG_ERR, "unknown URL check \"%s\"", urlcheck); exit(EX_DATAERR); } if (conf.c_debug || conf.c_acldebug) mg_log(LOG_DEBUG, "load acl urlcheck %s", urlcheck); d754 1 a754 22 return; } #endif void acl_add_macro(macro) char *macro; { if (gacl.a_macro != NULL || gacl.a_macrolist != NULL) { mg_log(LOG_ERR, "sm_macro specified twice in ACL line %d", conf_line); exit(EX_DATAERR); } if ((gacl.a_macro = macro_byname(macro)) == NULL) { mg_log(LOG_ERR, "unknown sm_macro \"%s\"", macro); exit(EX_DATAERR); } if (conf.c_debug || conf.c_acldebug) mg_log(LOG_DEBUG, "load acl sm_macro %s", macro); d756 5 a760 1 return; d763 1 d765 8 a772 9 acl_add_rcpt(email) char *email; { if (gacl.a_rcpt != NULL || gacl.a_rcpt_re != NULL || gacl.a_rcptlist != NULL) { mg_log(LOG_ERR, "rcpt specified twice in ACL line %d", conf_line); a774 4 if ((gacl.a_rcpt = strdup(email)) == NULL) { mg_log(LOG_ERR, "acl malloc failed: %s", strerror(errno)); exit(EX_OSERR); } a775 3 if (conf.c_debug || conf.c_acldebug) mg_log(LOG_DEBUG, "load acl rcpt %s", email); d779 5 a783 3 void acl_add_header(header) char *header; d785 2 a786 20 if (gacl.a_header != NULL || gacl.a_header_re != NULL || gacl.a_headerlist != NULL) { mg_log(LOG_ERR, "header specified twice in ACL line %d", conf_line); exit(EX_DATAERR); } if ((gacl.a_header = strdup(header)) == NULL) { mg_log(LOG_ERR, "acl malloc failed: %s", strerror(errno)); exit(EX_OSERR); } if (conf.c_debug || conf.c_acldebug) mg_log(LOG_DEBUG, "load acl header %s", header); if (conf.c_maxpeek == 0) conf.c_maxpeek = -1; return; d788 1 d790 1 d792 3 a794 2 acl_add_body(body) char *body; d796 1 a796 15 if (gacl.a_body != NULL || gacl.a_body_re != NULL || gacl.a_bodylist != NULL) { mg_log(LOG_ERR, "body specified twice in ACL line %d", conf_line); exit(EX_DATAERR); } if ((gacl.a_body = strdup(body)) == NULL) { mg_log(LOG_ERR, "acl malloc failed: %s", strerror(errno)); exit(EX_OSERR); } if (conf.c_debug || conf.c_acldebug) mg_log(LOG_DEBUG, "load acl body %s", body); d798 2 a799 16 if (conf.c_maxpeek == 0) conf.c_maxpeek = -1; return; } void acl_add_domain(domain) char *domain; { if (gacl.a_domain != NULL || gacl.a_domain_re != NULL || gacl.a_domainlist != NULL) { mg_log(LOG_ERR, "domain specified twice in ACL line %d", conf_line); a801 4 if ((gacl.a_domain = strdup(domain)) == NULL) { mg_log(LOG_ERR, "acl malloc failed: %s", strerror(errno)); exit(EX_OSERR); } a802 3 if (conf.c_debug || conf.c_acldebug) mg_log(LOG_DEBUG, "load acl domain %s", domain); d806 5 a810 4 #define ERRLEN 1024 void acl_add_from_regex(regexstr) char *regexstr; d812 2 a813 41 size_t len; int error; char errstr[ERRLEN + 1]; if (gacl.a_from != NULL || gacl.a_from_re != NULL || gacl.a_fromlist != NULL) { mg_log(LOG_ERR, "from specified twice in ACL line %d", conf_line); exit(EX_DATAERR); } /* * Strip leading and trailing slashes */ len = strlen(regexstr); if (len > 0) regexstr[len - 1] = '\0'; regexstr++; if ((gacl.a_from_re = malloc(sizeof(*gacl.a_from_re))) == NULL) { mg_log(LOG_ERR, "acl malloc failed: %s", strerror(errno)); exit(EX_OSERR); } if ((error = regcomp(gacl.a_from_re, regexstr, (conf.c_extendedregex ? REG_EXTENDED : 0) | REG_ICASE)) != 0) { regerror(error, gacl.a_from_re, errstr, ERRLEN); mg_log(LOG_ERR, "bad regular expression \"%s\": %s", regexstr, errstr); exit(EX_OSERR); } if ((gacl.a_from_re_copy = strdup(regexstr)) == NULL) { mg_log(LOG_ERR, "acl strdup failed: %s", strerror(errno)); exit(EX_OSERR); } if (conf.c_debug || conf.c_acldebug) mg_log(LOG_DEBUG, "load acl from regex %s", regexstr); return; d815 1 d818 3 a820 2 acl_add_rcpt_regex(regexstr) char *regexstr; d822 1 a822 3 size_t len; int error; char errstr[ERRLEN + 1]; d824 2 a825 6 if (gacl.a_rcpt != NULL || gacl.a_rcpt_re != NULL || gacl.a_rcptlist != NULL) { mg_log(LOG_ERR, "rcpt specified twice in ACL line %d", conf_line); d828 1 a828 28 /* * Strip leading and trailing slashes */ len = strlen(regexstr); if (len > 0) regexstr[len - 1] = '\0'; regexstr++; if ((gacl.a_rcpt_re = malloc(sizeof(*gacl.a_rcpt_re))) == NULL) { mg_log(LOG_ERR, "acl malloc failed: %s", strerror(errno)); exit(EX_OSERR); } if ((error = regcomp(gacl.a_rcpt_re, regexstr, (conf.c_extendedregex ? REG_EXTENDED : 0) | REG_ICASE)) != 0) { regerror(error, gacl.a_rcpt_re, errstr, ERRLEN); mg_log(LOG_ERR, "bad regular expression \"%s\": %s", regexstr, errstr); exit(EX_OSERR); } if ((gacl.a_rcpt_re_copy = strdup(regexstr)) == NULL) { mg_log(LOG_ERR, "acl strdup failed: %s", strerror(errno)); exit(EX_OSERR); } if (conf.c_debug || conf.c_acldebug) mg_log(LOG_DEBUG, "load acl rcpt regex %s", regexstr); d832 4 a835 4 void acl_add_domain_regex(regexstr) char *regexstr; { a836 45 int error; char errstr[ERRLEN + 1]; if (gacl.a_domain != NULL || gacl.a_domain_re != NULL || gacl.a_domainlist != NULL) { mg_log(LOG_ERR, "domain specified twice in ACL line %d", conf_line); exit(EX_DATAERR); } /* * Strip leading and trailing slashes */ len = strlen(regexstr); if (len > 0) regexstr[len - 1] = '\0'; regexstr++; if ((gacl.a_domain_re = malloc(sizeof(*gacl.a_domain_re))) == NULL) { mg_log(LOG_ERR, "acl malloc failed: %s", strerror(errno)); exit(EX_OSERR); } if ((error = regcomp(gacl.a_domain_re, regexstr, (conf.c_extendedregex ? REG_EXTENDED : 0) | REG_ICASE)) != 0) { regerror(error, gacl.a_domain_re, errstr, ERRLEN); mg_log(LOG_ERR, "bad regular expression \"%s\": %s", regexstr, errstr); exit(EX_OSERR); } if ((gacl.a_domain_re_copy = strdup(regexstr)) == NULL) { mg_log(LOG_ERR, "acl strdup failed: %s", strerror(errno)); exit(EX_OSERR); } if (conf.c_debug || conf.c_acldebug) mg_log(LOG_DEBUG, "load acl domain regex %s", regexstr); return; } void acl_add_header_regex(regexstr) char *regexstr; d838 2 a839 44 size_t len; int error; char errstr[ERRLEN + 1]; if (gacl.a_header != NULL || gacl.a_header_re != NULL || gacl.a_headerlist != NULL) { mg_log(LOG_ERR, "header specified twice in ACL line %d", conf_line); exit(EX_DATAERR); } /* * Strip leading and trailing slashes */ len = strlen(regexstr); if (len > 0) regexstr[len - 1] = '\0'; regexstr++; if ((gacl.a_header_re = malloc(sizeof(*gacl.a_header_re))) == NULL) { mg_log(LOG_ERR, "acl malloc failed: %s", strerror(errno)); exit(EX_OSERR); } if ((error = regcomp(gacl.a_header_re, regexstr, (conf.c_extendedregex ? REG_EXTENDED : 0) | REG_ICASE)) != 0) { regerror(error, gacl.a_header_re, errstr, ERRLEN); mg_log(LOG_ERR, "bad regular expression \"%s\": %s", regexstr, errstr); exit(EX_OSERR); } if ((gacl.a_header_re_copy = strdup(regexstr)) == NULL) { mg_log(LOG_ERR, "acl strdup failed: %s", strerror(errno)); exit(EX_OSERR); } if (conf.c_debug || conf.c_acldebug) mg_log(LOG_DEBUG, "load acl header regex %s", regexstr); if (conf.c_maxpeek == 0) conf.c_maxpeek = -1; return; d843 3 a845 2 acl_add_body_regex(regexstr) char *regexstr; d847 3 a849 3 size_t len; int error; char errstr[ERRLEN + 1]; d851 1 a851 15 if (gacl.a_body != NULL || gacl.a_body_re != NULL || gacl.a_bodylist != NULL) { mg_log(LOG_ERR, "body specified twice in ACL line %d", conf_line); exit(EX_DATAERR); } /* * Strip leading and trailing slashes */ len = strlen(regexstr); if (len > 0) regexstr[len - 1] = '\0'; regexstr++; d853 1 a853 1 if ((gacl.a_body_re = malloc(sizeof(*gacl.a_header_re))) == NULL) { d857 10 a866 6 if ((error = regcomp(gacl.a_body_re, regexstr, (conf.c_extendedregex ? REG_EXTENDED : 0) | REG_ICASE)) != 0) { regerror(error, gacl.a_body_re, errstr, ERRLEN); mg_log(LOG_ERR, "bad regular expression \"%s\": %s", regexstr, errstr); exit(EX_OSERR); d869 23 a891 3 if ((gacl.a_body_re_copy = strdup(regexstr)) == NULL) { mg_log(LOG_ERR, "acl strdup failed: %s", strerror(errno)); exit(EX_OSERR); d894 6 a899 2 if (conf.c_debug || conf.c_acldebug) mg_log(LOG_DEBUG, "load acl body regex %s", regexstr); d913 19 a941 5 if ((gacl.a_rcptlist || gacl.a_rcpt || gacl.a_rcpt_re)) { mg_log(LOG_ERR, "rcpt clause in DATA stage ACL " "at line %d", conf_line - 1); exit(EX_DATAERR); } d961 1 a961 1 *acl = gacl; d995 19 a1023 5 if ((gacl.a_rcptlist || gacl.a_rcpt || gacl.a_rcpt_re)) { mg_log(LOG_ERR, "rcpt clause in DATA stage ACL " "at line %d", conf_line - 1); exit(EX_DATAERR); } d1048 1 a1048 1 acl_init_entry (); d1087 1 d1091 1 d1107 1 d1117 4 a1120 7 if (acl->a_addrlist != NULL) { if (list_addr_filter(acl->a_addrlist, sa)) { retval |= EXF_ADDR; } else { continue; } } d1122 1 a1122 178 if (acl->a_addr != NULL) { if (ip_match(sa, acl->a_addr, acl->a_mask)) { retval |= EXF_ADDR; } else { continue; } } if (acl->a_domainlist != NULL) { if (list_domain_filter(acl->a_domainlist, hostname)) { retval |= EXF_DOMAIN; } else { continue; } } if (acl->a_domain != NULL) { if (domaincmp(hostname, acl->a_domain)) { retval |= EXF_DOMAIN; } else { continue; } } if (acl->a_domain_re != NULL) { if (regexec(acl->a_domain_re, hostname, 0, NULL, 0) == 0) { retval |= EXF_DOMAIN; } else { continue; } } if (acl->a_fromlist != NULL) { if (list_from_filter(acl->a_fromlist, from)) { retval |= EXF_FROM; } else { continue; } } if (acl->a_from != NULL) { if (emailcmp(from, acl->a_from) == 0) { retval |= EXF_FROM; } else { continue; } } if (acl->a_from_re != NULL) { if (regexec(acl->a_from_re, from, 0, NULL, 0) == 0) { retval |= EXF_FROM; } else { continue; } } if (cur_rcpt && (acl->a_rcptlist != NULL)) { if (list_rcpt_filter(acl->a_rcptlist, cur_rcpt)) { retval |= EXF_RCPT; } else { continue; } } if (cur_rcpt && (acl->a_rcpt != NULL)) { if (emailcmp(cur_rcpt, acl->a_rcpt) == 0) { retval |= EXF_RCPT; } else { continue; } } if (cur_rcpt && (acl->a_rcpt_re != NULL)) { if (regexec(acl->a_rcpt_re, cur_rcpt, 0, NULL, 0) == 0) { retval |= EXF_RCPT; } else { continue; } } if ((stage == AS_DATA) && (acl->a_header != NULL)) { struct header *h; int found = 0; LIST_FOREACH(h, &priv->priv_header, h_list) { if (strstr(h->h_line, acl->a_header) != NULL) { found = 1; break; } } if (found) retval |= EXF_HEADER; else continue; } if ((stage == AS_DATA) && (acl->a_header_re != NULL)) { struct header *h; int found = 0; LIST_FOREACH(h, &priv->priv_header, h_list) { if (regexec(acl->a_header_re, h->h_line, 0, NULL, 0) == 0){ found = 1; break; } } if (found) retval |= EXF_HEADER; else continue; } if ((stage == AS_DATA) && (acl->a_body != NULL)) { struct body *b; int found = 0; LIST_FOREACH(b, &priv->priv_body, b_list) { if (strstr(b->b_lines, acl->a_body) != NULL) { found = 1; break; } } if (found) retval |= EXF_BODY; else continue; } if ((stage == AS_DATA) && (acl->a_body_re != NULL)) { struct body *b; int found = 0; LIST_FOREACH(b, &priv->priv_body, b_list) { if (regexec(acl->a_body_re, b->b_lines, 0, NULL, 0) == 0){ found = 1; break; } } if (found) retval |= EXF_BODY; else continue; } #ifdef USE_DNSRBL if (acl->a_dnsrbllist != NULL) { if (list_dnsrbl_filter(acl->a_dnsrbllist, salen, sa)) { retval |= EXF_DNSRBL; } else { continue; } } if (acl->a_dnsrbl != NULL) { if (dnsrbl_check_source(sa, salen, acl->a_dnsrbl) == 1) { retval |= EXF_DNSRBL; } else { continue; } } #endif #ifdef USE_CURL if (acl->a_urlchecklist != NULL) { if (list_urlcheck_filter(acl->a_urlchecklist, priv, (cur_rcpt != NULL) ? cur_rcpt : NULL, &ap)) { retval |= EXF_URLCHECK; } else { continue; } d1124 2 a1126 24 if (acl->a_urlcheck != NULL) { if (urlcheck_validate(priv, (cur_rcpt != NULL) ? cur_rcpt : NULL, acl->a_urlcheck, &ap) == 1) { retval |= EXF_URLCHECK; } else { continue; } } #endif if (acl->a_macrolist != NULL) { if (list_macro_filter(acl->a_macrolist, ctx)) { retval |= EXF_MACRO; } else { continue; } } if (acl->a_macro != NULL) { if (macro_check(ctx, acl->a_macro) == 0) { retval |= EXF_MACRO; } else { continue; } } a1275 29 int domaincmp(host, domain) char *host; char *domain; { int hidx, didx; if ((host[0] == '\0') && domain[0] == '\0') return 1; if ((host[0] == '\0') || domain[0] == '\0') return 0; hidx = strlen(host) - 1; didx = strlen(domain) - 1; while ((hidx >= 0) && (didx >= 0)) { if (tolower((int)host[hidx]) != tolower((int)domain[didx])) { return (0); } hidx--; didx--; } if (didx >= 0) return (0); return (1); } d1338 1 d1344 9 a1352 22 if (acl->a_addr != NULL) { free(acl->a_addr); free(acl->a_mask); } if (acl->a_from != NULL) free(acl->a_from); if (acl->a_rcpt != NULL) free(acl->a_rcpt); if (acl->a_domain != NULL) free(acl->a_domain); if (acl->a_from_re != NULL) regfree(acl->a_from_re); if (acl->a_from_re_copy != NULL) free(acl->a_from_re_copy); if (acl->a_rcpt_re != NULL) regfree(acl->a_rcpt_re); if (acl->a_rcpt_re_copy != NULL) free(acl->a_rcpt_re_copy); if (acl->a_domain_re != NULL) regfree(acl->a_domain_re); if (acl->a_domain_re_copy != NULL) free(acl->a_domain_re_copy); a1373 2 char addrstr[IPADDRSTRLEN]; char maskstr[IPADDRSTRLEN]; d1375 1 d1377 12 a1388 2 snprintf(entrystr, HDRLEN, "%cacl %d ", (acl->a_stage == AS_RCPT) ? 'r' : 'd', acl->a_line); d1406 8 a1413 139 if (acl->a_addrlist != NULL) { snprintf(tempstr, sizeof(tempstr), "addr list \"%s\" ", acl->a_addrlist->al_name); mystrlcat(entrystr, tempstr, sizeof(entrystr)); def = 0; } if (acl->a_addr != NULL) { iptostring(acl->a_addr, acl->a_addrlen, addrstr, sizeof(addrstr)); inet_ntop(acl->a_addr->sa_family, acl->a_mask, maskstr, sizeof(maskstr)); snprintf(tempstr, sizeof(tempstr), "addr %s/%s ", addrstr, maskstr); mystrlcat(entrystr, tempstr, sizeof(entrystr)); def = 0; } if (acl->a_fromlist != NULL) { snprintf(tempstr, sizeof(tempstr), "from list \"%s\" ", acl->a_fromlist->al_name); mystrlcat(entrystr, tempstr, sizeof(entrystr)); def = 0; } if (acl->a_from != NULL) { snprintf(tempstr, sizeof(tempstr), "from %s ", acl->a_from); mystrlcat(entrystr, tempstr, sizeof(entrystr)); def = 0; } if (acl->a_from_re != NULL) { snprintf(tempstr, sizeof(tempstr), "from /%s/ ", acl->a_from_re_copy); mystrlcat(entrystr, tempstr, sizeof(entrystr)); def = 0; } if (acl->a_rcptlist != NULL) { snprintf(tempstr, sizeof(tempstr), "rcpt list \"%s\" ", acl->a_rcptlist->al_name); mystrlcat(entrystr, tempstr, sizeof(entrystr)); def = 0; } if (acl->a_rcpt != NULL) { snprintf(tempstr, sizeof(tempstr), "rcpt %s ", acl->a_rcpt); mystrlcat(entrystr, tempstr, sizeof(entrystr)); def = 0; } if (acl->a_rcpt_re != NULL) { snprintf(tempstr, sizeof(tempstr), "rcpt /%s/ ", acl->a_rcpt_re_copy); mystrlcat(entrystr, tempstr, sizeof(entrystr)); def = 0; } if (acl->a_domainlist != NULL) { snprintf(tempstr, sizeof(tempstr), "domainlist \"%s\" ", acl->a_domainlist->al_name); mystrlcat(entrystr, tempstr, sizeof(entrystr)); def = 0; } if (acl->a_domain != NULL) { snprintf(tempstr, sizeof(tempstr), "domain %s ", acl->a_domain); mystrlcat(entrystr, tempstr, sizeof(entrystr)); def = 0; } if (acl->a_domain_re != NULL) { snprintf(tempstr, sizeof(tempstr), "domain /%s/ ", acl->a_domain_re_copy); mystrlcat(entrystr, tempstr, sizeof(entrystr)); def = 0; } if (acl->a_header != NULL) { snprintf(tempstr, sizeof(tempstr), "header \"%s\" ", acl->a_header); mystrlcat(entrystr, tempstr, sizeof(entrystr)); def = 0; } if (acl->a_header_re != NULL) { snprintf(tempstr, sizeof(tempstr), "header /%s/ ", acl->a_header_re_copy); mystrlcat(entrystr, tempstr, sizeof(entrystr)); def = 0; } if (acl->a_headerlist != NULL) { snprintf(tempstr, sizeof(tempstr), "headerlist \"%s\" ", acl->a_headerlist->al_name); mystrlcat(entrystr, tempstr, sizeof(entrystr)); def = 0; } if (acl->a_body != NULL) { snprintf(tempstr, sizeof(tempstr), "body \"%s\" ", acl->a_body); mystrlcat(entrystr, tempstr, sizeof(entrystr)); def = 0; } if (acl->a_body_re != NULL) { snprintf(tempstr, sizeof(tempstr), "body /%s/ ", acl->a_body_re_copy); mystrlcat(entrystr, tempstr, sizeof(entrystr)); def = 0; } if (acl->a_bodylist != NULL) { snprintf(tempstr, sizeof(tempstr), "bodylist \"%s\" ", acl->a_bodylist->al_name); mystrlcat(entrystr, tempstr, sizeof(entrystr)); def = 0; } #if USE_DNSRBL if (acl->a_dnsrbllist != NULL) { snprintf(tempstr, sizeof(tempstr), "dnsrbllist \"%s\" ", acl->a_dnsrbllist->al_name); mystrlcat(entrystr, tempstr, sizeof(entrystr)); def = 0; } if (acl->a_dnsrbl != NULL) { snprintf(tempstr, sizeof(tempstr), "dnsrbl \"%s\" ", acl->a_dnsrbl->d_name); mystrlcat(entrystr, tempstr, sizeof(entrystr)); def = 0; } #endif #if USE_CURL if (acl->a_urlchecklist != NULL) { snprintf(tempstr, sizeof(tempstr), "urlchecklist \"%s\" ", acl->a_urlchecklist->al_name); mystrlcat(entrystr, tempstr, sizeof(entrystr)); def = 0; } if (acl->a_urlcheck != NULL) { snprintf(tempstr, sizeof(tempstr), "urlcheck \"%s\" ", acl->a_urlcheck->u_name); mystrlcat(entrystr, tempstr, sizeof(entrystr)); def = 0; } #endif if (acl->a_macrolist != NULL) { snprintf(tempstr, sizeof(tempstr), "sm_macrolist \"%s\" ", acl->a_macrolist->al_name); mystrlcat(entrystr, tempstr, sizeof(entrystr)); def = 0; } if (acl->a_macro != NULL) { snprintf(tempstr, sizeof(tempstr), "sm_macro \"%s\" ", acl->a_macro->m_name); d1417 1 d1526 3 a1528 2 acl_add_list(list) char *list; d1530 1 d1532 1 d1540 4 a1543 5 switch (ale->al_type) { case LT_FROM: if (gacl.a_from != NULL || gacl.a_from_re != NULL || gacl.a_fromlist != NULL) { d1545 2 a1546 2 "muliple from statement (list \"%s\", line %d)", list, conf_line); d1549 1 a1549 72 gacl.a_fromlist = ale; break; case LT_RCPT: if (gacl.a_rcpt != NULL || gacl.a_rcpt_re != NULL || gacl.a_rcptlist != NULL) { mg_log(LOG_ERR, "muliple rcpt statement (list \"%s\", line %d)", list, conf_line); exit(EX_DATAERR); } gacl.a_rcptlist = ale; break; case LT_DOMAIN: if (gacl.a_domain != NULL || gacl.a_domain_re != NULL || gacl.a_domainlist != NULL) { mg_log(LOG_ERR, "muliple domain statement (list \"%s\", line %d)", list, conf_line); exit(EX_DATAERR); } gacl.a_domainlist = ale; break; #if USE_DNSRBL case LT_DNSRBL: if (gacl.a_dnsrbl != NULL || gacl.a_dnsrbllist != NULL) { mg_log(LOG_ERR, "muliple dnsrbl statement (list \"%s\", line %d)", list, conf_line); exit(EX_DATAERR); } gacl.a_dnsrbllist = ale; break; #endif #if USE_CURL case LT_URLCHECK: if (gacl.a_urlcheck != NULL || gacl.a_urlchecklist != NULL) { mg_log(LOG_ERR, "muliple urlcheck statement (list \"%s\", line %d)", list, conf_line); exit(EX_DATAERR); } gacl.a_urlchecklist = ale; break; #endif case LT_MACRO: if (gacl.a_macro != NULL || gacl.a_macrolist != NULL) { mg_log(LOG_ERR, "muliple sm_macro statement (list \"%s\", line %d)", list, conf_line); exit(EX_DATAERR); } gacl.a_macrolist = ale; break; case LT_ADDR: if (gacl.a_addr != NULL || gacl.a_addrlist != NULL) { mg_log(LOG_ERR, "muliple addr statement (list \"%s\", line %d)", list, conf_line); exit(EX_DATAERR); } gacl.a_addrlist = ale; break; d1551 1 a1551 9 default: mg_log(LOG_ERR, "unexpected al_type %d line %d", ale->al_type, conf_line); exit(EX_DATAERR); break; } if (conf.c_debug || conf.c_acldebug) mg_log(LOG_DEBUG, "load acl list \"%s\"", list); @ 1.38 log @DATA stage ACL, with some limitations: only whitelist or blacklist, and no access to rcpt. @ text @d1 1 a1 1 /* $Id: acl.c,v 1.37 2006/12/06 15:02:41 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.37 2006/12/06 15:02:41 manu Exp $"); d305 52 d521 100 d629 8 d647 8 d691 1 a691 1 acl_type_t acl_stage; d697 8 d715 8 d758 1 a758 1 acl_filter(stage, ctx, priv, rcpt) a761 1 char *rcpt; d775 1 d782 1 d865 2 a866 2 if (acl->a_rcptlist != NULL) { if (list_rcpt_filter(acl->a_rcptlist, rcpt)) { d873 2 a874 2 if (acl->a_rcpt != NULL) { if (emailcmp(rcpt, acl->a_rcpt) == 0) { d881 3 a883 2 if (acl->a_rcpt_re != NULL) { if (regexec(acl->a_rcpt_re, rcpt, 0, NULL, 0) == 0) { d889 70 d980 2 a981 1 priv, rcpt, &ap)) { d989 2 a990 1 if (urlcheck_validate(priv, rcpt, d1085 2 a1086 1 "is matched by entry %s", from, rcpt, d1133 1 a1133 1 if (retval & EXF_RCPT) { d1135 1 a1135 1 "recipient %s is whitelisted", rcpt); d1148 3 a1150 1 "(from=%s, rcpt=%s, addr=%s[%s])", from, rcpt, hostname, addrstr); d1389 36 @ 1.37 log @Add URL check feature Bump to 3.1.2 @ text @d1 1 a1 1 /* $Id: acl.c,v 1.36 2006/10/08 13:21:09 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.36 2006/10/08 13:21:09 manu Exp $"); d470 2 a471 1 acl_register_entry_first(acl_type) /* acllist must be write-locked */ d476 13 d495 1 d522 2 a523 1 acl_register_entry_last(acl_type) /* acllist must be write-locked */ d528 13 d546 1 d574 2 a575 1 acl_filter(ctx, priv, rcpt) d602 3 d780 1 a780 1 priv->priv_acl_line = acl->a_line; d782 1 a782 1 priv->priv_delay = d784 1 a784 1 priv->priv_autowhite = d789 2 a790 1 if ((priv->priv_code = strdup(ap.ap_code)) == NULL) { d797 2 a798 1 if ((priv->priv_ecode = strdup(ap.ap_ecode)) == NULL) { d805 2 a806 1 if ((priv->priv_msg = strdup(ap.ap_msg)) == NULL) { d840 2 a841 2 priv->priv_delay = conf.c_delay; priv->priv_autowhite = conf.c_autowhite_validity; d1043 2 a1044 1 snprintf(entrystr, HDRLEN, "acl %d ", acl->a_line); @ 1.36 log @Remove the /tmp/access-list.debug for security sake (AIDA Shinra) @ text @d1 1 a1 1 /* $Id: acl.c,v 1.35 2006/10/02 17:03:57 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.35 2006/10/02 17:03:57 manu Exp $"); d70 3 d235 24 d560 1 d573 8 d687 19 d730 1 a730 1 switch (acl->a_type) { d749 1 a749 1 (acl->a_delay != -1) ? acl->a_delay : conf.c_delay; d751 2 a752 2 (acl->a_autowhite != -1) ? acl->a_autowhite : conf.c_autowhite_validity; d754 2 a755 2 if (acl->a_code) { if ((priv->priv_code = strdup(acl->a_code)) == NULL) { d761 2 a762 2 if (acl->a_ecode) { if ((priv->priv_ecode = strdup(acl->a_ecode)) == NULL) { d768 2 a769 2 if (acl->a_msg) { if ((priv->priv_msg = strdup(acl->a_msg)) == NULL) { d776 7 d784 1 a784 1 if (acl->a_flags & A_FLUSHADDR) d821 6 d1104 14 d1298 12 @ 1.35 log @display fix in logs @ text @d1 1 a1 1 /* $Id: acl.c,v 1.34 2006/09/04 21:28:18 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.34 2006/09/04 21:28:18 manu Exp $"); d1092 1 a1092 1 FILE *debug; d1096 1 a1096 1 * We also write the ACL in a file because syslogd seems to lose d1098 4 d1103 1 d1105 1 @ 1.34 log @Fix various race conditions (AIDA Shinra) Fix big bugs in macro support (AIDA Shinra) @ text @d1 1 a1 1 /* $Id: acl.c,v 1.33 2006/08/27 20:54:40 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.33 2006/08/27 20:54:40 manu Exp $"); a636 9 if (conf.c_debug) { iptostring(sa, salen, addrstr, sizeof(addrstr)); mg_log(LOG_DEBUG, "Mail from addr=%s[%s] exists in " "DNSRBL \"%s\"", hostname, addrstr, acl->a_dnsrbl->d_name); } a645 9 if (conf.c_debug) { iptostring(sa, salen, addrstr, sizeof(addrstr)); mg_log(LOG_DEBUG, "Mail from addr=%s[%s] exists in " "DNSRBL \"%s\"", hostname, addrstr, acl->a_dnsrbl->d_name); } @ 1.33 log @Remove the need of LOG_PERROR, make sure no log is missed @ text @d1 1 a1 1 /* $Id: acl.c,v 1.32 2006/08/27 16:02:25 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.32 2006/08/27 16:02:25 manu Exp $"); d517 2 a518 1 acl_filter(priv, rcpt) d669 14 d792 5 @ 1.33.2.1 log @Fix serious bugs in macro handling (AIDA Shinra) @ text @d1 1 a1 1 /* $Id: acl.c,v 1.33 2006/08/27 20:54:40 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.33 2006/08/27 20:54:40 manu Exp $"); d517 1 a517 2 acl_filter(ctx, priv, rcpt) SMFICTX *ctx; a667 14 if (acl->a_macrolist != NULL) { if (list_macro_filter(acl->a_macrolist, ctx)) { retval |= EXF_MACRO; } else { continue; } } if (acl->a_macro != NULL) { if (macro_check(ctx, acl->a_macro) == 0) { retval |= EXF_MACRO; } else { continue; } } a776 5 if (retval & EXF_MACRO) { snprintf(tmpstr, sizeof(tmpstr), "macro rule is satisfied"); ADD_REASON(whystr, tmpstr); } @ 1.33.2.2 log @Fix display message in log messages @ text @d1 1 a1 1 /* $Id: acl.c,v 1.33.2.1 2006/09/04 22:07:21 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.33.2.1 2006/09/04 22:07:21 manu Exp $"); d637 9 d655 9 @ 1.33.2.3 log @Remove the /tmp/access-list.debug for security sake (AIDA Shinra) @ text @d1 1 a1 1 /* $Id: acl.c,v 1.33.2.2 2006/10/02 17:02:42 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.33.2.2 2006/10/02 17:02:42 manu Exp $"); d1092 1 a1092 1 FILE *debug = NULL; d1096 1 a1096 1 * We can also write the ACL in a file because syslogd seems to lose a1097 4 * XXX This is disabled by default (#if 0 above) since it creates * security hazards: /tmp/access-list.debug could already exist and * be a link to some system file which would be overwritten. * Enable it if you need it, but you may be better changing the path a1098 1 #if 0 a1099 1 #endif @ 1.32 log @Add support to use Sendmail macros in the ACL @ text @d1 1 a1 1 /* $Id: acl.c,v 1.31 2006/08/20 06:38:43 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.31 2006/08/20 06:38:43 manu Exp $"); d91 1 a91 1 syslog(LOG_ERR, "pthread_rwlock_init failed: %s", d121 2 a122 2 fprintf (stderr, "addr specified twice in ACL line %d\n", d138 2 a139 2 fprintf(stderr, "bad address family in acl list line %d\n", d144 1 a144 1 fprintf(stderr, "bad mask in acl list line %d\n", d166 1 a166 1 syslog(LOG_ERR, "acl malloc failed: %s", strerror(errno)); d179 1 a179 1 printf("load acl net %s/%s\n", addrstr, maskstr); d192 2 a193 2 fprintf (stderr, "from specified twice in ACL line %d\n", d198 1 a198 1 syslog(LOG_ERR, "acl malloc failed: %s", strerror(errno)); d203 1 a203 1 printf("load acl from %s\n", email); d215 2 a216 2 fprintf (stderr, "dnsrbl specified twice in ACL line %d\n", d221 1 a221 1 syslog(LOG_ERR, "unknown DNSRBL \"%s\"", dnsrbl); d226 1 a226 1 printf("load acl dnsrbl %s\n", dnsrbl); d238 2 a239 2 fprintf (stderr, "sm_macro specified twice in ACL line %d\n", d244 1 a244 1 syslog(LOG_ERR, "unknown sm_macro \"%s\"", macro); d249 1 a249 1 printf("load acl sm_macro %s\n", macro); d261 2 a262 2 fprintf (stderr, "rcpt specified twice in ACL line %d\n", d267 1 a267 1 syslog(LOG_ERR, "acl malloc failed: %s", strerror(errno)); d272 1 a272 1 printf("load acl rcpt %s\n", email); d284 2 a285 2 fprintf (stderr, "domain specified twice in ACL line %d\n", d290 1 a290 1 syslog(LOG_ERR, "acl malloc failed: %s", strerror(errno)); d295 1 a295 1 printf("load acl domain %s\n", domain); d312 2 a313 2 fprintf (stderr, "from specified twice in ACL line %d\n", d326 1 a326 1 syslog(LOG_ERR, "acl malloc failed: %s", strerror(errno)); d332 1 a332 1 fprintf(stderr, "bad regular expression \"%s\": %s\n", d338 1 a338 1 syslog(LOG_ERR, "acl strdup failed: %s", strerror(errno)); d343 1 a343 1 printf("load acl from regex %s\n", regexstr); d359 2 a360 2 fprintf (stderr, "rcpt specified twice in ACL line %d\n", d373 1 a373 1 syslog(LOG_ERR, "acl malloc failed: %s", strerror(errno)); d379 1 a379 1 fprintf(stderr, "bad regular expression \"%s\": %s\n", d385 1 a385 1 syslog(LOG_ERR, "acl strdup failed: %s", strerror(errno)); d390 1 a390 1 printf("load acl rcpt regex %s\n", regexstr); d406 2 a407 2 fprintf (stderr, "domain specified twice in ACL line %d\n", d420 1 a420 1 syslog(LOG_ERR, "acl malloc failed: %s", strerror(errno)); d426 1 a426 1 fprintf(stderr, "bad regular expression \"%s\": %s\n", d432 1 a432 1 syslog(LOG_ERR, "acl strdup failed: %s", strerror(errno)); d437 1 a437 1 printf("load acl domain regex %s\n", regexstr); d449 1 a449 1 syslog(LOG_ERR, "ACL malloc failed: %s", strerror(errno)); d461 1 a461 1 printf("register acl first GREYLIST\n"); d464 1 a464 1 printf("register acl first WHITELIST\n"); d467 1 a467 1 printf("register acl first BLACKLIST\n"); d470 1 a470 1 syslog(LOG_ERR, "unecpected acl_type %d", acl_type); d486 1 a486 1 syslog(LOG_ERR, "ACL malloc failed: %s", strerror(errno)); d498 1 a498 1 printf("register acl last GREYLIST\n"); d501 1 a501 1 printf("register acl last WHITELIST\n"); d504 1 a504 1 printf("register acl last BLACKLIST\n"); d507 1 a507 1 syslog(LOG_ERR, "unecpected acl_type %d", acl_type); d639 1 a639 1 syslog(LOG_DEBUG, d657 1 a657 1 syslog(LOG_DEBUG, d689 1 a689 1 syslog(LOG_ERR, "corrupted acl list"); d704 1 a704 1 syslog(LOG_ERR, "strdup failed: %s", d711 1 a711 1 syslog(LOG_ERR, "strdup failed: %s", d718 1 a718 1 syslog(LOG_ERR, "strdup failed: %s", d730 1 a730 1 syslog(LOG_DEBUG, "Mail from=%s, rcpt=%s, addr=%s[%s] " d785 1 a785 1 syslog(LOG_INFO, "%s: skipping greylist because %s", d836 1 a836 1 syslog(LOG_ERR, "malloc failed: %s", strerror(errno)); d843 1 a843 1 syslog(LOG_ERR, "malloc failed: %s", strerror(errno)); d949 1 a949 1 syslog(LOG_ERR, "corrupted acl list"); d1099 1 a1099 1 syslog(LOG_INFO, "Access list dump:\n"); d1102 1 a1102 1 syslog(LOG_INFO, "%s\n", entry); d1104 1 a1104 1 fprintf (debug, "%s\n", entry); d1116 2 a1117 2 fprintf (stderr, "delay specified twice in ACL line %d\n", conf_line); d1124 1 a1124 1 printf("load acl delay %ld\n", (long)delay); d1134 2 a1135 2 fprintf (stderr, "autowhite specified twice in ACL line %d\n", conf_line); d1142 1 a1142 1 printf("load acl delay %ld\n", (long)delay); d1154 1 a1154 1 syslog(LOG_ERR, "inexistent list \"%s\" line %d", d1164 1 a1164 1 fprintf (stderr, d1176 1 a1176 1 fprintf (stderr, d1188 1 a1188 1 fprintf (stderr, d1200 1 a1200 1 fprintf (stderr, d1211 1 a1211 1 fprintf (stderr, d1222 1 a1222 1 fprintf (stderr, d1231 1 a1231 1 syslog(LOG_ERR, "unexpected al_type %d line %d", d1238 1 a1238 1 printf("load acl list \"%s\"\n", list); d1248 2 a1249 2 fprintf (stderr, "code specified twice in ACL line %d\n", conf_line); d1254 2 a1255 2 fprintf (stderr, "malloc failed in ACL line %d\n", conf_line); d1260 1 a1260 1 printf("load acl code \"%s\"\n", code); d1270 2 a1271 2 fprintf (stderr, "ecode specified twice in ACL line %d\n", conf_line); d1276 2 a1277 2 fprintf (stderr, "malloc failed in ACL line %d\n", conf_line); d1282 1 a1282 1 printf("load acl ecode \"%s\"\n", ecode); d1292 2 a1293 2 fprintf (stderr, "msg specified twice in ACL line %d\n", conf_line); d1298 2 a1299 2 fprintf (stderr, "malloc failed in ACL line %d\n", conf_line); d1304 1 a1304 1 printf("load acl msg \"%s\"\n", msg); @ 1.31 log @Fix improper strncpy usage (AIDA Shinra) @ text @d1 1 a1 1 /* $Id: acl.c,v 1.30 2006/08/20 05:52:20 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.30 2006/08/20 05:52:20 manu Exp $"); d70 1 d233 22 d1034 12 d1208 10 @ 1.30 log @(Fabien Tassin) Add more log output for blackist and flushaddr Allow rejecting by tempfail on blacklist configuration @ text @d1 1 a1 1 /* $Id: acl.c,v 1.29 2006/08/01 21:29:36 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.29 2006/08/01 21:29:36 manu Exp $"); d917 1 a917 1 strncat(entrystr, "greylist ", sizeof(entrystr)); d920 1 a920 1 strncat(entrystr, "whitelist ", sizeof(entrystr)); d923 1 a923 1 strncat(entrystr, "blacklist ", sizeof(entrystr)); d934 1 a934 1 strncat(entrystr, tempstr, sizeof(entrystr)); d943 1 a943 1 strncat(entrystr, tempstr, sizeof(entrystr)); d949 1 a949 1 strncat(entrystr, tempstr, sizeof(entrystr)); d954 1 a954 1 strncat(entrystr, tempstr, sizeof(entrystr)); d960 1 a960 1 strncat(entrystr, tempstr, sizeof(entrystr)); d966 1 a966 1 strncat(entrystr, tempstr, sizeof(entrystr)); d971 1 a971 1 strncat(entrystr, tempstr, sizeof(entrystr)); d977 1 a977 1 strncat(entrystr, tempstr, sizeof(entrystr)); d983 1 a983 1 strncat(entrystr, tempstr, sizeof(entrystr)); d988 1 a988 1 strncat(entrystr, tempstr, sizeof(entrystr)); d994 1 a994 1 strncat(entrystr, tempstr, sizeof(entrystr)); d1001 1 a1001 1 strncat(entrystr, tempstr, sizeof(entrystr)); d1007 1 a1007 1 strncat(entrystr, tempstr, sizeof(entrystr)); d1014 1 a1014 1 strncat(entrystr, tempstr, sizeof(entrystr)); d1020 1 a1020 1 strncat(entrystr, tempstr, sizeof(entrystr)); d1025 1 a1025 1 strncat(entrystr, tempstr, sizeof(entrystr)); d1031 1 a1031 1 strncat(entrystr, tempstr, sizeof(entrystr)); d1037 1 a1037 1 strncat(entrystr, tempstr, sizeof(entrystr)); d1043 1 a1043 1 strncat(entrystr, tempstr, sizeof(entrystr)); d1047 1 a1047 1 strncat(entrystr, "default", sizeof(entrystr)); @ 1.29 log @per-ACL code and SMTP replies @ text @d1 1 a1 1 /* $Id: acl.c,v 1.28 2006/08/01 17:08:15 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.28 2006/08/01 17:08:15 manu Exp $"); d703 1 a703 1 pending_del_addr(sa, salen); @ 1.28 log @IPv6 fixes, FreeBSD build fix @ text @d1 1 a1 1 /* $Id: acl.c,v 1.27 2006/08/01 14:55:20 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.27 2006/08/01 14:55:20 manu Exp $"); d494 4 a497 1 acl_filter(sa, salen, hostname, from, rcpt, queueid, delay, autowhite, line) a501 1 char *rcpt; a502 4 time_t *delay; time_t *autowhite; int *line; { d510 6 d671 1 a671 1 *line = acl->a_line; d673 1 a673 1 *delay = d675 1 a675 1 *autowhite = d679 23 d721 2 a722 2 *delay = conf.c_delay; *autowhite = conf.c_autowhite_validity; d888 6 d1028 18 d1197 66 @ 1.27 log @flushaddr @ text @d1 1 a1 1 /* $Id: acl.c,v 1.26 2006/07/31 17:09:41 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.26 2006/07/31 17:09:41 manu Exp $"); d625 1 a625 1 salen, acl->a_dnsrbl) != 0) { @ 1.26 log @fix warnings @ text @d1 1 a1 1 /* $Id: acl.c,v 1.25 2006/07/28 16:44:17 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.25 2006/07/28 16:44:17 manu Exp $"); d100 6 d675 3 d990 5 @ 1.25 log @Multi-line statements. @ text @d1 1 a1 1 /* $Id: acl.c,v 1.24 2006/07/28 15:53:30 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.24 2006/07/28 15:53:30 manu Exp $"); d971 1 a971 1 "[delay %ld] ", acl->a_delay); d977 1 a977 1 "[aw %ld] ", acl->a_autowhite); d1024 1 a1024 1 printf("load acl delay %ld\n", delay); d1042 1 a1042 1 printf("load acl delay %ld\n", delay); @ 1.24 log @uninitialized string, bump to 1.3.9 @ text @d1 1 a1 1 /* $Id: acl.c,v 1.23 2006/07/28 15:41:51 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.23 2006/07/28 15:41:51 manu Exp $"); d871 1 a871 1 strcpy(entrystr, "acl "); @ 1.23 log @Build fixes @ text @d1 1 a1 1 /* $Id: acl.c,v 1.22 2006/07/27 20:08:32 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.22 2006/07/27 20:08:32 manu Exp $"); d697 6 @ 1.22 log @cvs blacklist feature @ text @d1 1 a1 1 /* $Id: acl.c,v 1.21 2006/07/27 09:37:24 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.21 2006/07/27 09:37:24 manu Exp $"); d601 1 a601 1 if (list_dnsrbl_filter(acl->a_dnsrbllist, sa)) { d618 2 a619 1 if (dnsrbl_check_source(sa, acl->a_dnsrbl) != 0) { @ 1.21 log @sanity checks for multiple statements @ text @d1 1 a1 1 /* $Id: acl.c,v 1.20 2006/07/27 08:53:16 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.20 2006/07/27 08:53:16 manu Exp $"); d429 17 a445 3 if (conf.c_debug || conf.c_acldebug) printf("register acl first %s\n", (acl_type == A_GREYLIST) ? "GREYLIST" : "WHITELIST"); d466 17 a482 3 if (conf.c_debug || conf.c_acldebug) printf("register acl last %s\n", (acl_type == A_GREYLIST) ? "GREYLIST" : "WHITELIST"); d651 3 d865 17 a881 3 strncat(entrystr, (acl->a_type == A_GREYLIST) ? "greylist " : "whitelist ", sizeof(entrystr)); @ 1.20 log @Build fixes, --enable-dnsrbl flag @ text @d1 1 a1 1 /* $Id: acl.c,v 1.19 2006/07/26 21:41:00 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.19 2006/07/26 21:41:00 manu Exp $"); d182 3 a184 1 if (gacl.a_from != NULL || gacl.a_from_re != NULL) { d206 2 a207 1 if (gacl.a_dnsrbl != NULL) { d229 3 a231 1 if (gacl.a_rcpt != NULL || gacl.a_rcpt_re != NULL) { d252 3 a254 1 if (gacl.a_domain != NULL || gacl.a_domain_re != NULL) { d280 3 a282 1 if (gacl.a_from != NULL || gacl.a_from_re != NULL) { d327 3 a329 1 if (gacl.a_rcpt != NULL || gacl.a_rcpt_re != NULL) { d374 3 a376 1 if (gacl.a_domain != NULL || gacl.a_domain_re != NULL) { d1009 3 a1011 1 if (gacl.a_from != NULL || gacl.a_from_re != NULL) { d1013 1 a1013 1 "list \"%s\" conficts with from statement line %d", d1021 3 a1023 1 if (gacl.a_rcpt != NULL || gacl.a_rcpt_re != NULL) { d1025 1 a1025 1 "list \"%s\" conficts with rcpt statement line %d", d1033 3 a1035 1 if (gacl.a_domain != NULL || gacl.a_domain_re != NULL) { d1037 1 a1037 2 "list \"%s\" conficts with " "domain statement line %d", d1046 2 a1047 1 if (gacl.a_dnsrbl != NULL) { d1049 1 a1049 2 "list \"%s\" conficts with " "DNSRBL statement line %d", d1058 2 a1059 1 if (gacl.a_addr != NULL) { d1061 1 a1061 2 "list \"%s\" conficts with " "addr statement line %d", @ 1.19 log @Lists for from, rcpt, domain, netblocks and DNSRBL @ text @d1 1 a1 1 /* $Id: acl.c,v 1.18 2006/07/26 13:26:02 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.18 2006/07/26 13:26:02 manu Exp $"); d890 1 d903 1 d1026 1 d1037 1 @ 1.18 log @Rename struct dnsrbl_entry membersn, rename PATH -> QSTRING @ text @d1 1 a1 1 /* $Id: acl.c,v 1.17 2006/07/26 08:22:41 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.17 2006/07/26 08:22:41 manu Exp $"); d66 1 a76 3 static int emailcmp(char *, char *); static int domaincmp(char *, char *); d470 8 d479 1 a479 1 if (ip_match(sa, acl->a_addr, acl->a_mask)) d481 9 a489 1 else { d493 1 d495 1 a495 1 if (domaincmp(hostname, acl->a_domain)) d497 1 a497 1 else { d501 1 d504 1 a504 1 hostname, 0, NULL, 0) == 0) d506 9 a514 1 else { d518 1 d526 1 d534 9 d550 1 d559 17 d683 1 a683 1 static int d713 1 a713 1 static int d824 6 d839 6 d856 6 d873 6 d890 6 d979 79 @ 1.17 log @Report matching ACL line number in the logs @ text @d1 1 a1 1 /* $Id: acl.c,v 1.16 2006/07/26 07:54:38 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.16 2006/07/26 07:54:38 manu Exp $"); d533 1 a533 1 acl->a_dnsrbl->de_name); d815 1 a815 1 acl->a_dnsrbl->de_name); @ 1.16 log @Log DNSRBL matches @ text @d1 1 a1 1 /* $Id: acl.c,v 1.15 2006/07/26 07:31:17 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.15 2006/07/26 07:31:17 manu Exp $"); d414 1 d437 1 d449 1 a449 1 acl_filter(sa, salen, hostname, from, rcpt, queueid, delay, autowhite) d458 1 d563 2 @ 1.15 log @First work on DNSRBL @ text @d1 1 a1 1 /* $Id: acl.c,v 1.14 2006/07/24 22:49:43 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.14 2006/07/24 22:49:43 manu Exp $"); d507 1 a507 1 retval |= EXF_RCPT; d523 9 @ 1.14 log @per-acl greylist and autowhitelist setting @ text @d1 1 a1 1 /* $Id: acl.c,v 1.13 2006/04/13 11:17:10 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.13 2006/04/13 11:17:10 manu Exp $"); d66 3 d201 23 d519 9 d799 6 @ 1.13 log @cosmetic change in logs @ text @d1 1 a1 1 /* $Id: acl.c,v 1.12 2006/03/25 08:03:38 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.12 2006/03/25 08:03:38 manu Exp $"); d79 2 d421 1 a421 1 acl_filter(sa, salen, hostname, from, rcpt, queueid) d428 2 d515 7 d525 2 a526 2 "is matched by entry %s", from, rcpt, hostname, addrstr, acl_entry(acl)); d537 3 d764 12 d805 36 @ 1.12 log @Faster ACL code @ text @d1 1 a1 1 /* $Id: acl.c,v 1.11 2006/03/03 21:54:31 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.11 2006/03/03 21:54:31 manu Exp $"); d556 1 a556 1 "(from=%s, rcpt=%s, addr=%s[%s})", from, rcpt, hostname, addrstr); @ 1.11 log @Cosmetic changes in debug logs (Fredrik Pettai) @ text @d1 1 a1 1 /* $Id: acl.c,v 1.10 2005/10/31 09:53:02 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.10 2005/10/31 09:53:02 manu Exp $"); a431 1 int match; a435 2 match = 0; retval = 0; a436 1 match = 1; a442 1 match = 0; a449 1 match = 0; a457 1 match = 0; a464 1 match = 0; a471 1 match = 0; a478 1 match = 0; a485 1 match = 0; d496 1 a496 1 if (match == 1) { @ 1.10 log @Log hostnames as well as IP in ACl debug @ text @d1 1 a1 1 /* $Id: acl.c,v 1.9 2005/06/10 08:36:50 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.9 2005/06/10 08:36:50 manu Exp $"); d524 1 a524 1 syslog(LOG_DEBUG, "Mail from=%s, rcpt=%s, addr=%s[%s} " @ 1.9 log @Fix suffix match for domain clause @ text @d1 1 a1 1 /* $Id: acl.c,v 1.8 2005/06/08 19:33:17 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.8 2005/06/08 19:33:17 manu Exp $"); d524 2 a525 2 syslog(LOG_DEBUG, "Mail from=%s, rcpt=%s, addr=%s " "is matched by entry %s", from, rcpt, addrstr, d567 1 a567 1 "(from=%s, rcpt=%s, addr=%s)", from, rcpt, addrstr); @ 1.8 log @Perfom suffix match for the domain clause @ text @d1 1 a1 1 /* $Id: acl.c,v 1.7 2005/05/23 20:41:31 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.7 2005/05/23 20:41:31 manu Exp $"); d452 1 a452 1 if (domaincmp(hostname, acl->a_domain) == 0) @ 1.7 log @Don't free a pointer that was changed @ text @d1 1 a1 1 /* $Id: acl.c,v 1.6 2005/05/22 10:12:54 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.6 2005/05/22 10:12:54 manu Exp $"); d74 1 d452 1 a452 2 /* Use emailcmp even if it's not an e-mail */ if (emailcmp(hostname, acl->a_domain) == 0) d577 31 @ 1.6 log @Bugfix in address comparison code @ text @d1 1 a1 1 /* $Id: acl.c,v 1.5 2005/03/19 07:38:53 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.5 2005/03/19 07:38:53 manu Exp $"); d586 2 d593 1 d600 1 d629 2 a630 2 free(cbig); free(clittle); @ 1.5 log @extendedregex for using extended regex instead of basic regex. @ text @d1 1 a1 1 /* $Id: acl.c,v 1.4 2005/03/18 23:48:20 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.4 2005/03/18 23:48:20 manu Exp $"); d583 15 a598 1 printf("big = \"%s\", little = \"%s\"\n", big, little); d600 4 a603 4 while (strchr("< \t", big[0]) != NULL) big++; while (strchr("< \t", little[0]) != NULL) little++; d606 6 a611 8 i = strlen(big) - 1; while ((i >= 0) && (strchr("> \t", big[i]) != NULL)) big[i--] = '\0'; i = strlen(little) - 1; while ((i >= 0) && (strchr("> \t", little[i]) != NULL)) little[i--] = '\0'; printf(">> big = \"%s\", little = \"%s\"\n", big, little); d613 2 a614 2 while (big[0] && little[0]) { if (tolower((int)big[0]) != tolower((int)little[0])) d616 2 a617 2 big++; little++; d620 4 a623 2 if (big[0] || little[0]) return -1; d625 4 a628 2 printf("match\n"); return 0; @ 1.4 log @Better email_cmp, strip leading [< \t] and trailing [> \t]. But it is useless since [ \t] get replaced by _ beforehand. @ text @d1 1 a1 1 /* $Id: acl.c,v 1.3 2005/03/13 16:43:03 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.3 2005/03/13 16:43:03 manu Exp $"); d264 2 a265 1 if ((error = regcomp(gacl.a_from_re, regexstr, REG_ICASE)) != 0) { d309 2 a310 1 if ((error = regcomp(gacl.a_rcpt_re, regexstr, REG_ICASE)) != 0) { d354 2 a355 1 if ((error = regcomp(gacl.a_domain_re, regexstr, REG_ICASE)) != 0) { @ 1.3 log @Move e-mail matching to exact match @ text @d1 1 a1 1 /* $Id: acl.c,v 1.2 2005/02/07 22:01:51 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.2 2005/02/07 22:01:51 manu Exp $"); d581 3 a583 2 /* Strip leading < */ while (big[0] == '<') d585 1 a585 1 while (little[0] == '<') d588 1 a588 1 /* Strip trailing > */ d590 1 a590 1 while ((i >= 0) && (big[i] == '>')) d593 1 a593 1 while ((i >= 0) && (little[i] == '>')) d596 2 d608 1 @ 1.2 log @Shut down warnings in acl.c @ text @d1 1 a1 1 /* $Id: acl.c,v 1.1 2004/12/08 22:23:43 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.1 2004/12/08 22:23:43 manu Exp $"); d581 15 a595 1 while (big[0]) { d597 4 a600 7 big++; for (i = 0; big[0] && little[i]; i++) { if (tolower((int)big[0]) != tolower((int)little[i])) break; big++; } d602 2 a603 3 if (little[i] == 0) return 0; } d605 1 a605 1 return 1; @ 1.1 log @New ACL framework for whitelist and greylist (Remy Card) @ text @d1 1 a1 1 /* $Id: acl.c,v 1.50 2004/10/11 20:57:42 manu Exp $ */ d37 1 a37 1 __RCSID("$Id: acl.c,v 1.50 2004/10/11 20:57:42 manu Exp $"); d582 1 a582 1 if (tolower(big[0]) != tolower(little[0])) d586 1 a586 1 if (tolower(big[0]) != tolower(little[i])) @