2013-03-09 1 views
2

Я пытаюсь сделать простое подключение к SMTP-серверу (для которого требуется аутентификация). Я подключен к smtp.live.com на порту 587, используя SSL (библиотека OpenSSL на C).Как использовать SMTP Auth в C?

Сначала я инициализирую свой сокет функцией socket(), затем подключитесь к серверу с помощью connect(). Затем я запускаю канал SSL, а затем пытаюсь войти в систему.

Вот результат на моей оболочки:

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 : 

Как вы можете видеть, имя пользователя и пароль оба закодировать в base64 (без \ г \ п). Я не понимаю, почему сервер ничего не отвечает ... (я попытался поставить sleep() перед чтением сокета, но получил тот же результат)

Код для подключения к серверу:

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); 
} 

код для запуска 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); 
} 

код для подключения 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); 
} 

Главная:

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); 
} 
+0

Вам необходимо показать нам свой код ... –

ответ

1

Прежде всего, я надеюсь, что вы намерены улучшить своего клиента, чтобы он фактически реагировал на то, что посылает сервер. Например, похоже, что в вашей функции _launch_ssl вы фактически не проверяете ответ сервера на EHLO, чтобы убедиться, что STARTTLS предлагается в качестве опции, прежде чем пытаться его использовать. Псевдокод этой функции должно быть:

  1. отправить EHLO (желательно не с чем-то бессмысленным, как [127.0.0.1]!)
  2. проверки ответа сервера
  3. если STARTTLS не является одним из вариантов, предлагаемых, под залог
  4. Если STARTTLS входит в число предлагаемых вариантов, отправьте STARTTLS и продолжайте.

, подобным образом, в main(), вам нужно проверить после EHLO, что сервер фактически ответил 250 и проверить после AUTH, что сервер фактически ответил 334.

В противном случае, проблема, кажется, что вы не отправляйте \r\n после ваших ответов. Другими словами:

ssl_write_socket(c, "Y2hlcmNoZXN0b3lhQGhvdG1haWwuY29tXHJcbg0K"); 

должно быть:

ssl_write_socket(c, "Y2hlcmNoZXN0b3lhQGhvdG1haWwuY29tXHJcbg0K\r\n"); 

Кроме того, ваша base64 строка содержит \\r\\n\r\n (обратной косой + 'R' + обратной косой + 'п' + CR + LF) встроенный внутри строка, как будто \\r\\n\r\n были частью имени пользователя. Предполагая, что это неправильно, тогда на самом деле ваш код должен, вероятно, действительно читать:

ssl_write_socket(c, "Y2hlcmNoZXN0b3lhQGhvdG1haWwuY29t\r\n"); 
Смежные вопросы