Here is the relevant source from protocol.c

static void smtp_client(CLI *c) {
    char *line;

    do { /* copy multiline greeting */
        line=fdgetline(c, c->remote_fd.fd);
        fdputline(c, c->local_wfd.fd, line);
    } while(isprefix(line, "220-"));

    fdputline(c, c->remote_fd.fd, "EHLO localhost");
    do { /* skip multiline reply */
        line=fdgetline(c, c->remote_fd.fd);
    } while(isprefix(line, "250-"));
    if(!isprefix(line, "250 ")) { /* error */
        s_log(LOG_ERR, "Remote server is not RFC 1425 compliant");
        longjmp(c->err, 1);
    }

    fdputline(c, c->remote_fd.fd, "STARTTLS");
    do { /* skip multiline reply */
        line=fdgetline(c, c->remote_fd.fd);
    } while(isprefix(line, "220-"));
    if(!isprefix(line, "220 ")) { /* error */
        s_log(LOG_ERR, "Remote server is not RFC 2487 compliant");
        longjmp(c->err, 1);
    }
}

static void smtp_server(CLI *c) {
    char *line;

    s_poll_init(&c->fds);
    s_poll_add(&c->fds, c->local_rfd.fd, 1, 0);
    switch(s_poll_wait(&c->fds, 0, 200)) { /* wait up to 200ms */
    case 0: /* fd not ready to read */
        s_log(LOG_DEBUG, "RFC 2487 detected");
        break;
    case 1: /* fd ready to read */
        s_log(LOG_DEBUG, "RFC 2487 not detected");
        return; /* return if RFC 2487 is not used */
    default: /* -1 */
        sockerror("RFC2487 (s_poll_wait)");
        longjmp(c->err, 1);
    }

    line=fdgetline(c, c->remote_fd.fd);
    if(!isprefix(line, "220")) {
        s_log(LOG_ERR, "Unknown server welcome");
        longjmp(c->err, 1);
    }
    fdprintf(c, c->local_wfd.fd, "%s + stunnel", line);
    line=fdgetline(c, c->local_rfd.fd);
    if(!isprefix(line, "EHLO ")) {
        s_log(LOG_ERR, "Unknown client EHLO");
        longjmp(c->err, 1);
    }
    fdprintf(c, c->local_wfd.fd, "250-%s Welcome", line);
    fdputline(c, c->local_wfd.fd, "250 STARTTLS");
    line=fdgetline(c, c->local_rfd.fd);
    if(!isprefix(line, "STARTTLS")) {
        s_log(LOG_ERR, "STARTTLS expected");
        longjmp(c->err, 1);
    }
    fdputline(c, c->local_wfd.fd, "220 Go ahead");
}


After the initial handshake, it looks for the STARTTLS line. From there, that's where the magic happens. Try setting protocol equal to smtp.



On Wed, Dec 5, 2012 at 6:00 PM, <jw72253@verizon.net> wrote:
 
 
 Hi, Brian.
 
You know, I probably did not ask this question clearly enough. I understood that the purpose of "starttls" is to negotiate an (higher level) encrypted connection on the same port. No problem with this much. What I am really trying to get at is this: how does stunnel go about requesting the negotiation from the server? I am wanting to make a connection to a remote SMTP server using stunnel on port 587. So, if I use this setting
 
[my SMTP connection]
Accept = 127.0.0.1:<some port>
Connect = <SMTP server IP>:587
 
I am assuming that with this my connection would start out SSL, but where is the part that makes it begin to negotiate from SSL to the TLS? Based on my impression of what I read, I was expecting also to see something along these lines
 
protocol = starttls 
 
This assumption may very well be a misconception, but how so? Thanks.
 
Or is my understanding of this process faulty, incomplete, all of the above?  :(
 
 
John 
 
 
Knowledge counts.  
 
On 12/05/12, Brian Wilkins<bwilkins@gmail.com> wrote:
 
>From protocol.c in the stunnel source:

static const struct {
    char *name;
    struct {
        PROTOCOL_PHASE type;
        FUNCTION func;
    } handlers[2];
} protocols[]={
    {"proxy",   {{PROTOCOL_PRE_SSL,     proxy_server},      {PROTOCOL_PRE_SSL, NULL}}},
    {"cifs",    {{PROTOCOL_PRE_CONNECT, cifs_server},       {PROTOCOL_PRE_SSL, cifs_client}}},
    {"pgsql",   {{PROTOCOL_PRE_CONNECT, pgsql_server},      {PROTOCOL_PRE_SSL, pgsql_client}}},
    {"smtp",    {{PROTOCOL_PRE_SSL,     smtp_server},       {PROTOCOL_PRE_SSL, smtp_client}}},
    {"pop3",    {{PROTOCOL_PRE_SSL,     pop3_server},       {PROTOCOL_PRE_SSL, pop3_client}}},
    {"imap",    {{PROTOCOL_PRE_SSL,     imap_server},       {PROTOCOL_PRE_SSL, imap_client}}},
    {"nntp",    {{PROTOCOL_NONE,        NULL},              {PROTOCOL_PRE_SSL, nntp_client}}},
    {"connect", {{PROTOCOL_PRE_CONNECT, connect_server},    {PROTOCOL_PRE_SSL, connect_client}}},
    {NULL,      {{PROTOCOL_NONE,        NULL},              {PROTOCOL_NONE,    NULL}}}
};

STARTTLS is an extension to plain text communication protocols, which offers a way to upgrade a plain text connection to an encrypted (TLS or SSL) connection instead of using a separate port for encrypted communication.

stunnel will use one port to communicate the encrypted information. That's what it is telling you. No need to initiate a separate port when STARTTLS is sent.



On Wed, Dec 5, 2012 at 1:27 PM, John A. Wallace <jw72253@verizon.net> wrote:

The Service Level Options of the manual includes the following points:

protocol = proto

      application protocol to negotiate SSL (e.g. starttls or stls)

      protocol option should not be used with SSL encryption on a separate port.

      Currently supported protocols:

CIFS

Connect

Etc..

However, in the listed protocols supported neither starttls or stls appears, even though they appear to be options as far as I can see from the above explanation.  Am I missing something here, or should they be among those in the list, and can one use this setting:

Protocol=starttls


Also, I dont really understand what this statement is telling me: protocol option should not be used with SSL encryption on a separate port.

John A. Wallace


_______________________________________________
stunnel-users mailing list
stunnel-users@stunnel.org
https://www.stunnel.org/cgi-bin/mailman/listinfo/stunnel-users



_______________________________________________
stunnel-users mailing list
stunnel-users@stunnel.org
https://www.stunnel.org/cgi-bin/mailman/listinfo/stunnel-users