我一直在从事一个小的项目,这是一个用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;
}
void send_secure(const char* buffer){
SSL_write(ssl, buffer, sizeof(buffer));
}
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
我似乎不明白我在这里想念什么。
答案 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,这将(在最佳情况下;-)导致程序崩溃。