# HG changeset patch # User meillo@marmaro.de # Date 1303977306 -7200 # Node ID 55b7bde95d375964a03d8a716dccbbd61dfbfedc # Parent d596ac8b5afb76e62cd3ac8f406fb90efe0f7e4f reworked allowed and denied addrs for routes The following refactorings had been made: - allowed_mail_locals + allowed_return_paths -> allowed_senders - not_allowed_mail_locals + not_allowed_return_paths -> denied_senders - allowed_rcpt_domains -> allowed_recipients - not_allowed_rcpt_domains -> denied_recipients The new options allow more consistent and more flexible matching. diff -r d596ac8b5afb -r 55b7bde95d37 admin/config-transition --- a/admin/config-transition Mon Apr 25 15:17:30 2011 +0200 +++ b/admin/config-transition Thu Apr 28 09:55:06 2011 +0200 @@ -67,7 +67,7 @@ " check["online_detect"] = "conf" SUBSEP "Removed in 0.3.2" SUBSEP "\ -Destilled to online_query. \ +Distilled to online_query. \ " check["online_file"] = "conf" SUBSEP "Removed in 0.3.2" SUBSEP "\ @@ -96,6 +96,34 @@ If pipe is given, pipe will be used, otherwise smtp will be used. \ " +check["(^|[ ])allowed_return_paths"] = "route" SUBSEP "Removed in 0.3.2" SUBSEP "\ +Replaced by 'allowed_senders'. \ +" + +check["not_allowed_return_paths"] = "route" SUBSEP "Removed in 0.3.2" SUBSEP "\ +Replaced by 'denied_senders'. \ +" + +check["(^|[ ])allowed_mail_locals"] = "route" SUBSEP "Removed in 0.3.2" SUBSEP "\ +Replaced by 'allowed_senders', if neither wildcards nor '@' is used. \ +" + +check["not_allowed_mail_locals"] = "route" SUBSEP "Removed in 0.3.2" SUBSEP "\ +Replaced by 'denied_senders', if neither wildcards nor '@' is used. \ +" + +check["(^|[ ])allowed_rcpt_domains"] = "route" SUBSEP "Removed in 0.3.2" SUBSEP "\ +Replaced by 'allowed_recipients', if the values are prepended with \ +'*@', because 'allowed_recipients' matches complete addresses not just \ +domains. \ +" + +check["not_allowed_rcpt_domains"] = "route" SUBSEP "Removed in 0.3.2" SUBSEP "\ +Replaced by 'denied_recipients', if the values are prepended with \ +'*@', because 'allowed_recipients' matches complete addresses not just \ +domains. \ +" + # get files # already covered by the get.* and online_gets.* options in the conf diff -r d596ac8b5afb -r 55b7bde95d37 examples/example.route --- a/examples/example.route Mon Apr 25 15:17:30 2011 +0200 +++ b/examples/example.route Thu Apr 28 09:55:06 2011 +0200 @@ -6,10 +6,10 @@ # # users that can send mail over this connection: -# this is a list of the local parts of the original return addresses, as they are +# this is a list of the envelope sender addresses, as they are # configured with your mail client. If not set, anybody may send. -allowed_mail_locals = "okurth" +allowed_senders = "okurth" # local_hosts and local_nets will be checked before this. # cpwright.com uses the dialup up list of dul.maps.vix.com, @@ -20,7 +20,7 @@ # You will find this necessary only if you send mail directly # (if mail_host is not set below) -not_allowed_rcpt_domains = "cpwright.com" +denied_recipients = "*@cpwright.com" # # settings: diff -r d596ac8b5afb -r 55b7bde95d37 examples/openssl.route --- a/examples/openssl.route Mon Apr 25 15:17:30 2011 +0200 +++ b/examples/openssl.route Thu Apr 28 09:55:06 2011 +0200 @@ -14,8 +14,8 @@ #wrapper="/usr/bin/openssl s_client -quiet -connect mail.gmx.net:465 2>/dev/null" -# which addresses are allowed through this route? -allowed_return_paths = "*@gmx.de;*@gmx.net" +# which sender addresses are allowed for this route? +allowed_senders = "*@gmx.de;*@gmx.net" # the authentication method #auth_name = "cram-md5" diff -r d596ac8b5afb -r 55b7bde95d37 man/masqmail.route.5 --- a/man/masqmail.route.5 Mon Apr 25 15:17:30 2011 +0200 +++ b/man/masqmail.route.5 Thu Apr 28 09:55:06 2011 +0200 @@ -17,62 +17,65 @@ .SH ROUTE CONDITIONS .TP -\fBallowed_mail_locals\fR = \fIlist\fR +\fBallowed_senders\fR = \fIlist\fR -This is a semicolon `;' separated list of local parts of envelope -senders (= mail from = return path) which will be allowed -to send mail through this connection. -If unset and \fBnot_allowed_mail_locals\fR is also unset, all users are allowed. +This is a semicolon `;' separated list of envelope sender addresses. +Messages which have one of these addresses as the return path (= mail +from) are allowed to use this route +(if not also in \fBdenied_senders\fR). + +Glob patterns containing `?' and `*' can be used. +The special item "<>" matches the null sender address +(eg. failure notices or delivery notifications). +If the pattern doesn't contain an `@', it is seen as a pattern for the +local part only. + +Example: \fImeillo;*@*example.org;web*@example.com\fP + +(``meillo'' equals ``meillo@*'', i.e. the local part.) .TP -\fBnot_allowed_mail_locals\fR = \fIlist\fR +\fBdenied_senders\fR = \fIlist\fR -This is a semicolon `;' separated list of local parts of envelope -senders (= mail from = return path) which will be not allowed -to send mail through this connection. -Local parts in this list will not be allowed to use this route even if they -are part of \fBallowed_mail_locals\fR (see above). +This is a semicolon `;' separated list of envelope sender addresses. +Messages which have one of these addresses as the return path (= +mail from) will not +be sent using this route (even if also in \fBallowed_senders\fR). + +Glob patterns containing `?' and `*' can be used. +The special item "<>" matches the null sender address +(eg. failure notices or delivery notifications). +If the pattern doesn't contain an `@', it is seen as a pattern for the +local part only. + +Example: (see \fIallowed_senders\fP) .TP -\fBallowed_return_paths\fR = \fIlist\fR +\fBallowed_recipients\fR = \fIlist\fR -This is a semicolon `;' separated list of addresses. -Messages which have one of these addresses as the return path (= -envelope sender = mail from) will be used using this route -(if not also in \fBnot_allowed_return_paths\fR or an item in \fBnot_allowed_mail_locals\fR matches). +A list of envelope recipient addresses where mail can be sent to using +this route. +This is for example useful if you use this route configuration when connected to another LAN via ppp. +Glob patterns containing `?' and `*' can be used. -Patterns containing `?' and `*' can be used. -The special item "<>" matches the null sender address (eg. failure notices or delivery notifications). +Example: \fI*@example.org;*@*foo.bar\fP + +(See also examples for \fIallowed_senders\fP) .TP -\fBnot_allowed_return_paths\fR = \fIlist\fR +\fBdenied_recipients\fR = \fIlist\fR -This is a semicolon `;' separated list of addresses. -Messages which have one of these addresses as the return path (= -envelope sender = mail from) will not -be used using this route (even if also in \fBallowed_return_paths\fR -or an item in \fBallowed_mail_locals\fR matches). - -Patterns containing `?' and `*' can be used. -The special item "<>" matches the null sender address (eg. failure notices or delivery notifications). - -.TP -\fBallowed_rcpt_domains\fR = \fIlist\fR - -A list of recipient domains (of envelope recipients) where mail will be sent to. -This is for example useful if you use this route configuration when connected to another LAN via ppp. -Patterns containing `?' and `*' can be used. - -.TP -\fBnot_allowed_rcpt_domains\fR = \fIlist\fR - -A list of recipient domains (of envelope recipients) where mail will not be sent to. +A list of envelope recipient addresses where mail will not be sent to +using this route. This is for example useful if you send mail directly (\fBmail_host\fR is not set) and you know of hosts that will not accept mail from you because they use a dialup list (eg. \fBhttp://maps.vix.com/dul/\fR). -If any domain matches both \fBallowed_rcpt_domains\fR and \fBnot_allowed_rcpt_domains\fR, -mail will not be sent to this domain. -Patterns containing `?' and `*' can be used. +\fBdenied_recipients\fR overrules \fBallowed_recipients\fR. +Glob patterns containing `?' and `*' can be used. + +Example: \fI*@spamblocker.example.org\fP + +(See also examples for \fIallowed_senders\fP) .TP \fBlast_route\fR = \fIboolean\fR @@ -80,8 +83,9 @@ If this is set, a mail which would have been delivered using this route, but has failed temporarily, will not be tried to be delivered using the next route. -If you have set up a special route with filters using the lists `allowed_rcpt_domains', -`allowed_return_paths', and `allowed_mail_locals' or their complements (not_), +If you have set up a special route with filters using the lists +`allowed_recipients' and `allowed_senders' or their complements +(denied_), and the mail passing these rules should be delivered using this route only, you should set this to `true'. Otherwise the mail would be passed to the next route (if any), diff -r d596ac8b5afb -r 55b7bde95d37 src/address.c --- a/src/address.c Mon Apr 25 15:17:30 2011 +0200 +++ b/src/address.c Thu Apr 28 09:55:06 2011 +0200 @@ -17,7 +17,6 @@ */ #include "masqmail.h" -#include address* create_address(gchar * path, gboolean is_rfc821) @@ -186,15 +185,3 @@ } return buffer; } - -gint -addr_match(address * addr1, address * addr2) -{ - int res; - - if ((res = fnmatch(addr1->local_part, addr2->local_part, 0)) == 0) { - if ((res = fnmatch(addr1->domain, addr2->domain, FNM_CASEFOLD)) == 0) - return 0; - } - return res; -} diff -r d596ac8b5afb -r 55b7bde95d37 src/conf.c --- a/src/conf.c Mon Apr 25 15:17:30 2011 +0200 +++ b/src/conf.c Thu Apr 28 09:55:06 2011 +0200 @@ -142,8 +142,14 @@ return list; } +/* Split the addrs at '@' into local_part and domain. Without an '@' + everything is local_part. Create address structs, which are put + into a list and returned. + This funktion is used for lists of addrs containing globbing chars (* and ?). + We don't need valid RFC821 addresses here, just patterns to match against. +*/ static GList* -parse_address_list(gchar * line, gboolean read_file) +parse_address_glob_list(gchar * line, gboolean read_file) { GList *plain_list = parse_list(line, read_file); GList *node; @@ -151,13 +157,32 @@ foreach(plain_list, node) { gchar *item = (gchar *) (node->data); - address *addr = create_address(item, TRUE); - if (addr) - list = g_list_append(list, addr); + char* at; + char* p; + address *addr = calloc(1, sizeof(address)); + + for (p=item+strlen(item)-1; isspace(*p) || *p=='>'; p--) { + *p = '\0'; + } + for (p=item; isspace(*p) || *p=='<'; p++) { + } + + addr->address = strdup(p); + at = strrchr(p, '@'); + if (at) { + *at = '\0'; + addr->local_part = strdup(p); + addr->domain = strdup(at+1); + } else { + addr->local_part = strdup(p); + addr->domain = ""; + } + list = g_list_append(list, addr); + DEBUG(6) debugf("parse_address_glob_list: read pattern `%s' `%s'\n", + addr->local_part, addr->domain); g_free(item); } g_list_free(plain_list); - return list; } @@ -648,18 +673,16 @@ route->instant_helo = parse_boolean(rval); else if (strcmp(lval, "do_pipelining") == 0) route->do_pipelining = parse_boolean(rval); - else if (strcmp(lval, "allowed_return_paths") == 0) - route->allowed_return_paths = parse_address_list(rval, TRUE); - else if (strcmp(lval, "allowed_mail_locals") == 0) - route->allowed_mail_locals = parse_list(rval, TRUE); - else if (strcmp(lval, "not_allowed_return_paths") == 0) - route->not_allowed_return_paths = parse_address_list(rval, TRUE); - else if (strcmp(lval, "not_allowed_mail_locals") == 0) - route->not_allowed_mail_locals = parse_list(rval, TRUE); - else if (strcmp(lval, "allowed_rcpt_domains") == 0) - route->allowed_rcpt_domains = parse_list(rval, TRUE); - else if (strcmp(lval, "not_allowed_rcpt_domains") == 0) - route->not_allowed_rcpt_domains = parse_list(rval, TRUE); + + else if (strcmp(lval, "allowed_senders") == 0) + route->allowed_senders = parse_address_glob_list(rval, TRUE); + else if (strcmp(lval, "denied_senders") == 0) + route->denied_senders = parse_address_glob_list(rval, TRUE); + else if (strcmp(lval, "allowed_recipients") == 0) + route->allowed_recipients = parse_address_glob_list(rval, TRUE); + else if (strcmp(lval, "denied_recipients") == 0) + route->denied_recipients = parse_address_glob_list(rval, TRUE); + else if (strcmp(lval, "set_h_from_domain") == 0) route->set_h_from_domain = g_strdup(rval); else if (strcmp(lval, "set_h_reply_to_domain") == 0) @@ -808,10 +831,10 @@ g_free(r->wrapper); if (r->helo_name) g_free(r->helo_name); - _g_list_free_all(r->allowed_mail_locals); - _g_list_free_all(r->not_allowed_mail_locals); - _g_list_free_all(r->allowed_rcpt_domains); - _g_list_free_all(r->not_allowed_rcpt_domains); + _g_list_free_all(r->allowed_senders); + _g_list_free_all(r->denied_senders); + _g_list_free_all(r->allowed_recipients); + _g_list_free_all(r->denied_recipients); if (r->set_h_from_domain) g_free(r->set_h_from_domain); if (r->set_h_reply_to_domain) diff -r d596ac8b5afb -r 55b7bde95d37 src/deliver.c --- a/src/deliver.c Mon Apr 25 15:17:30 2011 +0200 +++ b/src/deliver.c Thu Apr 28 09:55:06 2011 +0200 @@ -560,21 +560,21 @@ continue; } - /* filter by allowed return paths (= envelope sender) */ - if (!route_is_allowed_mail_local(route, msgout->msg->return_path) - || !route_is_allowed_return_path(route, msgout->msg->return_path)) { + /* filter by allowed envelope sender */ + if (!route_sender_is_allowed(route, msgout->msg->return_path)) { destroy_msg_out(msgout_cloned); continue; } - /* filter by allowed rcpt addrs (= envelope rcpts) */ - GList *rcpt_list_allowed = NULL, *rcpt_list_notallowed = NULL; - msg_rcptlist_route(route, msgout_cloned->rcpt_list, &rcpt_list_allowed, &rcpt_list_notallowed); - + /* filter by allowed envelope rcpts */ + GList* rcpt_list_allowed = NULL; + GList* rcpt_list_notallowed = NULL; + route_split_rcpts(route, msgout_cloned->rcpt_list, &rcpt_list_allowed, &rcpt_list_notallowed); if (!rcpt_list_allowed) { destroy_msg_out(msgout_cloned); continue; } + logwrite(LOG_NOTICE, "%s using '%s'\n", msgout->msg->uid, route->name); g_list_free(msgout_cloned->rcpt_list); diff -r d596ac8b5afb -r 55b7bde95d37 src/masqmail.h --- a/src/masqmail.h Mon Apr 25 15:17:30 2011 +0200 +++ b/src/masqmail.h Thu Apr 28 09:55:06 2011 +0200 @@ -84,12 +84,10 @@ gboolean is_local_net; gboolean last_route; - GList *allowed_return_paths; - GList *not_allowed_return_paths; - GList *allowed_mail_locals; - GList *not_allowed_mail_locals; - GList *allowed_rcpt_domains; - GList *not_allowed_rcpt_domains; + GList *allowed_senders; + GList *denied_senders; + GList *allowed_recipients; + GList *denied_recipients; interface *mail_host; gchar *wrapper; @@ -390,7 +388,6 @@ gboolean addr_is_delivered_children(address * addr); gboolean addr_is_finished_children(address * addr); gchar *addr_string(address * addr); -gint addr_match(address * addr1, address * addr2); /* accept.c */ accept_error accept_message(FILE * in, message * msg, guint flags); @@ -493,9 +490,8 @@ gboolean route_strip_msgout(connect_route * route, msg_out * msgout); msg_out *route_prepare_msgout(connect_route * route, msg_out * msgout); GList *route_msgout_list(connect_route * route, GList * msgout_list); -gboolean route_is_allowed_return_path(connect_route * route, address * ret_path); -gboolean route_is_allowed_mail_local(connect_route * route, address * ret_path); -void msg_rcptlist_route(connect_route * route, GList * rcpt_list, GList ** p_rcpt_list, GList ** p_non_rcpt_list); +gboolean route_sender_is_allowed(connect_route * route, address * ret_path); +void route_split_rcpts(connect_route * route, GList * rcpt_list, GList ** p_rcpt_list, GList ** p_non_rcpt_list); /* tables.c */ table_pair *create_pair(gchar * key, gpointer value); diff -r d596ac8b5afb -r 55b7bde95d37 src/route.c --- a/src/route.c Mon Apr 25 15:17:30 2011 +0200 +++ b/src/route.c Thu Apr 28 09:55:06 2011 +0200 @@ -238,21 +238,34 @@ } static gint -_g_list_addrcmp(gconstpointer a, gconstpointer b) +_g_list_addrcmp(gconstpointer pattern, gconstpointer addr) { - return addr_match((address *) a, (address *) b); + int res; + address* patternaddr = (address*) pattern; + address* stringaddr = (address*) addr; + + DEBUG(6) debugf("_g_list_addrcmp: pattern `%s' `%s' on string `%s' `%s'\n", + patternaddr->local_part, patternaddr->domain, + stringaddr->local_part, stringaddr->domain); + /* TODO: check if we should match here dependent on caseless_matching */ + res = fnmatch(patternaddr->local_part, stringaddr->local_part, 0); + if (res != 0) { + DEBUG(6) debugf("_g_list_addrcmp: ... failed on local_part\n"); + return res; + } + res = fnmatch(patternaddr->domain, stringaddr->domain, FNM_CASEFOLD); + DEBUG(6) debugf("_g_list_addrcmp: ... %s\n", (res==0) ? "matched" : "failed on domain"); + return res; } gboolean -route_is_allowed_return_path(connect_route * route, address * ret_path) +route_sender_is_allowed(connect_route * route, address * ret_path) { - if (route->not_allowed_return_paths != NULL) { - if (g_list_find_custom(route->not_allowed_return_paths, ret_path, _g_list_addrcmp) != NULL) { - return FALSE; - } + if (route->denied_senders && g_list_find_custom(route->denied_senders, ret_path, _g_list_addrcmp)) { + return FALSE; } - if (route->allowed_return_paths != NULL) { - if (g_list_find_custom(route->allowed_return_paths, ret_path, _g_list_addrcmp) != NULL) { + if (route->allowed_senders) { + if (g_list_find_custom(route->allowed_senders, ret_path, _g_list_addrcmp)) { return TRUE; } else { return FALSE; @@ -261,49 +274,25 @@ return TRUE; } -static gint -_g_list_strcmp(gconstpointer a, gconstpointer b) -{ - return (gint) strcmp(a, b); -} - -gboolean -route_is_allowed_mail_local(connect_route * route, address * ret_path) -{ - gchar *loc_part = ret_path->local_part; - - if (route->not_allowed_mail_locals != NULL) { - if (g_list_find_custom(route->not_allowed_mail_locals, loc_part, _g_list_strcmp) != NULL) - return FALSE; - } - if (route->allowed_mail_locals != NULL) { - if (g_list_find_custom(route->allowed_mail_locals, loc_part, _g_list_strcmp) != NULL) - return TRUE; - else - return FALSE; - } - return TRUE; -} - /* Make lists of matching/not matching rcpts. Local domains are NOT regared here, these should be sorted out previously */ void -msg_rcptlist_route(connect_route * route, GList * rcpt_list, GList ** p_rcpt_list, GList ** p_non_rcpt_list) +route_split_rcpts(connect_route * route, GList * rcpt_list, GList ** p_rcpt_list, GList ** p_non_rcpt_list) { GList *tmp_list = NULL; /* sort out those domains that can be sent over this connection: */ - if (route->allowed_rcpt_domains) { - DEBUG(5) debugf("testing for route->allowed_rcpt_domains\n"); - split_rcpts(rcpt_list, route->allowed_rcpt_domains, NULL, &tmp_list, p_non_rcpt_list); + if (route->allowed_recipients) { + DEBUG(5) debugf("testing for route->allowed_recipients\n"); + split_rcpts(rcpt_list, route->allowed_recipients, NULL, &tmp_list, p_non_rcpt_list); } else { - DEBUG(5) debugf("route->allowed_rcpt_domains == NULL\n"); + DEBUG(5) debugf("route->allowed_recipients == NULL\n"); tmp_list = g_list_copy(rcpt_list); } /* sort out those domains that cannot be sent over this connection: */ - split_rcpts(tmp_list, route->not_allowed_rcpt_domains, NULL, p_non_rcpt_list, p_rcpt_list); + split_rcpts(tmp_list, route->denied_recipients, NULL, p_non_rcpt_list, p_rcpt_list); g_list_free(tmp_list); }