C上的SMTP客户端在SSL_read上阻止

时间:2018-09-10 14:06:06

标签: c email openssl smtp

我一直在从事一个小的项目,这是一个用C用SSL编写的SMTP客户端。

我正在尝试使其与GMail一起使用。我已在GMail设置中启用了允许不安全的应用程序

当我尝试使用带有命令openssl s_client -connect smtp.gmail.com:465的OpenSSL CLI进行身份验证时,它工作得很好,我对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客户端运行它,它在发送HELO smtp.gmail.com后就挂在SSL_read上,它甚至没有给我HELO smtp.gmail.com的任何输出。

但是,如果我仅发送HELO,则会从服务器收到正确的回复,说不允许空HELO

主要

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 :(得分:3)

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,这将(在最佳情况下;-)导致程序崩溃。