1 /* $NetBSD: deliver_pass.c,v 1.5 2026/05/09 18:49:16 christos Exp $ */ 2 3 /*++ 4 /* NAME 5 /* deliver_pass 3 6 /* SUMMARY 7 /* deliver request pass_through 8 /* SYNOPSIS 9 /* #include <deliver_request.h> 10 /* 11 /* int deliver_pass(class, service, request, recipient) 12 /* const char *class; 13 /* const char *service; 14 /* DELIVER_REQUEST *request; 15 /* RECIPIENT *recipient; 16 /* 17 /* int deliver_pass_all(class, service, request) 18 /* const char *class; 19 /* const char *service; 20 /* DELIVER_REQUEST *request; 21 /* DESCRIPTION 22 /* This module implements the client side of the `queue manager 23 /* to delivery agent' protocol, passing one recipient on from 24 /* one delivery agent to another. 25 /* 26 /* deliver_pass() delegates delivery of the named recipient. 27 /* 28 /* deliver_pass_all() delegates an entire delivery request. 29 /* 30 /* Arguments: 31 /* .IP class 32 /* Destination delivery agent service class 33 /* .IP service 34 /* String of the form \fItransport\fR:\fInexthop\fR. Either transport 35 /* or nexthop are optional. For details see the transport map manual page. 36 /* .IP request 37 /* Delivery request with queue file information. 38 /* .IP recipient 39 /* Recipient information. See recipient_list(3). 40 /* DIAGNOSTICS 41 /* LICENSE 42 /* .ad 43 /* .fi 44 /* The Secure Mailer license must be distributed with this software. 45 /* BUGS 46 /* One recipient at a time; this is OK for mailbox deliveries. 47 /* 48 /* Hop status information cannot be passed back. 49 /* AUTHOR(S) 50 /* Wietse Venema 51 /* IBM T.J. Watson Research 52 /* P.O. Box 704 53 /* Yorktown Heights, NY 10598, USA 54 /* 55 /* Wietse Venema 56 /* Google, Inc. 57 /* 111 8th Avenue 58 /* New York, NY 10011, USA 59 /* 60 /* Wietse Venema 61 /* porcupine.org 62 /*--*/ 63 64 /* System library. */ 65 66 #include <sys_defs.h> 67 68 /* Utility library. */ 69 70 #include <msg.h> 71 #include <vstring.h> 72 #include <vstream.h> 73 #include <split_at.h> 74 #include <mymalloc.h> 75 76 /* Global library. */ 77 78 #include <mail_params.h> 79 #include <deliver_pass.h> 80 #include <dsb_scan.h> 81 #include <defer.h> 82 #include <rcpt_print.h> 83 #include <info_log_addr_form.h> 84 85 #define DELIVER_PASS_DEFER 1 86 #define DELIVER_PASS_UNKNOWN 2 87 88 /* deliver_pass_initial_reply - retrieve initial delivery process response */ 89 90 static int deliver_pass_initial_reply(VSTREAM *stream) 91 { 92 if (attr_scan(stream, ATTR_FLAG_STRICT, 93 RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_DELIVER), 94 ATTR_TYPE_END) != 0) { 95 msg_warn("%s: malformed response", VSTREAM_PATH(stream)); 96 return (-1); 97 } 98 return (0); 99 } 100 101 /* deliver_pass_send_request - send delivery request to delivery process */ 102 103 static int deliver_pass_send_request(VSTREAM *stream, DELIVER_REQUEST *request, 104 const char *nexthop, 105 RECIPIENT *rcpt) 106 { 107 int stat; 108 109 attr_print(stream, ATTR_FLAG_NONE, 110 SEND_ATTR_INT(MAIL_ATTR_FLAGS, request->flags), 111 SEND_ATTR_STR(MAIL_ATTR_QUEUE, request->queue_name), 112 SEND_ATTR_STR(MAIL_ATTR_QUEUEID, request->queue_id), 113 SEND_ATTR_LONG(MAIL_ATTR_OFFSET, request->data_offset), 114 SEND_ATTR_LONG(MAIL_ATTR_SIZE, request->data_size), 115 SEND_ATTR_STR(MAIL_ATTR_NEXTHOP, nexthop), 116 SEND_ATTR_STR(MAIL_ATTR_ENCODING, request->encoding), 117 SEND_ATTR_INT(MAIL_ATTR_SENDOPTS, request->sendopts), 118 SEND_ATTR_STR(MAIL_ATTR_SENDER, request->sender), 119 SEND_ATTR_STR(MAIL_ATTR_DSN_ENVID, request->dsn_envid), 120 SEND_ATTR_INT(MAIL_ATTR_DSN_RET, request->dsn_ret), 121 SEND_ATTR_FUNC(msg_stats_print, (const void *) &request->msg_stats), 122 /* XXX Should be encapsulated with ATTR_TYPE_FUNC. */ 123 SEND_ATTR_STR(MAIL_ATTR_LOG_CLIENT_NAME, request->client_name), 124 SEND_ATTR_STR(MAIL_ATTR_LOG_CLIENT_ADDR, request->client_addr), 125 SEND_ATTR_STR(MAIL_ATTR_LOG_CLIENT_PORT, request->client_port), 126 SEND_ATTR_STR(MAIL_ATTR_LOG_PROTO_NAME, request->client_proto), 127 SEND_ATTR_STR(MAIL_ATTR_LOG_HELO_NAME, request->client_helo), 128 /* XXX Should be encapsulated with ATTR_TYPE_FUNC. */ 129 SEND_ATTR_STR(MAIL_ATTR_SASL_METHOD, request->sasl_method), 130 SEND_ATTR_STR(MAIL_ATTR_SASL_USERNAME, request->sasl_username), 131 SEND_ATTR_STR(MAIL_ATTR_SASL_SENDER, request->sasl_sender), 132 /* XXX Ditto if we want to pass TLS certificate info. */ 133 SEND_ATTR_STR(MAIL_ATTR_LOG_IDENT, request->log_ident), 134 SEND_ATTR_STR(MAIL_ATTR_RWR_CONTEXT, request->rewrite_context), 135 SEND_ATTR_INT(MAIL_ATTR_RCPT_COUNT, 1), 136 ATTR_TYPE_END); 137 attr_print(stream, ATTR_FLAG_NONE, 138 SEND_ATTR_FUNC(rcpt_print, (const void *) rcpt), 139 ATTR_TYPE_END); 140 141 if (vstream_fflush(stream)) { 142 msg_warn("%s: bad write: %m", VSTREAM_PATH(stream)); 143 stat = -1; 144 } else { 145 stat = 0; 146 } 147 return (stat); 148 } 149 150 /* deliver_pass_final_reply - retrieve final delivery status response */ 151 152 static int deliver_pass_final_reply(VSTREAM *stream, DSN_BUF *dsb) 153 { 154 int stat; 155 156 if (attr_scan(stream, ATTR_FLAG_STRICT, 157 RECV_ATTR_FUNC(dsb_scan, (void *) dsb), 158 RECV_ATTR_INT(MAIL_ATTR_STATUS, &stat), 159 ATTR_TYPE_END) != 2) { 160 msg_warn("%s: malformed response", VSTREAM_PATH(stream)); 161 return (DELIVER_PASS_UNKNOWN); 162 } else { 163 return (stat ? DELIVER_PASS_DEFER : 0); 164 } 165 } 166 167 /* deliver_pass - deliver one per-site queue entry */ 168 169 int deliver_pass(const char *class, const char *service, 170 DELIVER_REQUEST *request, 171 RECIPIENT *rcpt) 172 { 173 VSTREAM *stream; 174 DSN_BUF *dsb; 175 DSN dsn; 176 int status; 177 char *saved_service; 178 char *transport; 179 char *nexthop; 180 181 /* 182 * Parse service into transport:nexthop form, and allow for omission of 183 * optional fields 184 */ 185 transport = saved_service = mystrdup(service); 186 if ((nexthop = split_at(saved_service, ':')) == 0 || *nexthop == 0) 187 nexthop = request->nexthop; 188 if (*transport == 0) 189 msg_fatal("missing transport name in \"%s\"", service); 190 191 /* 192 * Initialize. 193 */ 194 msg_info("%s: passing <%s> to transport=%s", 195 request->queue_id, info_log_addr_form_recipient(rcpt->address), 196 transport); 197 stream = mail_connect_wait(class, transport); 198 dsb = dsb_create(); 199 200 /* 201 * Get the delivery process initial response. Send the queue file info 202 * and recipient info to the delivery process. Retrieve the delivery 203 * agent status report. The numerical status code indicates if delivery 204 * should be tried again. The reason text is sent only when a destination 205 * should be avoided for a while, so that the queue manager can log why 206 * it does not even try to schedule delivery to the affected recipients. 207 * XXX Can't pass back hop status info because the problem is with a 208 * different transport. 209 */ 210 if (deliver_pass_initial_reply(stream) != 0 211 || deliver_pass_send_request(stream, request, nexthop, rcpt) != 0) { 212 (void) DSN_SIMPLE(&dsn, "4.3.0", "mail transport unavailable"); 213 status = defer_append(DEL_REQ_TRACE_FLAGS(request->flags), 214 request->queue_id, &request->msg_stats, 215 rcpt, "none", NO_TLS_STATS, &dsn); 216 } else if ((status = deliver_pass_final_reply(stream, dsb)) 217 == DELIVER_PASS_UNKNOWN) { 218 (void) DSN_SIMPLE(&dsn, "4.3.0", "unknown mail transport error"); 219 status = defer_append(DEL_REQ_TRACE_FLAGS(request->flags), 220 request->queue_id, &request->msg_stats, 221 rcpt, "none", NO_TLS_STATS, &dsn); 222 } 223 224 /* 225 * Clean up. 226 */ 227 vstream_fclose(stream); 228 dsb_free(dsb); 229 myfree(saved_service); 230 231 return (status); 232 } 233 234 /* deliver_pass_all - pass entire delivery request */ 235 236 int deliver_pass_all(const char *class, const char *service, 237 DELIVER_REQUEST *request) 238 { 239 RECIPIENT_LIST *list; 240 RECIPIENT *rcpt; 241 int status = 0; 242 243 /* 244 * XXX We should find out if the target transport can handle 245 * multi-recipient requests. Unfortunately such code is hard to test, 246 * rarely used, and therefore will be buggy. 247 */ 248 list = &request->rcpt_list; 249 for (rcpt = list->info; rcpt < list->info + list->len; rcpt++) 250 status |= deliver_pass(class, service, request, rcpt); 251 return (status); 252 } 253