From d4af7a5e1ba2f371803245e1952d4309838328f9 Mon Sep 17 00:00:00 2001 From: manu Date: Mon, 8 Jun 2009 23:40:06 +0000 Subject: [PATCH] Allow ACL override by ldapcheck clauses (Piotr Wadas) --- ChangeLog | 1 + acl.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++-- acl.h | 4 +- conf_lex.l | 6 ++- conf_yacc.y | 29 +++++++++++--- ldapcheck.c | 61 +++++++++++++++++++++-------- ldapcheck.h | 4 +- urlcheck.c | 105 ++------------------------------------------------ 8 files changed, 187 insertions(+), 132 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6070ba9..52bd2de 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ 4.3.3 + Allow ACL override by ldapcheck clauses (Piotr Wadas) Header for autowhitelisted messages bug fix (Attila Bruncsak) Fix MX sync stop on config reload (Attila Bruncsak, Hajimu UMEMOTO) Improve Debian startup script (Adam Katz) diff --git a/acl.c b/acl.c index 6bdf3fe..0f054bd 100644 --- a/acl.c +++ b/acl.c @@ -1,4 +1,4 @@ -/* $Id: acl.c,v 1.90 2009/04/16 12:33:19 manu Exp $ */ +/* $Id: acl.c,v 1.91 2009/06/08 23:40:06 manu Exp $ */ /* * Copyright (c) 2004-2007 Emmanuel Dreyfus @@ -34,7 +34,7 @@ #ifdef HAVE_SYS_CDEFS_H #include #ifdef __RCSID -__RCSID("$Id: acl.c,v 1.90 2009/04/16 12:33:19 manu Exp $"); +__RCSID("$Id: acl.c,v 1.91 2009/06/08 23:40:06 manu Exp $"); #endif #endif @@ -2522,7 +2522,7 @@ acl_add_report(report) } void -acl_add_addheader(hdr) + acl_add_addheader(hdr) char *hdr; { if (gacl->a_addheader) { @@ -2542,3 +2542,106 @@ acl_add_addheader(hdr) 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 + 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, "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; +} diff --git a/acl.h b/acl.h index 9e8eb9b..478aba7 100644 --- a/acl.h +++ b/acl.h @@ -1,4 +1,4 @@ -/* $Id: acl.h,v 1.39 2008/11/26 05:20:13 manu Exp $ */ +/* $Id: acl.h,v 1.40 2009/06/08 23:40:06 manu Exp $ */ /* * Copyright (c) 2004-2007 Emmanuel Dreyfus @@ -316,7 +316,7 @@ int acl_msgsize_cmp(acl_data_t *, acl_stage_t, int acl_opnum_cmp(int, enum operator, int); int myregexec(struct mlfi_priv *, acl_data_t *, struct acl_param *, const char *); - +int acl_modify_by_prop(char *, char *, struct acl_param *); /* acl_filter() return codes */ #define EXF_UNSET 0 #define EXF_GREYLIST (1 << 0) diff --git a/conf_lex.l b/conf_lex.l index c907ef5..c689621 100644 --- a/conf_lex.l +++ b/conf_lex.l @@ -61,6 +61,8 @@ delay -?[0-9]+[smhdw]? qstring "\""([^"\n]|\\\")+"\"" regex "/"([^/\n]|\\"/")+"/" dumpfreq [Dd][Uu][Mm][Pp][Ff][Rr][Ee][Qq]:? +binddn [Bb][Ii][Nn][Dd][Dd][Nn] +bindpw [Bb][Ii][Nn][Dd][Pp][Ww] timeout [Tt][Ii][Mm][Ee][Oo][Uu][Tt]:? time [Tt][Ii][Mm][Ee] domain [Dd][Oo][Mm][Aa][Ii][Nn]:? @@ -161,7 +163,7 @@ domainexact [Dd][Oo][Mm][Aa][Ii][Nn][Ee][Xx][Aa][Cc][Tt] #ifndef HAVE_BROKEN_RCSID #include #ifdef __RCSID - __RCSID("$Id: conf_lex.l,v 1.89 2009/01/17 04:32:55 manu Exp $"); + __RCSID("$Id: conf_lex.l,v 1.90 2009/06/08 23:40:06 manu Exp $"); #endif #endif #endif @@ -308,6 +310,8 @@ domainexact [Dd][Oo][Mm][Aa][Ii][Nn][Ee][Xx][Aa][Cc][Tt] {all} { return ALL; } {dumpfreq} { return GLDUMPFREQ; } {timeout} { return GLTIMEOUT; } +{binddn} { return LDAPBINDDN; } +{bindpw} { return LDAPBINDPW; } {time} { BEGIN(S_CLOCKSPEC1); return TIME; } {domain} { BEGIN(S_REGEX); return DOMAIN; } {syncaddr} { return SYNCADDR; } diff --git a/conf_yacc.y b/conf_yacc.y index b67855c..9a47856 100644 --- a/conf_yacc.y +++ b/conf_yacc.y @@ -14,7 +14,8 @@ %token LOGFAC_NEWS LOGFAC_UUCP LOGFAC_CRON LOGFAC_AUTHPRIV LOGFAC_FTP %token LOGFAC_LOCAL0 LOGFAC_LOCAL1 LOGFAC_LOCAL2 LOGFAC_LOCAL3 LOGFAC_LOCAL4 %token LOGFAC_LOCAL5 LOGFAC_LOCAL6 LOGFAC_LOCAL7 P0F P0FSOCK DKIMCHECK -%token SPAMDSOCK SPAMDSOCKT SPAMD DOMAINEXACT ADDHEADER NOLOG +%token SPAMDSOCK SPAMDSOCKT SPAMD DOMAINEXACT ADDHEADER NOLOG LDAPBINDDN +%token LDAPBINDPW %{ #include "config.h" @@ -22,7 +23,7 @@ #ifdef HAVE_SYS_CDEFS_H #include #ifdef __RCSID -__RCSID("$Id: conf_yacc.y,v 1.101 2009/04/09 03:36:30 manu Exp $"); +__RCSID("$Id: conf_yacc.y,v 1.102 2009/06/08 23:40:06 manu Exp $"); #endif #endif @@ -1386,17 +1387,35 @@ urlcheckdef_fork: FORK { } ; -ldapconfdef: LDAPCONF QSTRING ldaptimeout { +ldapconfdef: LDAPCONF QSTRING ldaptimeout + LDAPBINDDN QSTRING LDAPBINDPW QSTRING { #ifdef USE_LDAP char uris[QSTRLEN + 1]; - - ldapcheck_conf_add(quotepath(uris, $2, QSTRLEN)); + char bdn[QSTRLEN +1 ]; + char bpw[QSTRLEN + 1 ]; + ldapcheck_conf_add( + quotepath(uris, $2, QSTRLEN), + quotepath(bdn, $5, QSTRLEN), + quotepath(bpw, $7, QSTRLEN)); #else mg_log(LOG_INFO, "LDAP support not compiled in, ignore line %d", conf_line); #endif } + | LDAPCONF QSTRING ldaptimeout { /* 4.2.1 backward compatiblity */ + #ifdef USE_LDAP + char uris[QSTRLEN + 1]; + char *bdn = NULL; + char *bpw = NULL; + ldapcheck_conf_add( + quotepath(uris, $2, QSTRLEN), bdn, bpw); + #else + mg_log(LOG_INFO, + "LDAP support not compiled in, ignore line %d", + conf_line); + #endif + } ; ldaptimeout: GLTIMEOUT TDELAY { #ifdef USE_LDAP diff --git a/ldapcheck.c b/ldapcheck.c index 4e79a21..58369da 100644 --- a/ldapcheck.c +++ b/ldapcheck.c @@ -1,4 +1,4 @@ -/* $Id: ldapcheck.c,v 1.7 2009/04/09 03:27:20 manu Exp $ */ +/* $Id: ldapcheck.c,v 1.8 2009/06/08 23:40:06 manu Exp $ */ /* * Copyright (c) 2008 Emmanuel Dreyfus @@ -36,7 +36,7 @@ #ifdef HAVE_SYS_CDEFS_H #include #ifdef __RCSID -__RCSID("$Id: ldapcheck.c,v 1.7 2009/04/09 03:27:20 manu Exp $"); +__RCSID("$Id: ldapcheck.c,v 1.8 2009/06/08 23:40:06 manu Exp $"); #endif #endif #include @@ -71,7 +71,7 @@ struct ldapconf_entry { SIMPLEQ_HEAD(ldapconf_list, ldapconf_entry); LIST_HEAD(ldapcheck_list, ldapcheck_entry); -static void ldapcheck_conf_addone(char *); +static void ldapcheck_conf_addone(char *, char *, char *); static int ldapcheck_connect(struct ldapconf_entry *); static int ldapcheck_disconnect(struct ldapconf_entry *); static char *url_encode_percent(char *); @@ -81,6 +81,8 @@ static inline void ldapcheck_unlock(struct ldapconf_entry *); static struct ldapcheck_list ldapcheck_list; static struct ldapconf_list ldapconf_list; static struct timeval ldap_timeout; +static char *ldap_binddn; +static char *ldap_bindpw; int ldapcheck_gflags = 0; @@ -96,8 +98,10 @@ ldapcheck_init(void) { } static void -ldapcheck_conf_addone(url) +ldapcheck_conf_addone(url, binddn, bindpw) char *url; + char *binddn; + char *bindpw; { struct ldapconf_entry *lc; @@ -113,6 +117,16 @@ ldapcheck_conf_addone(url) lc->lc_dn = NULL; lc->lc_pwd = NULL; + if ((binddn != NULL) && (lc->lc_dn = strdup(binddn)) == NULL) { + mg_log(LOG_ERR, "strdup failed: %s", strerror(errno)); + exit(EX_OSERR); + } + + if ((bindpw != NULL) && (lc->lc_pwd = strdup(bindpw)) == NULL) { + mg_log(LOG_ERR, "strdup failed: %s", strerror(errno)); + exit(EX_OSERR); + } + lc->lc_ld = NULL; lc->lc_refcount = 0; if (pthread_mutex_init(&lc->lc_lock, NULL) != 0) { @@ -127,19 +141,24 @@ ldapcheck_conf_addone(url) } void -ldapcheck_conf_add(urls) +ldapcheck_conf_add(urls, binddn, bindpw) char *urls; + char *binddn; + char *bindpw; { char *lasts = NULL; char *p; char *sep = "\t "; - + if (conf.c_debug || conf.c_acldebug) { + mg_log(LOG_DEBUG, "bind options dn =\"%s\", pwd = \"%s\"\n", + binddn, bindpw); + } if ((p = strtok_r(urls, sep, &lasts)) != NULL) { - ldapcheck_conf_addone(p); + ldapcheck_conf_addone(p, binddn, bindpw); while (p) if ((p = strtok_r(NULL, sep, &lasts)) != NULL) - ldapcheck_conf_addone(p); + ldapcheck_conf_addone(p, binddn, bindpw); } return; @@ -264,10 +283,10 @@ ldapcheck_connect(lc) } error = ldap_simple_bind_s(lc->lc_ld, lc->lc_dn, lc->lc_pwd); - if (error != 0) { + if (error != LDAP_SUCCESS) { mg_log(LOG_WARNING, - "ldap_simple_bind_s failed for LDAP URL \"%s\": %s", - lc->lc_url, ldap_err2string(error)); + "ldap_simple_bind_s (%s/%s) failed for LDAP URL \"%s\": %s", + lc->lc_dn, lc->lc_pwd, lc->lc_url, ldap_err2string(error)); goto bad; } @@ -338,7 +357,7 @@ ldapcheck_validate(ad, stage, ap, priv) struct timeval tv1, tv2, tv3; LDAPMessage *res0 = NULL; LDAPMessage *res = NULL; - int error; + int error,pushed = 0 ; int retval = -1; int clearprop; @@ -430,13 +449,21 @@ ldapcheck_validate(ad, stage, ap, priv) vals = ldap_get_values(lc->lc_ld, res, attr); if (vals == NULL) { - mg_log(LOG_ERR, "ldap_get_values for URL \"%s\"" - "returns vals = NULL", url); - goto bad; + mg_log(LOG_ERR, "ldap_get_values for URL \"%s\" attr %s " + "returns vals = NULL", attr, url); + ldap_value_free(vals); + ldap_memfree(attr); + continue; } - for (val = vals; *val; val++) + for (val = vals; *val; val++) + { + acl_modify_by_prop(attr, *val, ap); prop_push(attr, *val, clearprop, priv); + pushed++; + if (conf.c_acldebug) mg_log(LOG_DEBUG, + "acl debug: pushed prop %s: %s", attr,*val); + } ldap_value_free(vals); ldap_memfree(attr); @@ -446,7 +473,7 @@ ldapcheck_validate(ad, stage, ap, priv) ber_free(ber, 0); } - retval = 0; + retval = pushed ? 1 : 0 ; bad: if (res0) ldap_msgfree(res0); diff --git a/ldapcheck.h b/ldapcheck.h index c6510e4..5014047 100644 --- a/ldapcheck.h +++ b/ldapcheck.h @@ -1,4 +1,4 @@ -/* $Id: ldapcheck.h,v 1.2 2009/04/03 04:15:27 manu Exp $ */ +/* $Id: ldapcheck.h,v 1.3 2009/06/08 23:40:06 manu Exp $ */ /* * Copyright (c) 2008 Emmanuel Dreyfus @@ -51,7 +51,7 @@ struct ldapcheck_entry { extern int ldapcheck_gflags; void ldapcheck_init(void); -void ldapcheck_conf_add(char *); +void ldapcheck_conf_add(char *, char *, char *); void ldapcheck_timeout_set(int); struct ldapcheck_entry *ldapcheck_def_add(char *, char *, int); struct ldapcheck_entry *ldapcheck_byname(char *); diff --git a/urlcheck.c b/urlcheck.c index b4aff7d..792a36e 100644 --- a/urlcheck.c +++ b/urlcheck.c @@ -1,4 +1,4 @@ -/* $Id: urlcheck.c,v 1.34 2008/09/26 17:00:51 manu Exp $ */ +/* $Id: urlcheck.c,v 1.35 2009/06/08 23:40:06 manu Exp $ */ /* * Copyright (c) 2006-2007 Emmanuel Dreyfus @@ -36,7 +36,7 @@ #ifdef HAVE_SYS_CDEFS_H #include #ifdef __RCSID -__RCSID("$Id: urlcheck.c,v 1.34 2008/09/26 17:00:51 manu Exp $"); +__RCSID("$Id: urlcheck.c,v 1.35 2009/06/08 23:40:06 manu Exp $"); #endif #endif @@ -111,7 +111,6 @@ static int find_boundary(struct mlfi_priv *, char *); static size_t curl_post(void *, size_t, size_t, void *); static int answer_parse(struct iovec *, struct acl_param *, int, struct mlfi_priv *); -static int answer_getline(char *, char *, struct acl_param *); static struct urlcheck_cnx *get_cnx(struct urlcheck_entry *); static void urlcheck_validate_pipe(struct urlcheck_data *, struct urlcheck_entry *, @@ -1076,7 +1075,7 @@ answer_parse(data, ap, flags, priv) buf[idx - 1] = '\0'; idx++; - if (answer_getline(linep, valp, ap) == -1) { + if (acl_modify_by_prop(linep, valp, ap) == -1) { if (!(flags & U_GETPROP)) mg_log(LOG_DEBUG, "ignoring unexpected \"%s\" => \"%s\"", @@ -1104,102 +1103,4 @@ answer_parse(data, ap, flags, priv) return retval; } -static int -answer_getline(key, value, ap) - char *key; - char *value; - struct acl_param *ap; -{ -#ifdef URLCHECK_DEBUG - if (conf.c_debug) - mg_log(LOG_DEBUG, "urlcheck got \"%s\" => \"%s\"", - key, value); -#endif - 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 - 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, "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; - - return -1; -out: - return 0; -} - #endif /* USE_CURL */