pop3: report error responses
[pop3.git] / conn_mbedtls.c
blob64d892cb7c6ef2614a74197f87cb4f5f060b521f
1 #include <arpa/inet.h>
2 #include <netinet/in.h>
3 #include <netdb.h>
4 #include <signal.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <sys/socket.h>
9 #include <sys/stat.h>
10 #include <sys/types.h>
11 #include <time.h>
12 #include <unistd.h>
13 #include <polarssl/ssl.h>
14 #include <polarssl/entropy.h>
15 #include <polarssl/ctr_drbg.h>
17 struct conn {
18 int fd;
19 int tls;
20 ssl_context ssl;
21 ssl_session ssn;
22 ctr_drbg_context ctr_drbg;
23 x509_crt cert;
26 static int ps_send(void *ctx, const unsigned char *buf, size_t len)
28 return write(*(int *) ctx, buf, len);
31 static int ps_recv(void *ctx, unsigned char *buf, size_t len)
33 return read(*(int *) ctx, buf, len);
36 int conn_read(struct conn *conn, char *buf, int len)
38 if (conn->tls)
39 return ssl_read(&conn->ssl, (unsigned char *) buf, len);
40 return read(conn->fd, buf, len);
43 int conn_write(struct conn *conn, char *buf, int len)
45 if (conn->tls)
46 return ssl_write(&conn->ssl, (unsigned char *) buf, len);
47 return write(conn->fd, buf, len);
50 int conn_tls(struct conn *conn, char *certfile)
52 entropy_context entropy;
53 entropy_init(&entropy);
54 ctr_drbg_init(&conn->ctr_drbg, entropy_func, &entropy, NULL, 0);
55 if (ssl_init(&conn->ssl))
56 return 1;
57 ssl_set_endpoint(&conn->ssl, SSL_IS_CLIENT);
58 if (certfile) {
59 x509_crt_parse_file(&conn->cert, certfile);
60 ssl_set_ca_chain(&conn->ssl, &conn->cert, NULL, NULL);
61 ssl_set_authmode(&conn->ssl, SSL_VERIFY_REQUIRED);
62 } else{
63 ssl_set_authmode(&conn->ssl, SSL_VERIFY_NONE);
65 ssl_set_rng(&conn->ssl, ctr_drbg_random, &conn->ctr_drbg);
66 ssl_set_bio(&conn->ssl, ps_recv, &conn->fd, ps_send, &conn->fd);
67 ssl_set_ciphersuites(&conn->ssl, ssl_list_ciphersuites());
68 ssl_set_session(&conn->ssl, &conn->ssn);
69 conn->tls = 1;
70 return ssl_handshake(&conn->ssl);
73 struct conn *conn_connect(char *addr, char *port, char *certfile)
75 struct addrinfo hints, *addrinfo;
76 struct conn *conn;
77 int fd;
79 memset(&hints, 0, sizeof(hints));
80 hints.ai_family = AF_UNSPEC;
81 hints.ai_socktype = SOCK_STREAM;
82 hints.ai_flags = AI_PASSIVE;
84 if (getaddrinfo(addr, port, &hints, &addrinfo))
85 return NULL;
86 fd = socket(addrinfo->ai_family, addrinfo->ai_socktype,
87 addrinfo->ai_protocol);
89 if (connect(fd, addrinfo->ai_addr, addrinfo->ai_addrlen) == -1) {
90 close(fd);
91 freeaddrinfo(addrinfo);
92 return NULL;
94 freeaddrinfo(addrinfo);
96 conn = malloc(sizeof(*conn));
97 memset(conn, 0, sizeof(*conn));
98 conn->fd = fd;
99 return conn;
102 int conn_close(struct conn *conn)
104 if (conn->tls) {
105 ssl_close_notify(&conn->ssl);
106 x509_crt_free(&conn->cert);
107 ssl_free(&conn->ssl);
109 close(conn->fd);
110 free(conn);
111 return 0;