This repository has been archived on 2023-10-10. You can view files and clone it, but cannot push or open issues/pull-requests.
hackfridge/terminal/network.c

113 lines
2.9 KiB
C

// heavily copypasted from http://www.rtfm.com/openssl-examples/
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include "config.h"
size_t strnlen(const char *s, size_t maxlen);
static char id_ctx[] = "hackfridge-ssl-context";
int pem_passwd_cb(char *buf, int size, int rwflag, void *userdata) {
strncpy(buf, userdata, size);
return strlen(userdata);
}
int initialize_ctx(const char* chainfile, const char* keyfile, const char* password,
const char* ca_file, SSL_CTX** rctx)
{
const SSL_METHOD *meth;
SSL_CTX* ctx;
int result = 1;
/* Create our context*/
meth=TLSv1_client_method();
ctx=SSL_CTX_new(meth);
if (!ctx)
{
ERR_print_errors_fp(stderr);
return -1;
}
/* Load our keys and certificates*/
result = SSL_CTX_use_certificate_chain_file(ctx, chainfile);
if(!result) goto exit;
SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_cb);
SSL_CTX_set_default_passwd_cb_userdata(ctx, (void*) password);
result = SSL_CTX_use_PrivateKey_file(ctx, keyfile, SSL_FILETYPE_PEM);
if(!result) goto finalize;
/* Load the CAs we trust*/
result = SSL_CTX_load_verify_locations(ctx, ca_file,0);
if(!result) goto finalize;
goto exit;
finalize:
SSL_CTX_free(ctx);
exit:
*rctx = ctx;
return result;
}
int send_purchase(const char* host, int port, const char* code, const char* dn) {
SSL_CTX* ctx;
BIO* bio;
SSL* ssl;
int result, sock, conn;
char msg[200];
*msg = 0;
result = initialize_ctx(SSL_CERT, SSL_CERT_KEY, SSL_PASSWORD, CA_FILE, &ctx);
if(!result) return result; // :(
SSL_CTX_set_session_id_context(ctx, id_ctx, sizeof id_ctx);
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
struct hostent *hp;
if(!(hp = gethostbyname(host))) {
result = -2;
goto finalize;
}
addr.sin_addr = *(struct in_addr*)hp->h_addr_list[0];
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
result = -3;
if(sock < 0) goto finalize;
result = connect(sock, (struct sockaddr*) &addr, sizeof(addr));
if(result < 0) goto close_socket;
ssl = SSL_new(ctx);
bio = BIO_new_socket(sock, BIO_NOCLOSE);
if(!bio) {
result = -4;
goto free_ssl;
}
SSL_set_bio(ssl, bio, bio);
result = SSL_connect(ssl);
if(result < 0) goto free_ssl;
strncat(msg, code, 200);
strncat(msg, " ", 200);
strncat(msg, dn, 200);
strncat(msg, "\n", 200);
int pending = strnlen(msg, 200);
char* t_msg = msg;
while(pending > 0) {
result = SSL_write(ssl, t_msg, pending);
if(result == 0) result = SSL_get_error(ssl, result); // :(
if(result < 0) goto free_ssl;
pending -= result;
t_msg += result;
}
SSL_shutdown(ssl);
free_ssl:
SSL_free(ssl);
close_socket:
close(sock);
finalize:
SSL_CTX_free(ctx);
return result;
}