SMTP-клиент в блоках C на SSL_read - PullRequest
0 голосов
/ 10 сентября 2018

Я работал над небольшим проектом, который является SMTP-клиентом, написанным на C с SSL.

Я пытаюсь заставить его работать с GMail. Я включил разрешить незащищенные приложения в настройках GMail.

Когда я пытаюсь аутентифицироваться с использованием OpenSSL CLI с помощью команды openssl s_client -connect smtp.gmail.com:465, она работает просто отлично, я получаю правильные ответы для команд HELO и EHLO (см. Вывод ниже)

220 smtp.gmail.com ESMTP o3-v6sm18136158pgv.53 - gsmtp
HELO smtp.gmail.com
250 smtp.gmail.com at your service
AUTH LOGIN
334 VXNlcm5hbWU6

Но как только я запускаю это с моим клиентом C, он зависает на SSL_read после отправки HELO smtp.gmail.com и даже не дает никакого вывода для HELO smtp.gmail.com.

Но если я отправлю только HELO, я получу правильный ответ от сервера о том, что пустой HELO не разрешен

MAIN

int main(int argc, char **argv) {
    setup("smtp.gmail.com", 465);
    printf("[INFO] -- %s\n", recv_secure());
    send_secure("HELO smtp.gmail.com\r\n");
    printf("[INFO] -- %s\n", recv_secure());
    send_secure("AUTH LOGIN\r\n");
    printf("[INFO] -- %s\n", recv_secure());
    close_secure();
    return 0;
}

установка

int setup(char *hostname, int port) {
    SSL_CTX *ctx = init();

    struct hostent *host;
    struct sockaddr_in addr;
    int sock_fd;

    if((host = gethostbyname(hostname)) == NULL) {
        fprintf(stderr, "[ERROR] Unable to get host by name: %s", hostname);
        return -1;
    }

    sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
    bzero(&addr, sizeof(addr));

    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = *(long*)host->h_addr_list[0];

    if(connect(sock_fd, (struct sockaddr*) &addr, sizeof(addr)) != 0) {
        close(sock_fd);
        fprintf(stderr, "[ERROR] Unable to connect to remote server: %s\n", hostname);
        return -1;
    }

    ssl = SSL_new(ctx);
    SSL_set_fd(ssl, sock_fd);

    if(SSL_connect(ssl) == -1) {
        fprintf(stderr, "[ERROR] Unable to establish secure connection\n");
        close(sock_fd);
        return -1;
    }
    return sock_fd;
}

send_secure

void send_secure(const char* buffer){
    SSL_write(ssl, buffer, sizeof(buffer));
}

recv_secure

char* recv_secure() {

    int bytes = SSL_read(ssl, rbuffer, SIZE);
    rbuffer[bytes] = 0;
    fprintf(stderr, "[DEBUG] -- Received: %s\n", rbuffer);
    return rbuffer;
}

Я запустил ltrace с ним, и он, кажется, заблокирован на SSL_read, но SSL_pending возвращаемое значение 0

Кажется, я не понимаю, чего мне здесь не хватает.

1 Ответ

0 голосов
/ 11 сентября 2018
void send_secure(const char* buffer){
  SSL_write(ssl, mbuffer, sizeof(mbuffer));
}

Если предположить, что mbuffer является опечаткой и вместо нее подразумевается buffer, будет записано 8 или 4 байта (размер указателя, в зависимости от вашей платформы), а недлина буфера, как вы, вероятно, ожидали (что также будет неверно, поскольку sizeof при применении к литеральной строке также включает завершающий нулевой байт, который НЕ будет принят сервером smtp).

Изменение sizeof на strlen может позволить вам продолжить, но у вашего кода много проблем, например:

int bytes = SSL_read(ssl, rbuffer, SIZE);
rbuffer[bytes] = 0;

Если SSL_read вернет -1, это приведет (в лучшем случае ;-)) к вашей программе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...