+
+ doingEHLO = 1;
+ result = smtalk (SM_HELO, "EHLO %s", client);
+ doingEHLO = 0;
+
+ if (result >= 500 && result <= 599)
+ result = smtalk (SM_HELO, "HELO %s", client);
+
+ if (result != 250) {
+ sm_end (NOTOK);
+ return RP_RPLY;
+ }
+
+#ifdef TLS_SUPPORT
+ /*
+ * If the user requested TLS support, then try to do the STARTTLS command
+ * as part of the initial dialog. Assuming this works, we then need to
+ * restart the EHLO dialog after TLS negotiation is complete.
+ */
+
+ if (tls) {
+ if (! EHLOset("STARTTLS")) {
+ sm_end(NOTOK);
+ return sm_ierror("SMTP server does not support TLS");
+ }
+
+ result = smtalk(SM_HELO, "STARTTLS");
+
+ if (result != 220) {
+ sm_end(NOTOK);
+ return RP_RPLY;
+ }
+
+ /*
+ * Okay, the other side should be waiting for us to start TLS
+ * negotiation. Oblige them.
+ */
+
+ if (! sslctx) {
+ SSL_METHOD *method;
+
+ SSL_library_init();
+ SSL_load_error_strings();
+
+ method = TLSv1_client_method(); /* Not sure about this */
+
+ sslctx = SSL_CTX_new(method);
+
+ if (! sslctx) {
+ sm_end(NOTOK);
+ return sm_ierror("Unable to initialize OpenSSL context: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ }
+ }
+
+ ssl = SSL_new(sslctx);
+
+ if (! ssl) {
+ sm_end(NOTOK);
+ return sm_ierror("Unable to create SSL connection: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ }
+
+ sbior = BIO_new_socket(fileno(sm_rfp), BIO_NOCLOSE);
+ sbiow = BIO_new_socket(fileno(sm_wfp), BIO_NOCLOSE);
+
+ if (sbior == NULL || sbiow == NULL) {
+ sm_end(NOTOK);
+ return sm_ierror("Unable to create BIO endpoints: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ }
+
+ SSL_set_bio(ssl, sbior, sbiow);
+
+ if (SSL_connect(ssl) < 1) {
+ sm_end(NOTOK);
+ return sm_ierror("Unable to negotiate SSL connection: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ }
+
+ if (sm_debug) {
+ SSL_CIPHER *cipher = SSL_get_current_cipher(ssl);
+ printf("SSL negotiation successful: %s(%d) %s\n",
+ SSL_CIPHER_get_name(cipher),
+ SSL_CIPHER_get_bits(cipher, NULL),
+ SSL_CIPHER_get_version(cipher));
+
+ }
+
+ tls_active = 1;
+