Reputation: 213
I'm trying to do a simple connection to a SMTP server (that requires authentification). I'm connected to smtp.live.com on port 587 using SSL (the OpenSSL library in C).
I first initialize my socket with the socket() function, then connect to the server with connect(). Then I launch the SSL channel and then I try to login.
Here's the output on my shell :
server : 220 BLU0-SMTP261.phx.gbl Microsoft ESMTP MAIL Service, Version: 6.0.3790.4675 ready at Sat, 9 Mar 2013 07:25:17 -0800
EHLO [127.0.0.1]
server : 250-BLU0-SMTP261.phx.gbl Hello [163.5.221.45]
250-TURN
250-SIZE 41943040
250-ETRN
250-PIPELINING
250-DSN
250-ENHANCEDSTATUSCODES
250-8bitmime
250-BINARYMIME
250-CHUNKING
250-VRFY
250-TLS
250-STARTTLS
250 OK
STARTTLS
server : 220 2.0.0 SMTP server ready
EHLO [127.0.0.1]
server : 250-BLU0-SMTP261.phx.gbl Hello [163.5.221.45]
250-TURN
250-SIZE 41943040
250-ETRN
250-PIPELINING
250-DSN
250-ENHANCEDSTATUSCODES
250-8bitmime
250-BINARYMIME
250-CHUNKING
250-VRFY
250-AUTH LOGIN PLAIN
250 OK
AUTH LOGIN
server : 334 VXNlcm5hbWU6
Y2hlcmGhvdXXXXXXXXXXXuY29tXHJcbg0K
serveur :
U2hsYWXXXXXXXXXXXwblxyXG4NCg0K
server :
As you can see, the username and the password are both encode in base64 (without \r\n). I don't understand why the server doesn't answer anything... (I tried to put a sleep() before reading the socket , but i got the same result)
Code to connect to the server :
static int _connect_IPV4(int socket, struct hostent *host)
{
struct sockaddr_in addr;
addr.sin_port = htons(587);
addr.sin_family = AF_INET;
addr.sin_addr = *(struct in_addr *)host->h_addr;
bzero(&addr.sin_zero, 8);
if (connect(socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) == -1)
printf("%s\n", strerror(errno));
else
return (socket);
}
Code to start SSL:
static void _launch_ssl(int socket)
{
read_socket(socket);
write_socket(socket, "EHLO [127.0.0.1]\r\n");
read_socket(socket);
write_socket(socket, "STARTTLS\r\n");
read_socket(socket);
}
Code to connect SSL:
connection *ssl_connect()
{
connection *c;
c = malloc(sizeof(connection));
c->ssl_handle = NULL;
c->ssl_context = NULL;
c->socket = connect_TCP_IP();
_launch_ssl(c->socket);
if (c->socket != -1)
{
SSL_load_error_strings();
SSL_library_init();
SSL_CTX_new(SSLv23_client_method());
SSL_new(c->ssl_context);
SSL_set_fd(c->ssl_handle, c->socket);
SSL_connect(c->ssl_handle);
}
return (c);
}
Main :
int main()
{
connection *c;
c = ssl_connect();
ssl_write_socket(c, "EHLO [127.0.0.1]\r\n");
ssl_read_socket(c);
ssl_write_socket(c, "AUTH LOGIN\r\n");
ssl_read_socket(c);
ssl_write_socket(c, "Y2hlcmNoZXN0b3lhQGhvdG1haWwuY29tXHJcbg0K");
printf("\n");
ssl_read_socket(c);
ssl_write_socket(c, "U2hsYWdldHRvUHIwblxyXG4NCg0K");
printf("\n");
ssl_read_socket(c);
}
Upvotes: 2
Views: 2261
Reputation: 22261
First of all, I hope you intend to improve your client so that it actually reacts to what the server sends. For example, it looks like in your _launch_ssl
function you do not actually check the server's reply to EHLO
to make sure STARTTLS
is offered as an option before you attempt to use it. The pseudocode of that function should be:
Similarily, in main()
, you need to check after EHLO
that the server has actually responded 250, and check after AUTH
that the server has actually responded 334.
Otherwise, the problem seems to be that you don't send \r\n
after your responses. In other words:
ssl_write_socket(c, "Y2hlcmNoZXN0b3lhQGhvdG1haWwuY29tXHJcbg0K");
should be:
ssl_write_socket(c, "Y2hlcmNoZXN0b3lhQGhvdG1haWwuY29tXHJcbg0K\r\n");
Furthermore, your base64 string contains an \\r\\n\r\n
(backslash + 'r' + backslash + 'n' + CR + LF) embedded inside the string as though the \\r\\n\r\n
were part of the username. Assuming that's wrong, then, in fact, your code should probably actually read:
ssl_write_socket(c, "Y2hlcmNoZXN0b3lhQGhvdG1haWwuY29t\r\n");
Upvotes: 1