#include "ssl.h"
#include "err.h"
#include "pem.h"

SSL_CTX            *ssl_ctx = NULL;
SSL                *ssl_conn = NULL;
SSL                *ssl_con1 = NULL;

int                 certverify(int ok, X509 * subc, X509 * issc, int depth, int err)
{
	char               *cp;
	char                cbuf[255];
	FILE               *tmpfd = NULL;

	cp = X509_NAME_oneline(X509_get_subject_name(subc));
	strncpy(thisuser, cp, 255);
	free(cp);
	if (ok && depth == 0) {
		if (askuser[curcon]) {
			if (askuser[curcon] == 2 && (tmpfd = fopen(usercerts, "a"))) {	/* save certs */
				PEM_write_X509(tmpfd, subc);
				fclose(tmpfd);
			}
			else if (askuser[curcon] == 3 && !usermatch(thisuser))	/* verify user cert against file */
				ok = 0;
		}
		if (reverse[curcon] && !namematch(thisuser, hostname)) {	/* proxy SSL to remote secure server - verify server host */
			sprintf(error, "Host:%s != Cert:%s", hostname, thisuser);
			fprintf(stderr, "ERROR: Hostname [%s] does not match Name in cert\n", hostname);
			ok = 0;
		}
	}
	if (!debugflag && ok == 1 && err < 2)
		return (ok);
	fprintf(stderr, "SSL CERTIFICATE STATUS: ok=%d depth=%d err=%s\n", ok, depth, X509_cert_verify_error_string(err));
	if (issc)
		fprintf(stderr, "Issuer Oneline:\n%s\n", cp = X509_NAME_oneline(X509_get_issuer_name(issc))), free(cp);
	fprintf(stderr, "Subject Cert Oneline:\n%s %s\n", thisuser, hostname);
	strcpy(cbuf, subc->cert_info->validity->notBefore);
	fprintf(stderr, "Valid From: %2.2s/%2.2s/%2.2s %2.2s:%2.2s:%2.2s %s\n", cbuf, &cbuf[2], &cbuf[4], &cbuf[6], &cbuf[8], &cbuf[10], &cbuf[12]);
	strcpy(cbuf, subc->cert_info->validity->notAfter);
	fprintf(stderr, "     Until: %2.2s/%2.2s/%2.2s %2.2s:%2.2s:%2.2s %s\n", cbuf, &cbuf[2], &cbuf[4], &cbuf[6], &cbuf[8], &cbuf[10], &cbuf[12]);
	fprintf(stderr, "\n");
	if (askuser[curcon] == 1)
		return 1;	/* force good user cert */
	else
		return (ok);
}

void                prefix()
{
	if (ssl_ctx != NULL)
		return;
	ssl_ctx = SSL_CTX_new();
	X509_set_default_verify_paths(ssl_ctx->cert);
	SSL_load_error_strings();
}

int                 fixconn(int conn, char *certfile, int fd, int verflag, int conacpt)
{
	SSL                *scon;
	char                ebuf[256];
	int                 n;

	scon = SSL_new(ssl_ctx);
	SSL_use_certificate_file(scon, certfile, SSL_FILETYPE_PEM);
	SSL_use_RSAPrivateKey_file(scon, certfile, SSL_FILETYPE_PEM);
	SSL_set_fd(scon, fd);
	SSL_set_verify(scon, verflag | conacpt ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, certverify);
	n = (conacpt ? SSL_connect(scon) : SSL_accept(scon));
	if (n < 0)
		sprintf(&error[strlen(error)], "SSL connection: %d %s\n", n, ERR_error_string(ERR_get_error(), ebuf));
	else if (debugflag)
		fprintf(stderr, "Using cipher %s to %s\n", SSL_get_cipher(scon), conn ? "browser" : "server");
	if (conn)
		ssl_con1 = scon;
	else
		ssl_conn = scon;
	return n;
}
#define remote_write(a,b,c) SSL_write(a?ssl_con1:ssl_conn,b,c)
#define remote_read(a,b,c) SSL_read(a?ssl_con1:ssl_conn,b,c)
