SMTP_SESSION *smtp_session_alloc(VSTREAM *stream, const char *dest, const char *host, const char *addr, unsigned port, time_t start, int flags) { SMTP_SESSION *session; session = (SMTP_SESSION *) mymalloc(sizeof(*session)); session->stream = stream; session->dest = mystrdup(dest); session->host = mystrdup(host); session->addr = mystrdup(addr); session->namaddr = concatenate(host, "[", addr, "]", (char *) 0); session->helo = 0; session->port = port; session->features = 0; session->size_limit = 0; session->error_mask = 0; session->buffer = vstring_alloc(100); session->scratch = vstring_alloc(100); session->scratch2 = vstring_alloc(100); smtp_chat_init(session); session->mime_state = 0; if (session->port) { vstring_sprintf(session->buffer, "%s:%d", session->namaddr, ntohs(session->port)); session->namaddrport = mystrdup(STR(session->buffer)); } else session->namaddrport = mystrdup(session->namaddr); session->send_proto_helo = 0; if (flags & SMTP_MISC_FLAG_CONN_STORE) CACHE_THIS_SESSION_UNTIL(start + var_smtp_reuse_time); else DONT_CACHE_THIS_SESSION; session->reuse_count = 0; USE_NEWBORN_SESSION; /* He's not dead Jim! */ #ifdef USE_SASL_AUTH smtp_sasl_connect(session); #endif /* * Need to pass the session as a parameter when the new-style per-nexthop * policies can specify not only security level thresholds, but also how * security levels are defined. */ #ifdef USE_TLS session_tls_init(session, dest, host, flags); #endif session->state = 0; debug_peer_check(host, addr); return (session); }
SMTP_SESSION *smtp_session_alloc(VSTREAM *stream, SMTP_ITERATOR *iter, time_t start, int flags) { SMTP_SESSION *session; const char *host = STR(iter->host); const char *addr = STR(iter->addr); unsigned port = iter->port; session = (SMTP_SESSION *) mymalloc(sizeof(*session)); session->stream = stream; session->iterator = iter; session->namaddr = concatenate(host, "[", addr, "]", (char *) 0); session->helo = 0; session->port = port; session->features = 0; session->size_limit = 0; session->error_mask = 0; session->buffer = vstring_alloc(100); session->scratch = vstring_alloc(100); session->scratch2 = vstring_alloc(100); smtp_chat_init(session); session->mime_state = 0; if (session->port) { vstring_sprintf(session->buffer, "%s:%d", session->namaddr, ntohs(session->port)); session->namaddrport = mystrdup(STR(session->buffer)); } else session->namaddrport = mystrdup(session->namaddr); session->send_proto_helo = 0; if (flags & SMTP_MISC_FLAG_CONN_STORE) CACHE_THIS_SESSION_UNTIL(start + var_smtp_reuse_time); else DONT_CACHE_THIS_SESSION; session->reuse_count = 0; USE_NEWBORN_SESSION; /* He's not dead Jim! */ #ifdef USE_SASL_AUTH smtp_sasl_connect(session); #endif #ifdef USE_TLS session->tls_context = 0; session->tls_retry_plain = 0; session->tls_nexthop = 0; #endif session->state = 0; debug_peer_check(host, addr); return (session); }
SMTP_SESSION *smtp_session_activate(int fd, VSTRING *dest_prop, VSTRING *endp_prop) { const char *myname = "smtp_session_activate"; SMTP_SESSION *session; char *dest_props; char *endp_props; const char *prop; const char *dest; const char *host; const char *addr; unsigned port; unsigned features; /* server features */ time_t expire_time; /* session re-use expiration time */ unsigned reuse_count; /* # times reused */ /* * XXX it would be nice to have a VSTRING to VSTREAM adapter so that we * can de-serialize the properties with attr_scan(), instead of using * ad-hoc, non-reusable code. * * XXX As a preliminary solution we use mystrtok(), but that function is not * suitable for zero-length fields. */ endp_props = STR(endp_prop); if ((prop = mystrtok(&endp_props, "\n")) == 0 || !alldig(prop)) { msg_warn("%s: bad cached session reuse count property", myname); return (0); } reuse_count = atoi(prop); if ((dest = mystrtok(&endp_props, "\n")) == 0) { msg_warn("%s: missing cached session destination property", myname); return (0); } if ((host = mystrtok(&endp_props, "\n")) == 0) { msg_warn("%s: missing cached session hostname property", myname); return (0); } if ((addr = mystrtok(&endp_props, "\n")) == 0) { msg_warn("%s: missing cached session address property", myname); return (0); } if ((prop = mystrtok(&endp_props, "\n")) == 0 || !alldig(prop)) { msg_warn("%s: bad cached session port property", myname); return (0); } port = atoi(prop); if ((prop = mystrtok(&endp_props, "\n")) == 0 || !alldig(prop)) { msg_warn("%s: bad cached session features property", myname); return (0); } features = atoi(prop); if ((prop = mystrtok(&endp_props, "\n")) == 0 || !alldig(prop)) { msg_warn("%s: bad cached session expiration time property", myname); return (0); } #ifdef MISSING_STRTOUL expire_time = strtol(prop, 0, 10); #else expire_time = strtoul(prop, 0, 10); #endif if (dest_prop && VSTRING_LEN(dest_prop)) { dest_props = STR(dest_prop); if ((prop = mystrtok(&dest_props, "\n")) == 0 || !alldig(prop)) { msg_warn("%s: bad cached destination features property", myname); return (0); } features |= atoi(prop); } /* * Allright, bundle up what we have sofar. */ #define NO_FLAGS 0 session = smtp_session_alloc(vstream_fdopen(fd, O_RDWR), dest, host, addr, port, (time_t) 0, NO_FLAGS); session->features = (features | SMTP_FEATURE_FROM_CACHE); CACHE_THIS_SESSION_UNTIL(expire_time); session->reuse_count = ++reuse_count; if (msg_verbose) msg_info("%s: dest=%s host=%s addr=%s port=%u features=0x%x, " "ttl=%ld, reuse=%d", myname, dest, host, addr, ntohs(port), features, (long) (expire_time - time((time_t *) 0)), reuse_count); /* * Re-activate the SASL attributes. */ #ifdef notdef if (smtp_sasl_enable && smtp_sasl_activate(session, endp_props) < 0) { vstream_fdclose(session->stream); session->stream = 0; smtp_session_free(session); return (0); } #endif return (session); }
SMTP_SESSION *smtp_session_activate(int fd, SMTP_ITERATOR *iter, VSTRING *dest_prop, VSTRING *endp_prop) { const char *myname = "smtp_session_activate"; VSTREAM *mp; SMTP_SESSION *session; int endp_features; /* server features */ int dest_features; /* server features */ long expire_time; /* session re-use expiration time */ int reuse_count; /* # times reused */ #ifdef USE_TLS TLS_SESS_STATE *tls_context = 0; SMTP_TLS_POLICY *tls = iter->parent->tls; #define TLS_PROXY_CONTEXT_FREE() do { \ if (tls_context) \ tls_proxy_context_free(tls_context); \ } while (0) #else #define TLS_PROXY_CONTEXT_FREE() /* nothing */ #endif #define SMTP_SESSION_ACTIVATE_ERR_RETURN() do { \ TLS_PROXY_CONTEXT_FREE(); \ return (0); \ } while (0) /* * Sanity check: if TLS is required, the cached properties must contain a * TLS context. */ if ((mp = vstream_memopen(endp_prop, O_RDONLY)) == 0 || attr_scan_plain(mp, ATTR_FLAG_NONE, #ifdef USE_TLS RECV_ATTR_INT(SESS_ATTR_TLS_LEVEL, &tls->level), #endif RECV_ATTR_INT(SESS_ATTR_REUSE_COUNT, &reuse_count), RECV_ATTR_INT(SESS_ATTR_ENDP_FEATURES, &endp_features), RECV_ATTR_LONG(SESS_ATTR_EXPIRE_TIME, &expire_time), ATTR_TYPE_END) != 4 #ifdef USE_TLS || ((tls->level > TLS_LEV_MAY || (tls->level == TLS_LEV_MAY && vstream_peek(mp) > 0)) && attr_scan_plain(mp, ATTR_FLAG_NONE, RECV_ATTR_FUNC(tls_proxy_context_scan, (void *) &tls_context), ATTR_TYPE_END) != 1) #endif || vstream_fclose(mp) != 0) { msg_warn("smtp_session_activate: bad cached endp properties"); SMTP_SESSION_ACTIVATE_ERR_RETURN(); } /* * Clobber the iterator's current nexthop, host and address fields with * cached-connection information. This is done when a session is looked * up by delivery request nexthop instead of address and port. It is the * caller's responsibility to save and restore the delivery request * nexthop with SMTP_ITER_SAVE_DEST() and SMTP_ITER_RESTORE_DEST(). * * TODO: Eliminate the duplication between SMTP_ITERATOR and SMTP_SESSION. * * TODO: restore SASL username and password information so that we can * correctly save a reused authenticated connection. */ if (dest_prop && VSTRING_LEN(dest_prop)) { if ((mp = vstream_memopen(dest_prop, O_RDONLY)) == 0 || attr_scan_plain(mp, ATTR_FLAG_NONE, RECV_ATTR_STR(SESS_ATTR_DEST, iter->dest), RECV_ATTR_STR(SESS_ATTR_HOST, iter->host), RECV_ATTR_STR(SESS_ATTR_ADDR, iter->addr), RECV_ATTR_INT(SESS_ATTR_DEST_FEATURES, &dest_features), ATTR_TYPE_END) != 4 || vstream_fclose(mp) != 0) { msg_warn("smtp_session_passivate: bad cached dest properties"); SMTP_SESSION_ACTIVATE_ERR_RETURN(); } } else { dest_features = 0; } #ifdef USE_TLS if (msg_verbose) msg_info("%s: tls_level=%d", myname, tls->level); #endif /* * Allright, bundle up what we have sofar. */ #define NO_FLAGS 0 session = smtp_session_alloc(vstream_fdopen(fd, O_RDWR), iter, (time_t) 0, NO_FLAGS); session->features = (endp_features | dest_features | SMTP_FEATURE_FROM_CACHE); #ifdef USE_TLS session->tls_context = tls_context; #endif CACHE_THIS_SESSION_UNTIL(expire_time); session->reuse_count = ++reuse_count; if (msg_verbose) msg_info("%s: dest=%s host=%s addr=%s port=%u features=0x%x, " "ttl=%ld, reuse=%d", myname, STR(iter->dest), STR(iter->host), STR(iter->addr), ntohs(iter->port), endp_features | dest_features, (long) (expire_time - time((time_t *) 0)), reuse_count); #if USE_TLS if (tls_context) tls_log_summary(TLS_ROLE_CLIENT, TLS_USAGE_USED, session->tls_context); #endif return (session); }