1 /* $OpenBSD: ruleset.c,v 1.29 2013/11/06 10:01:29 eric Exp $ */ 2 3 /* 4 * Copyright (c) 2009 Gilles Chehade <gilles@poolp.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/types.h> 20 #include <sys/queue.h> 21 #include <sys/tree.h> 22 #include <sys/socket.h> 23 24 #include <netinet/in.h> 25 26 #include <errno.h> 27 #include <event.h> 28 #include <imsg.h> 29 #include <stdio.h> 30 #include <string.h> 31 32 #include "smtpd.h" 33 #include "log.h" 34 35 36 static int ruleset_check_source(struct table *, 37 const struct sockaddr_storage *, int); 38 static int ruleset_check_mailaddr(struct table *, const struct mailaddr *); 39 40 struct rule * 41 ruleset_match(const struct envelope *evp) 42 { 43 const struct mailaddr *maddr = &evp->dest; 44 const struct sockaddr_storage *ss = &evp->ss; 45 struct rule *r; 46 int ret; 47 48 TAILQ_FOREACH(r, env->sc_rules, r_entry) { 49 50 if (r->r_tag[0] != '\0') { 51 ret = strcmp(r->r_tag, evp->tag); 52 if (ret != 0 && !r->r_nottag) 53 continue; 54 if (ret == 0 && r->r_nottag) 55 continue; 56 } 57 58 ret = ruleset_check_source(r->r_sources, ss, evp->flags); 59 if (ret == -1) { 60 errno = EAGAIN; 61 return (NULL); 62 } 63 if ((ret == 0 && !r->r_notsources) || (ret != 0 && r->r_notsources)) 64 continue; 65 66 if (r->r_senders) { 67 ret = ruleset_check_mailaddr(r->r_senders, &evp->sender); 68 if (ret == -1) { 69 errno = EAGAIN; 70 return (NULL); 71 } 72 if ((ret == 0 && !r->r_notsenders) || (ret != 0 && r->r_notsenders)) 73 continue; 74 } 75 76 if (r->r_recipients) { 77 ret = ruleset_check_mailaddr(r->r_recipients, &evp->dest); 78 if (ret == -1) { 79 errno = EAGAIN; 80 return (NULL); 81 } 82 if ((ret == 0 && !r->r_notrecipients) || (ret != 0 && r->r_notrecipients)) 83 continue; 84 } 85 86 ret = r->r_destination == NULL ? 1 : 87 table_lookup(r->r_destination, maddr->domain, K_DOMAIN, 88 NULL); 89 if (ret == -1) { 90 errno = EAGAIN; 91 return NULL; 92 } 93 if ((ret == 0 && !r->r_notdestination) || (ret != 0 && r->r_notdestination)) 94 continue; 95 96 if (r->r_desttype == DEST_VDOM && 97 (r->r_action == A_RELAY || r->r_action == A_RELAYVIA)) { 98 if (! aliases_virtual_check(r->r_mapping, 99 &evp->rcpt)) { 100 return NULL; 101 } 102 } 103 goto matched; 104 } 105 106 errno = 0; 107 log_trace(TRACE_RULES, "no rule matched"); 108 return (NULL); 109 110 matched: 111 log_trace(TRACE_RULES, "rule matched: %s", rule_to_text(r)); 112 return r; 113 } 114 115 static int 116 ruleset_check_source(struct table *table, const struct sockaddr_storage *ss, 117 int evpflags) 118 { 119 const char *key; 120 121 if (evpflags & (EF_AUTHENTICATED | EF_INTERNAL)) 122 key = "local"; 123 else 124 key = ss_to_text(ss); 125 switch (table_lookup(table, key, K_NETADDR, NULL)) { 126 case 1: 127 return 1; 128 case -1: 129 log_warnx("warn: failure to perform a table lookup on table %s", 130 table->t_name); 131 return -1; 132 default: 133 break; 134 } 135 136 return 0; 137 } 138 139 static int 140 ruleset_check_mailaddr(struct table *table, const struct mailaddr *maddr) 141 { 142 const char *key; 143 144 key = mailaddr_to_text(maddr); 145 if (key == NULL) 146 return -1; 147 148 switch (table_lookup(table, key, K_MAILADDR, NULL)) { 149 case 1: 150 return 1; 151 case -1: 152 log_warnx("warn: failure to perform a table lookup on table %s", 153 table->t_name); 154 return -1; 155 default: 156 break; 157 } 158 return 0; 159 } 160