rp

simple email tools
git clone https://git.parazyd.org/rp
Log | Files | Refs | README | LICENSE

commit a5ffe13b1502e01adb7da16b879eb99e3c55d49d
parent d6b9c4355d3a6e4cd4d1e0f58ad3b26d10144728
Author: parazyd <parazyd@dyne.org>
Date:   Thu,  1 Mar 2018 00:47:39 +0100

Add net functionality.

Currently supports fetching a TLS certificate fingerprint.

Diffstat:
MMakefile | 2+-
Mconfig.mk | 6++++--
Anet.c | 164+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Anet.h | 24++++++++++++++++++++++++
Mrohrpost.c | 2++
5 files changed, 195 insertions(+), 3 deletions(-)

diff --git a/Makefile b/Makefile @@ -5,7 +5,7 @@ include config.mk BIN = $(NAME) -OBJ = $(BIN:=.o) headers.o ind.o sieve.o +OBJ = $(BIN:=.o) headers.o ind.o sieve.o net.o all: $(BIN) cp -f $(NAME) bin diff --git a/config.mk b/config.mk @@ -5,8 +5,10 @@ PREFIX = /usr/local SHAREPREFIX = $(PREFIX)/share/$(NAME) MANPREFIX = $(PREFIX)/share/man -CFLAGS = -O2 -Wall -pedantic -LDFLAGS = -static -s +CFLAGS = -O2 -Wall -pedantic -std=gnu99 +LDFLAGS = -static -s -lssl -lcrypto .c.o: $(CC) $(CFLAGS) -c $< + +CC = cc diff --git a/net.c b/net.c @@ -0,0 +1,164 @@ +/* + * Copy me if you can + * by 20h and parazyd + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <netdb.h> + +#include <openssl/ssl.h> +#include <openssl/err.h> +#include <openssl/x509.h> + +#include "arg.h" +#include "ind.h" +#include "net.h" + +char *argv0; + +/* + * net format: + * net!addr!service + */ +enum { + NET_NET = 0x00, + NET_TCP, + NET_TCPS +}; + +static char *netnames[] = { + [NET_NET] = "net", + [NET_TCP] = "tcp", + [NET_TCPS] = "tcps" +}; + +void netusage(void) { + die("usage: %s [-f host port]\n" + " -f: fetch and print ssl certificate fingerprint\n", argv0); +} + +int net_gettype(char *str) { + int i; + + for (i = 0; i < nelem(netnames); i++) + if (!strcmp(netnames[i], str)) + return i; + return -1; +} + +net_t *net_new(char *type, char *addr, char *port) { + net_t *ret; + + ret = malloc(sizeof(net_t)); + + ret->type = net_gettype(type); + ret->addr = addr; + ret->service = port; + + return ret; +} + +int sslfpr(net_t *net) { + int i; + unsigned int fpr_size; + SSL *sfd; + X509 *cert; + + const EVP_MD *fpr_type; + unsigned char fpr[EVP_MAX_MD_SIZE]; + + struct addrinfo hints, *ai, *rp; + + bzero(&hints, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + + if (getaddrinfo(net->addr, net->service, &hints, &ai)) + return 1; + if (ai == NULL) + return 1; + + SSL_library_init(); + OpenSSL_add_all_algorithms(); + + net->data[1] = SSL_CTX_new(SSLv23_client_method()); + if (net->data[1] == NULL) + goto sslfprerr; + SSL_CTX_set_options((SSL_CTX *)net->data[1], + SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3); + + for (rp = ai; rp != NULL; rp = rp->ai_next) { + net->fd = socket(rp->ai_family, rp->ai_socktype, + rp->ai_protocol); + if (connect(net->fd, rp->ai_addr, rp->ai_addrlen)) + break; + + if ((sfd = SSL_new((SSL_CTX *)net->data[1])) == NULL) + goto sslfprerr; + SSL_set_fd(sfd, net->fd); + if (SSL_connect(sfd) < 1) + goto sslfprerr; + + + cert = SSL_get_peer_certificate(sfd); + if (cert == NULL) + goto sslfprerr; + + fpr_type = EVP_sha1(); + if (!X509_digest(cert, fpr_type, fpr, &fpr_size)) + goto sslfprerr; + + for (i = 0; i < fpr_size; i++) + printf("%02X%c", fpr[i], (i+1 == fpr_size) ? '\n':':'); + + X509_free(cert); + SSL_CTX_free(net->data[1]); + SSL_free(sfd); + EVP_cleanup(); + CRYPTO_cleanup_all_ex_data(); + close(net->fd); + } + + return 0; + +sslfprerr: + SSL_load_error_strings(); + ERR_print_errors_fp(stderr); + ERR_free_strings(); + return 1; +} + +int netmain(int argc, char *argv[]) { + + int fflag; + + ARGBEGIN { + case 'f': + fflag = 1; + argc++; argv--; + break; + default: + netusage(); + } ARGEND; + + if (fflag) { + if (argc < 2) + netusage(); + + net_t *net; + + net = net_new("tcps", argv[1], argv[2]); + if (sslfpr(net)) + return 1; + + return 0; + } + + netusage(); + + return 0; +} diff --git a/net.h b/net.h @@ -0,0 +1,24 @@ +/* + * Copy me if you can + * by parazyd + */ + +#ifndef __RPNET_H__ +#define __RPNET_H__ + +typedef struct net_t net_t; +struct net_t { + int fd; + + char *net; + char *addr; + char *service; + char *options; + int type; + + void *data[2]; +}; + +int netmain(int argc, char *argv[]); + +#endif diff --git a/rohrpost.c b/rohrpost.c @@ -10,6 +10,7 @@ #include "arg.h" #include "headers.h" #include "ind.h" +#include "net.h" #include "sieve.h" char *argv0; @@ -33,6 +34,7 @@ enum { struct command cmds[] = { {"rpheaders", DOINSTALL, headersmain}, {"rpsieve", DONTINSTALL, sievemain}, + {"rpnet", DOINSTALL, netmain}, }; int main(int argc, char *argv[]) {