Я работал над небольшим проектом, который является 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
Кажется, я не понимаю, чего мне здесь не хватает.