#include "certtool-common.h"
#include "socket.h"
-static const char* obtain_cert(const char *hostname, const char *proto, unsigned int port, unsigned quiet);
+static const char* obtain_cert(const char *hostname, const char *proto, unsigned int port,
+ const char *app_proto, unsigned quiet);
static void cmd_parser(int argc, char **argv);
static void dane_info(const char *host, const char *proto,
unsigned int port, unsigned int ca,
int *dane_data_len;
int secure;
int bogus;
-
+
ret = dane_query_to_raw_tlsa(q, &entries, &dane_data,
&dane_data_len, &secure, &bogus);
if (ret < 0) {
fprintf(outfile,
"_%u._%s.%s. IN TLSA ( %.2x %.2x %.2x %s )\n",
port, proto, host, usage, type, match, lbuffer);
-
+
if (!HAVE_OPT(QUIET)) {
str = dane_cert_usage_name(usage);
if (str == NULL) str= "Unknown";
}
if (!cinfo->cert) {
- cinfo->cert = obtain_cert(host, proto, port, HAVE_OPT(QUIET));
+ const char *app_proto = NULL;
+ if (HAVE_OPT(APP_PROTO))
+ app_proto = OPT_ARG(APP_PROTO);
+
+ cinfo->cert = obtain_cert(host, proto, port, app_proto, HAVE_OPT(QUIET));
del = 1;
}
gnutls_transport_set_int(session, hd->fd);
gnutls_set_default_priority(session);
- gnutls_server_name_set(session, GNUTLS_NAME_DNS, hostname, strlen(hostname));
+ if (hostname && !isdigit(hostname[0])) {
+ gnutls_server_name_set(session, GNUTLS_NAME_DNS, hostname, strlen(hostname));
+ }
gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred);
do {
return 0;
}
-static const char *obtain_cert(const char *hostname, const char *proto, unsigned port, unsigned quiet)
+static const char *obtain_cert(const char *hostname, const char *proto, unsigned port,
+ const char *app_proto, unsigned quiet)
{
socket_st hd;
char txt_port[16];
static char tmpfile[32];
int fd, ret;
const char *str = "Obtaining certificate from";
+ const char *service;
if (strcmp(proto, "udp") == 0)
udp = 1;
if (quiet)
str = NULL;
- socket_open(&hd, hostname, port_to_service(txt_port, proto), udp, str);
+ service = port_to_service(txt_port, proto);
+ socket_open(&hd, hostname, service, udp, str);
+
+ if (app_proto == NULL) app_proto = service;
+ socket_starttls(&hd, app_proto);
fd = mkstemp(tmpfile);
if (fd == -1) {
return ret;
}
+static
+ssize_t send_line(int fd, const char *txt)
+{
+ int len = strlen(txt);
+ int ret;
+
+ ret = send(fd, txt, len, 0);
+
+ if (ret == -1) {
+ fprintf(stderr, "error sending %s\n", txt);
+ exit(1);
+ }
+
+ return ret;
+}
+
+static
+ssize_t wait_for_text(int fd, const char *txt, unsigned txt_size)
+{
+ char buf[256];
+ int ret;
+
+ alarm(10);
+ do {
+ ret = recv(fd, buf, sizeof(buf), 0);
+ if (ret == -1) {
+ fprintf(stderr, "error receiving %s\n", txt);
+ exit(1);
+ }
+ } while(ret < (int)txt_size || strncmp(buf, txt, txt_size) != 0);
+
+ alarm(0);
+
+ return ret;
+}
+
+void
+socket_starttls(socket_st * socket, const char *app_proto)
+{
+ if (socket->secure)
+ return;
+
+ if (app_proto == NULL || strcasecmp(app_proto, "https") == 0)
+ return;
+
+ if (strcasecmp(app_proto, "smtp") == 0) {
+ send_line(socket->fd, "EHLO mail.example.com\n");
+ wait_for_text(socket->fd, "220 ", 4);
+ send_line(socket->fd, "STARTTLS\n");
+ wait_for_text(socket->fd, "220 ", 4);
+ } else {
+ fprintf(stderr, "unknown protocol %s\n", app_proto);
+ }
+
+ return;
+}
+
void socket_bye(socket_st * socket)
{
int ret;