From 4cf241aa69f4e03dedbac1fc0f51e295ee85ed02 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Julio=20S=C3=A1nchez=20Fern=C3=A1ndez?= Date: Wed, 5 Apr 2000 19:15:33 +0000 Subject: [PATCH] Added support for doing routing at the MTA, that is the right thing anyway. A new syntax is defined, "present", that indicates that values of an attribute type are not used, only presence is significant. To do routing at the MTA, define both mailHost and mailRoutingAddress with syntax "present". Otherwise, use "host" and "rfc822" and mail500 will try to do routing by itself, if possible. Read the comments in the code for the ugly details. Added a new configuration line "own-address" that describes the FQDN of our host to compare with mailHost. The line can be repeated. --- clients/mail500/main.c | 89 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 81 insertions(+), 8 deletions(-) diff --git a/clients/mail500/main.c b/clients/mail500/main.c index d3e24b06c9..6a5c25bde9 100644 --- a/clients/mail500/main.c +++ b/clients/mail500/main.c @@ -82,6 +82,7 @@ typedef struct errs { #define E_NOMEMBERS 10 #define E_NOOWNER 11 #define E_GROUPUNKNOWN 12 +#define E_NOOWNADDRESS 13 char *e_addr; union e_union_u { char *e_u_loop; @@ -135,7 +136,7 @@ typedef struct attr_semantics { char *as_param; /* Extra info for filters and things alike */ } AttrSemantics; -#define AS_SYNTAX_UNKNOWN 0 /* Unqualified mailbox name */ +#define AS_SYNTAX_UNKNOWN 0 #define AS_SYNTAX_NATIVE_MB 1 /* Unqualified mailbox name */ #define AS_SYNTAX_RFC822 2 /* RFC822 mail address */ #define AS_SYNTAX_HOST 3 @@ -143,6 +144,8 @@ typedef struct attr_semantics { #define AS_SYNTAX_RFC822_EXT 5 #define AS_SYNTAX_URL 6 /* mailto: or ldap: URL */ #define AS_SYNTAX_BOOL_FILTER 7 /* For joinable, filter in as_param */ +#define AS_SYNTAX_PRESENT 8 /* Value irrelevant, only presence is + * considered. */ #define AS_KIND_UNKNOWN 0 #define AS_KIND_RECIPIENT 1 @@ -153,6 +156,7 @@ typedef struct attr_semantics { #define AS_KIND_ALLOWED_SENDER 6 /* Can send to group */ #define AS_KIND_MODERATOR 7 #define AS_KIND_ROUTE_TO_ADDR 8 /* Rewrite recipient address as */ +#define AS_KIND_OWN_ADDR 9 /* RFC822 name of this entry */ AttrSemantics **attr_semantics = NULL; int current_priority = 0; @@ -577,10 +581,14 @@ add_attr_semantics( char *s ) } } else if ( !strcasecmp( p, "host" ) ) { as->as_kind = AS_SYNTAX_HOST; + } else if ( !strcasecmp( p, "present" ) ) { + as->as_kind = AS_SYNTAX_PRESENT; } else if ( !strcasecmp( p, "route-to-host" ) ) { as->as_kind = AS_KIND_ROUTE_TO_HOST; } else if ( !strcasecmp( p, "route-to-address" ) ) { as->as_kind = AS_KIND_ROUTE_TO_ADDR; + } else if ( !strcasecmp( p, "own-address" ) ) { + as->as_kind = AS_KIND_OWN_ADDR; } else if ( !strcasecmp( p, "recipient" ) ) { as->as_kind = AS_KIND_RECIPIENT; } else if ( !strcasecmp( p, "errors" ) ) { @@ -1076,6 +1084,10 @@ url_list_search( return( resolved ); } +/* + * We should probably take MX records into account to cover all bases, + * but really, routing belongs in the MTA. + */ static int is_my_domain( char * domain @@ -1086,7 +1098,7 @@ is_my_domain( if ( d == NULL ) return 0; for ( d = mydomains; *d; d++ ) { - if ( !strcmp(*d,domain) ) { + if ( !strcasecmp(*d,domain) ) { return 1; } } @@ -1127,11 +1139,15 @@ entry_engine( int cur_priority = 0; char *route_to_host = NULL; char *route_to_address = NULL; + int needs_mta_routing = 0; + char **own_addresses = NULL; + int own_addresses_total = 0; char *nvals[2]; for ( i=0; attr_semantics[i] != NULL; i++ ) { AttrSemantics *as = attr_semantics[i]; int nent; + int j; if ( as->as_priority < cur_priority ) { /* @@ -1276,15 +1292,30 @@ entry_engine( case AS_KIND_ROUTE_TO_HOST: if ( !is_my_domain( vals[0] ) ) { cur_priority = as->as_priority; - route_to_host = strdup( vals[0] ); + if ( as->as_syntax == AS_SYNTAX_PRESENT ) { + needs_mta_routing = 1; + } else { + route_to_host = strdup( vals[0] ); + } } break; case AS_KIND_ROUTE_TO_ADDR: - if ( strcmp( vals[0], address ) ) { - cur_priority = as->as_priority; - route_to_address = strdup( vals[0] ); + for ( j=0; jas_priority; + if ( as->as_syntax == AS_SYNTAX_PRESENT ) { + needs_mta_routing = 1; + } else { + route_to_address = strdup( vals[0] ); + } + } + break; } + + case AS_KIND_OWN_ADDR: + add_to( &own_addresses, &own_addresses_total, vals ); + cur_priority = as->as_priority; break; default: @@ -1294,10 +1325,44 @@ entry_engine( } ldap_value_free( vals ); } - if ( route_to_host ) { + /* + * Now check if we are dealing with mail routing. We support + * two modes. + * + * The first mode and by far the most robust method is doing + * routing at the MTA. In this case, we just checked if the + * routing attributes were present and did not seem like + * pointing to ourselves. The only thing we have to do here + * is adding to the recipient list any of the RFC822 addresses + * of this entry. That means we needed to retrieve them from + * the entry itself because we might have arrived here through + * some directory search. The address received as argument is + * not the address of the entry we are processing, but rather + * the RFC822 address we are expanding now. Unfortunately, + * this requires an MTA that understands LDAP routing. + * Sendmail 8.10.0 does, if compiled properly. + * + * The second method, that is most emphatically not recommended + * is routing in mail500. This is going to require using the + * percent hack. Moreover, this may occasionally loop. + */ + if ( needs_mta_routing ) { + if ( !own_addresses ) { + add_error( err, nerr, E_NOOWNADDRESS, address, e ); + return( 0 ); + } + nvals[0] = own_addresses[0]; /* Anyone will do */ + nvals[1] = NULL; + add_to( current_to, current_nto, nvals ); + resolved = 1; + } else if ( route_to_host ) { char *p; if ( !route_to_address ) { - route_to_address = strdup( address ); + if ( !own_addresses ) { + add_error( err, nerr, E_NOOWNADDRESS, address, e ); + return( 0 ); + } + route_to_address = strdup( own_addresses[0] ); } /* This makes use of the percent hack, but there's no choice */ p = strchr( route_to_address, '@' ); @@ -1318,6 +1383,9 @@ entry_engine( resolved = 1; free( route_to_address ); } + if ( own_addresses ) { + ldap_value_free( own_addresses ); + } return( resolved ); } @@ -1626,6 +1694,11 @@ send_errors( Error *err, int nerr ) err[i].e_addr ); break; + case E_NOOWNADDRESS: + fprintf( fp, "%s: Not enough information to perform required routing\n", + err[i].e_addr ); + break; + default: syslog( LOG_ALERT, "unknown error %d", err[i].e_code ); unbind_and_exit( EX_TEMPFAIL ); -- 2.39.5