void ngx_mail_starttls_handler(ngx_event_t *rev) { ngx_connection_t *c; ngx_mail_session_t *s; ngx_mail_ssl_conf_t *sslcf; c = rev->data; s = c->data; s->starttls = 1; c->log->action = "in starttls state"; sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); ngx_mail_ssl_init_connection(&sslcf->ssl, c); }
void ngx_mail_init_connection(ngx_connection_t *c) { in_addr_t in_addr; socklen_t len; ngx_uint_t i; struct sockaddr_in sin; ngx_mail_log_ctx_t *ctx; ngx_mail_in_port_t *imip; ngx_mail_in_addr_t *imia; ngx_mail_session_t *s; /* find the server configuration for the address:port */ /* AF_INET only */ imip = c->listening->servers; imia = imip->addrs; i = 0; if (imip->naddrs > 1) { /* * There are several addresses on this port and one of them * is the "*:port" wildcard so getsockname() is needed to determine * the server address. * * AcceptEx() already gave this address. */ #if (NGX_WIN32) if (c->local_sockaddr) { in_addr = ((struct sockaddr_in *) c->local_sockaddr)->sin_addr.s_addr; } else #endif { len = sizeof(struct sockaddr_in); if (getsockname(c->fd, (struct sockaddr *) &sin, &len) == -1) { ngx_connection_error(c, ngx_socket_errno, "getsockname() failed"); ngx_mail_close_connection(c); return; } in_addr = sin.sin_addr.s_addr; } /* the last address is "*" */ for ( /* void */ ; i < imip->naddrs - 1; i++) { if (in_addr == imia[i].addr) { break; } } } s = ngx_pcalloc(c->pool, sizeof(ngx_mail_session_t)); if (s == NULL) { ngx_mail_close_connection(c); return; } s->main_conf = imia[i].ctx->main_conf; s->srv_conf = imia[i].ctx->srv_conf; s->addr_text = &imia[i].addr_text; c->data = s; s->connection = c; ngx_log_error(NGX_LOG_INFO, c->log, 0, "*%ui client %V connected to %V", c->number, &c->addr_text, s->addr_text); ctx = ngx_palloc(c->pool, sizeof(ngx_mail_log_ctx_t)); if (ctx == NULL) { ngx_mail_close_connection(c); return; } ctx->client = &c->addr_text; ctx->session = s; c->log->connection = c->number; c->log->handler = ngx_mail_log_error; c->log->data = ctx; c->log->action = "sending client greeting line"; c->log_error = NGX_ERROR_INFO; #if (NGX_MAIL_SSL) { ngx_mail_ssl_conf_t *sslcf; sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); if (sslcf->enable) { ngx_mail_ssl_init_connection(&sslcf->ssl, c); return; } } #endif ngx_mail_init_session(c); }
void ngx_mail_init_connection(ngx_connection_t *c) { ngx_uint_t i; ngx_mail_port_t *port; struct sockaddr *sa; struct sockaddr_in *sin; ngx_mail_log_ctx_t *ctx; ngx_mail_in_addr_t *addr; ngx_mail_session_t *s; ngx_mail_addr_conf_t *addr_conf; #if (NGX_HAVE_INET6) struct sockaddr_in6 *sin6; ngx_mail_in6_addr_t *addr6; #endif /* find the server configuration for the address:port */ port = c->listening->servers; if (port->naddrs > 1) { /* * There are several addresses on this port and one of them * is the "*:port" wildcard so getsockname() is needed to determine * the server address. * * AcceptEx() already gave this address. */ if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) { ngx_mail_close_connection(c); return; } sa = c->local_sockaddr; switch (sa->sa_family) { #if (NGX_HAVE_INET6) case AF_INET6: sin6 = (struct sockaddr_in6 *) sa; addr6 = port->addrs; /* the last address is "*" */ for (i = 0; i < port->naddrs - 1; i++) { if (ngx_memcmp(&addr6[i].addr6, &sin6->sin6_addr, 16) == 0) { break; } } addr_conf = &addr6[i].conf; break; #endif default: /* AF_INET */ sin = (struct sockaddr_in *) sa; addr = port->addrs; /* the last address is "*" */ for (i = 0; i < port->naddrs - 1; i++) { if (addr[i].addr == sin->sin_addr.s_addr) { break; } } addr_conf = &addr[i].conf; break; } } else { switch (c->local_sockaddr->sa_family) { #if (NGX_HAVE_INET6) case AF_INET6: addr6 = port->addrs; addr_conf = &addr6[0].conf; break; #endif default: /* AF_INET */ addr = port->addrs; addr_conf = &addr[0].conf; break; } } s = ngx_pcalloc(c->pool, sizeof(ngx_mail_session_t)); if (s == NULL) { ngx_mail_close_connection(c); return; } s->main_conf = addr_conf->ctx->main_conf; s->srv_conf = addr_conf->ctx->srv_conf; s->addr_text = &addr_conf->addr_text; c->data = s; s->connection = c; ngx_log_error(NGX_LOG_INFO, c->log, 0, "*%ui client %V connected to %V", c->number, &c->addr_text, s->addr_text); ctx = ngx_palloc(c->pool, sizeof(ngx_mail_log_ctx_t)); if (ctx == NULL) { ngx_mail_close_connection(c); return; } ctx->client = &c->addr_text; ctx->session = s; c->log->connection = c->number; c->log->handler = ngx_mail_log_error; c->log->data = ctx; c->log->action = "sending client greeting line"; c->log_error = NGX_ERROR_INFO; #if (NGX_MAIL_SSL) { ngx_mail_ssl_conf_t *sslcf; sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); if (sslcf->enable) { c->log->action = "SSL handshaking"; ngx_mail_ssl_init_connection(&sslcf->ssl, c, NGX_MAIL_SECURE_DIR_IN); return; } if (addr_conf->ssl) { c->log->action = "SSL handshaking"; if (sslcf->ssl.ctx == NULL) { ngx_log_error(NGX_LOG_ERR, c->log, 0, "no \"ssl_certificate\" is defined " "in server listening on SSL port"); ngx_mail_close_connection(c); return; } ngx_mail_ssl_init_connection(&sslcf->ssl, c, NGX_MAIL_SECURE_DIR_IN); return; } } #endif ngx_mail_init_session(c); }
void ngx_mail_proxy_init(ngx_mail_session_t *s, ngx_addr_t *peer) { int keepalive; ngx_int_t rc; ngx_int_t secured = 0; ngx_mail_proxy_ctx_t *p; ngx_mail_proxy_conf_t *pcf; ngx_mail_core_srv_conf_t *cscf; ngx_mail_ssl_conf_t *sslcf; s->connection->log->action = "connecting to upstream"; cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); if (cscf->so_keepalive) { keepalive = 1; if (setsockopt(s->connection->fd, SOL_SOCKET, SO_KEEPALIVE, (const void *) &keepalive, sizeof(int)) == -1) { ngx_log_error(NGX_LOG_ALERT, s->connection->log, ngx_socket_errno, "setsockopt(SO_KEEPALIVE) failed"); } } p = ngx_pcalloc(s->connection->pool, sizeof(ngx_mail_proxy_ctx_t)); if (p == NULL) { ngx_mail_session_internal_server_error(s); return; } s->proxy = p; p->upstream.sockaddr = peer->sockaddr; p->upstream.socklen = peer->socklen; p->upstream.name = &peer->name; p->upstream.get = ngx_event_get_peer; p->upstream.log = s->connection->log; p->upstream.log_error = NGX_ERROR_ERR; rc = ngx_event_connect_peer(&p->upstream); if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) { ngx_mail_proxy_internal_server_error(s); return; } ngx_add_timer(p->upstream.connection->read, cscf->timeout); p->upstream.connection->data = s; p->upstream.connection->pool = s->connection->pool; s->connection->read->handler = ngx_mail_proxy_block_read; p->upstream.connection->write->handler = ngx_mail_proxy_dummy_handler; #if (NGX_MAIL_SSL) if (s->auth_security) { sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); if (sslcf->ssl.ctx) { s->connection->log->action = "SSL handshaking"; ngx_mail_ssl_init_connection(&sslcf->ssl, p->upstream.connection, NGX_MAIL_SECURE_DIR_OUT); secured = 1; } else { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "failed to get SSL context;"); ngx_mail_proxy_internal_server_error(s); return; } } #endif pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module); s->proxy->buffer = ngx_create_temp_buf(s->connection->pool, pcf->buffer_size); if (s->proxy->buffer == NULL) { ngx_mail_proxy_internal_server_error(s); return; } s->out.len = 0; /* state will be changed in the ssl init routine */ if (!secured) ngx_mail_proxy_start(p->upstream.connection); }