I have been working on a small project which is a SMTP client written in C with SSL.
I am trying to get it working with GMail. I have enabled the allow unsecure apps in GMail settings.
When I try to authenticate using the OpenSSL CLI with the command openssl s_client -connect smtp.gmail.com:465
it works just fine I get proper responses for HELO and EHLO commands (see the output below)
220 smtp.gmail.com ESMTP o3-v6sm18136158pgv.53 - gsmtp
HELO smtp.gmail.com
250 smtp.gmail.com at your service
AUTH LOGIN
334 VXNlcm5hbWU6
But once I run this with my C client it hangs on SSL_read after I send HELO smtp.gmail.com
and it does not even give me any output for HELO smtp.gmail.com
.
But if I send just HELO
I get a proper response from the server saying that empty HELO isn't allowed
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;
}
I ran ltrace with it and it seems to be blocked at SSL_read
but SSL_pending
return value is 0
I cannot seem to understand what am I missing here.
void send_secure(const char* buffer){ SSL_write(ssl, mbuffer, sizeof(mbuffer)); }
Assuming that mbuffer
is a typo and buffer
was meant instead, this will write either 8 or 4 bytes (the size of a pointer, depending on your platform), not the length of the buffer as you probably expected (which will be wrong, too since sizeof
, when applied to a literal string, also includes the terminating null byte -- which will NOT be accepted by the smtp server).
Changing sizeof
to strlen
may let you proceed further, but your code has a lot of problems, for instance:
int bytes = SSL_read(ssl, rbuffer, SIZE); rbuffer[bytes] = 0;
If SSL_read
returns -1, this will (in the best case ;-)) crash your program.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.