From 88e1ffcde1bfd289fe67de1aea6cbd9c6cd0ca24 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Julio=20S=C3=A1nchez=20Fern=C3=A1ndez?= Date: Thu, 23 Mar 2000 16:19:01 +0000 Subject: [PATCH] The approach used was not powerfull enough to deal with things like nested groups or the laser mail routing draft. Mostly, this is because a flag saying the attribute type is 'final' is not flexible enough. The old 'final' flag is gone and replaced by a priority level. Change 'forward' to 'route' to be consistent with the laser wording. Add new 'domain' spec in the configuration file to describe what are the local domains so that we do not loop when doing the laser thing. We were escaping asterisks in filters. This seems incorrect. Removed. --- clients/mail500/main.c | 105 ++++++++++++++++++++++++++++++++++------- 1 file changed, 87 insertions(+), 18 deletions(-) diff --git a/clients/mail500/main.c b/clients/mail500/main.c index 56d016ced7..d3e24b06c9 100644 --- a/clients/mail500/main.c +++ b/clients/mail500/main.c @@ -128,7 +128,7 @@ char *sendmailargs[] = { MAIL500_SENDMAIL, "-oMrLDAP", "-odi", "-oi", "-f", NULL typedef struct attr_semantics { char *as_name; int as_m_valued; /* Is multivalued? */ - int as_final; /* If true, no further expansion is tried. */ + int as_priority; /* Priority level of this attribut type */ int as_syntax; /* How to interpret values */ int as_m_entries; /* Can resolve to several entries? */ int as_kind; /* Recipient, sender, etc. */ @@ -149,11 +149,13 @@ typedef struct attr_semantics { #define AS_KIND_ERRORS 2 /* For ErrorsTo and similar */ #define AS_KIND_REQUEST 3 #define AS_KIND_OWNER 4 -#define AS_KIND_FORWARD_TO_HOST 5 /* Expand at some other host */ +#define AS_KIND_ROUTE_TO_HOST 5 /* Expand at some other host */ #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 */ AttrSemantics **attr_semantics = NULL; +int current_priority = 0; typedef struct subst { char sub_char; @@ -162,6 +164,7 @@ typedef struct subst { char **groupclasses = NULL; char **def_attr = NULL; +char **mydomains = NULL; /* FQDNs not to route elsewhere */ static void load_config( char *filespec ); static void split_address( char *address, char **localpart, char **domainpart); @@ -519,6 +522,7 @@ add_attr_semantics( char *s ) AttrSemantics *as; as = calloc( 1, sizeof( AttrSemantics ) ); + as->as_priority = current_priority; p = s; while ( isspace ( *p ) ) p++; @@ -540,8 +544,6 @@ add_attr_semantics( char *s ) as->as_m_valued = 1; } else if ( !strcasecmp( p, "multiple-entries" ) ) { as->as_m_entries = 1; - } else if ( !strcasecmp( p, "final" ) ) { - as->as_final = 1; } else if ( !strcasecmp( p, "local-native-mailbox" ) ) { as->as_syntax = AS_SYNTAX_NATIVE_MB; } else if ( !strcasecmp( p, "rfc822" ) ) { @@ -575,8 +577,10 @@ add_attr_semantics( char *s ) } } else if ( !strcasecmp( p, "host" ) ) { as->as_kind = AS_SYNTAX_HOST; - } else if ( !strcasecmp( p, "forward-to-host" ) ) { - as->as_kind = AS_KIND_FORWARD_TO_HOST; + } 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, "recipient" ) ) { as->as_kind = AS_KIND_RECIPIENT; } else if ( !strcasecmp( p, "errors" ) ) { @@ -655,6 +659,12 @@ load_config( char *filespec ) } else if ( !strncmp(line, "group-classes", p-line) ) { p += strspn(p, " \t"); add_single_to( &groupclasses, p ); + } else if ( !strncmp(line, "priority", p-line) ) { + p += strspn(p, " \t"); + current_priority = atoi(p); + } else if ( !strncmp(line, "domain", p-line) ) { + p += strspn(p, " \t"); + add_single_to( &mydomains, p ); } else { syslog( LOG_ALERT, "Unparseable config definition at line %d", @@ -812,7 +822,6 @@ search_ldap_url( char *p, *s, *d; int i; char filter[1024]; - char realfilter[1024]; LDAPMessage *e, *res; int rc; char **attrlist; @@ -911,14 +920,6 @@ search_ldap_url( filter[ sizeof( filter ) - 1 ] = '\0'; } - for ( s = filter, d = realfilter; *s; s++, d++ ) { - if ( *s == '*' ) { - *d++ = '\\'; - } - *d = *s; - } - *d = '\0'; - if ( ludp->lud_attrs ) { attrlist = ludp->lud_attrs; } else { @@ -927,7 +928,7 @@ search_ldap_url( res = NULL; /* TBC: we don't read the host, dammit */ rc = ldap_search_st( ld, ludp->lud_dn, ludp->lud_scope, - realfilter, attrlist, 0, + filter, attrlist, 0, &timeout, &res ); /* some other trouble - try again later */ @@ -1075,6 +1076,23 @@ url_list_search( return( resolved ); } +static int +is_my_domain( + char * domain +) +{ + char **d; + + if ( d == NULL ) + return 0; + for ( d = mydomains; *d; d++ ) { + if ( !strcmp(*d,domain) ) { + return 1; + } + } + return 0; +} + /* * The entry engine processes an entry. Normally, each entry will resolve * to one or more values that will be added to the 'to' argument. This @@ -1106,11 +1124,22 @@ entry_engine( char buf[1024]; char *localpart, *domainpart; Subst substs[2]; + int cur_priority = 0; + char *route_to_host = NULL; + char *route_to_address = NULL; + char *nvals[2]; for ( i=0; attr_semantics[i] != NULL; i++ ) { AttrSemantics *as = attr_semantics[i]; int nent; + if ( as->as_priority < cur_priority ) { + /* + * We already got higher priority information, + * so no further work to do, ignore the rest. + */ + break; + } vals = ldap_get_values( ld, e, as->as_name ); if ( !vals || vals[0] == NULL ) { continue; @@ -1122,6 +1151,7 @@ entry_engine( } switch ( as->as_kind ) { case AS_KIND_RECIPIENT: + cur_priority = as->as_priority; if ( ! ( type & ( USER | GROUP_MEMBERS ) ) ) break; switch ( as->as_syntax ) { @@ -1188,6 +1218,7 @@ entry_engine( break; case AS_KIND_ERRORS: + cur_priority = as->as_priority; /* This is a group with special processing */ if ( type & GROUP_ERRORS ) { switch (as->as_kind) { @@ -1225,6 +1256,7 @@ entry_engine( break; case AS_KIND_REQUEST: + cur_priority = as->as_priority; /* This is a group with special processing */ if ( type & GROUP_REQUEST ) { add_to( current_to, current_nto, vals ); @@ -1233,6 +1265,7 @@ entry_engine( break; case AS_KIND_OWNER: + cur_priority = as->as_priority; /* This is a group with special processing */ if ( type & GROUP_REQUEST ) { add_to( current_to, current_nto, vals ); @@ -1240,16 +1273,52 @@ entry_engine( } break; + case AS_KIND_ROUTE_TO_HOST: + if ( !is_my_domain( vals[0] ) ) { + cur_priority = as->as_priority; + 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] ); + } + break; + default: syslog( LOG_ALERT, "Invalid kind %d", as->as_kind ); /* Error, TBC */ } ldap_value_free( vals ); - if ( as->as_final ) { - return( resolved ); + } + if ( route_to_host ) { + char *p; + if ( !route_to_address ) { + route_to_address = strdup( address ); + } + /* This makes use of the percent hack, but there's no choice */ + p = strchr( route_to_address, '@' ); + if ( p ) { + *p = '%'; } + sprintf( buf, "%s@%s", route_to_address, route_to_host ); + nvals[0] = buf; + nvals[1] = NULL; + add_to( current_to, current_nto, nvals ); + resolved = 1; + free( route_to_host ); + free( route_to_address ); + } else if ( route_to_address ) { + nvals[0] = route_to_address; + nvals[1] = NULL; + add_to( current_to, current_nto, nvals ); + resolved = 1; + free( route_to_address ); } + return( resolved ); } -- 2.39.5