#include #include #include #include #include #include #include #include #include "connect.h" #include "status.h" #include "url.h" int connect_socket(struct config *conf, struct url url) { struct addrinfo hints; struct addrinfo *servinfo; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; char port[5]; sprintf(port, "%d", url.port); int rc = getaddrinfo(url.host, port, &hints, &servinfo); if (rc != 0) { error_status(conf, (char *)gai_strerror(rc)); return ERR_GETADDRINFO; } struct addrinfo *p; int sockfd; for (p = servinfo; p != NULL; p = p->ai_next) { sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol); if (sockfd == -1) { continue; } rc = connect(sockfd, p->ai_addr, p->ai_addrlen); if (rc == -1) { close(sockfd); continue; } break; } if (p == NULL) { error_status(conf, strerror(errno)); return ERR_CONNECT; } update_status(conf, "Connected to socket"); freeaddrinfo(servinfo); return sockfd; } int tls_connect(struct config *conf, struct url url) { char status_msg[strlen(url.host) + 128]; sprintf(status_msg, "Connecting to %s...", url.host); update_status(conf, status_msg); struct connection *conn = init_connection(); conf->s.conn = conn; int sock; int rc = connect_socket(conf, url); if (rc < 0) { return rc; } else { sock = rc; } const SSL_METHOD *method; method = TLS_method(); SSL_CTX *ctx; ctx = SSL_CTX_new(method); if (ctx == NULL) { error_status(conf, "Failed to init SSL"); return ERR_SSL_CTX; } SSL *ssl; ssl = SSL_new(ctx); if (ssl == NULL) { error_status(conf, "Failed to init SSL"); return ERR_SSL_SSL; } rc = SSL_set_fd(ssl, sock); if (rc == 0) { error_status(conf, "Failed to wrap socket"); return ERR_SSL_SSL; } rc = SSL_connect(ssl); if (rc <= 0) { error_status(conf, "Failed to connect SSL"); return ERR_SSL_SSL; } conn->ssl = ssl; conn->sockfd = sock; conn->used = true; conf->s.conn = conn; update_status(conf, "Connected"); return 0; } void tls_cleanup(struct connection *conn) { if (conn->sockfd) { shutdown(conn->sockfd, SHUT_RDWR); close(conn->sockfd); } if (conn->ssl) { SSL_shutdown(conn->ssl); SSL_CTX_free(SSL_get_SSL_CTX(conn->ssl)); SSL_free(conn->ssl); } free(conn); } struct connection *init_connection(void) { struct connection *conn = malloc(sizeof(struct connection)); memset(conn, 0, sizeof(struct connection)); return conn; }