struct tls_config * https_init(void) { struct tls_config *tls_config; char *str; int depth; uint32_t http_tls_protocols; const char *errstr; if (tls_init() != 0) errx(1, "tls init failed"); if ((tls_config = tls_config_new()) == NULL) errx(1, "tls config_new failed"); tls_config_set_protocols(tls_config, TLS_PROTOCOLS_ALL); if (tls_config_set_ciphers(tls_config, "compat") != 0) errx(1, "tls set ciphers failed"); if (tls_options == NULL) return tls_config; while (*tls_options) { switch (getsubopt(&tls_options, tls_verify_opts, &str)) { case HTTP_TLS_CAFILE: if (str == NULL) errx(1, "missing CA file"); if (tls_config_set_ca_file(tls_config, str) != 0) errx(1, "tls ca file failed"); break; case HTTP_TLS_CAPATH: if (str == NULL) errx(1, "missing ca path"); if (tls_config_set_ca_path(tls_config, str) != 0) errx(1, "tls ca path failed"); break; case HTTP_TLS_CIPHERS: if (str == NULL) errx(1, "missing cipher list"); if (tls_config_set_ciphers(tls_config, str) != 0) errx(1, "tls set ciphers failed"); break; case HTTP_TLS_DONTVERIFY: tls_config_insecure_noverifycert(tls_config); tls_config_insecure_noverifyname(tls_config); break; case HTTP_TLS_PROTOCOLS: if (tls_config_parse_protocols(&http_tls_protocols, str) != 0) errx(1, "tls parsing protocols failed"); tls_config_set_protocols(tls_config, http_tls_protocols); break; case HTTP_TLS_VERIFYDEPTH: if (str == NULL) errx(1, "missing depth"); depth = strtonum(str, 0, INT_MAX, &errstr); if (errstr) errx(1, "Cert validation depth is %s", errstr); tls_config_set_verify_depth(tls_config, depth); break; default: errx(1, "Unknown -S suboption `%s'", suboptarg ? suboptarg : ""); } } return tls_config; }
static const char *create_worker(struct Worker **w_p, bool is_server, ...) { va_list ap; const char *k, *v; int klen; struct Worker *w; int err; const char *mem = NULL; void *fdata; size_t flen; const char *errmsg = NULL; *w_p = NULL; w = calloc(1, sizeof *w); if (!w) return "calloc"; w->wstate = HANDSHAKE; w->is_server = is_server; w->config = tls_config_new(); if (!w->config) return "tls_config_new failed"; if (is_server) { w->base = tls_server(); if (!w->base) return "tls_server failed"; } else { w->ctx = tls_client(); if (!w->ctx) return "tls_client failed"; } va_start(ap, is_server); while (1) { k = va_arg(ap, char *); if (!k) break; v = strchr(k, '='); if (!v) { errmsg = k; break; } v++; klen = v - k; err = 0; if (!strncmp(k, "mem=", klen)) { mem = v; } else if (!strncmp(k, "ca=", klen)) { if (mem) { fdata = load_file(v, &flen); if (!fdata) { errmsg = strerror(errno); break; } err = tls_config_set_ca_mem(w->config, fdata, flen); free(fdata); } else { err = tls_config_set_ca_file(w->config, v); } } else if (!strncmp(k, "cert=", klen)) { if (mem) { fdata = load_file(v, &flen); if (!fdata) { errmsg = strerror(errno); break; } err = tls_config_set_cert_mem(w->config, fdata, flen); free(fdata); } else { err = tls_config_set_cert_file(w->config, v); } } else if (!strncmp(k, "key=", klen)) { if (mem) { fdata = load_file(v, &flen); if (!fdata) { errmsg = strerror(errno); break; } err = tls_config_set_key_mem(w->config, fdata, flen); free(fdata); } else { err = tls_config_set_key_file(w->config, v); } } else if (!strncmp(k, "show=", klen)) { w->show = v; } else if (!strncmp(k, "ciphers=", klen)) { err = tls_config_set_ciphers(w->config, v); } else if (!strncmp(k, "host=", klen)) { w->hostname = v; } else if (!strncmp(k, "noverifycert=", klen)) { tls_config_insecure_noverifycert(w->config); } else if (!strncmp(k, "noverifyname=", klen)) { tls_config_insecure_noverifyname(w->config); } else if (!strncmp(k, "verify=", klen)) { tls_config_verify(w->config); } else if (!strncmp(k, "dheparams=", klen)) { err = tls_config_set_dheparams(w->config, v); } else if (!strncmp(k, "ecdhecurve=", klen)) { err = tls_config_set_ecdhecurve(w->config, v); } else if (!strncmp(k, "protocols=", klen)) { uint32_t protos; err = tls_config_parse_protocols(&protos, v); tls_config_set_protocols(w->config, protos); } else if (!strncmp(k, "peer-sha1=", klen)) { w->peer_fingerprint_sha1 = v; } else if (!strncmp(k, "peer-sha256=", klen)) { w->peer_fingerprint_sha256 = v; } else if (!strncmp(k, "verify-client=", klen)) { tls_config_verify_client(w->config); } else if (!strncmp(k, "verify-client-optional=", klen)) { tls_config_verify_client_optional(w->config); } else if (!strncmp(k, "aggressive-close=", klen)) { w->aggressive_close = 1; } else { errmsg = k; break; } if (err < 0) { errmsg = k; break; } } va_end(ap); if (errmsg) return errmsg; if (is_server) { if (tls_configure(w->base, w->config) < 0) return tls_error(w->base); } else { if (tls_configure(w->ctx, w->config) < 0) return tls_error(w->ctx); } *w_p = w; return "OK"; }
int main(int argc, char **argv) { struct tls_config *config = NULL; struct tls *tls = NULL; unsigned int protocols = 0; struct sockaddr_in server, client; int sock = socket(AF_INET, SOCK_STREAM, 0); int opt = 1; int b; struct tls *tls2 = NULL; ssize_t outlen = 0; char bufs[1000], bufc[1000]; int sc; char *msg = "HELLO TLS CLIENT\n"; char *ciphers = "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384"; struct pollfd pfd[2]; if(tls_init() < 0) { printf("tls_init error\n"); exit(1); } config = tls_config_new(); if(config == NULL) { printf("tls_config_new error\n"); exit(1); } tls = tls_server(); if(tls == NULL) { printf("tls_server error\n"); exit(1); } if(tls_config_parse_protocols(&protocols, "secure") < 0) { printf("tls_config_parse_protocols error\n"); exit(1); } tls_config_set_protocols(config, protocols); if(tls_config_set_ciphers(config, ciphers) < 0) { printf("tls_config_set_ciphers error\n"); exit(1); } if(tls_config_set_key_file(config, "private.pem") < 0) { printf("tls_config_set_key_file error\n"); exit(1); } if(tls_config_set_cert_file(config, "server.crt") < 0) { printf("tls_config_set_cert_file error\n"); exit(1); } if(tls_configure(tls, config) < 0) { printf("tls_configure error: %s\n", tls_error(tls)); exit(1); } bzero(&server, sizeof(server)); server.sin_addr.s_addr = inet_addr("127.0.0.1"); server.sin_port = htons(9000); server.sin_family = AF_INET; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, 4); b = bind(sock, (struct sockaddr *) &server, sizeof(server)); if(b < 0) { printf("erro bind\n"); exit(1); } listen(sock, 10); socklen_t client_size = sizeof(client); sc = accept(sock, (struct sockaddr *) &client, &client_size); if(tls_accept_socket(tls, &tls2, sc) < 0) { printf("tls_accept_socket error\n"); exit(1); } tls_write(tls2, msg, strlen(msg)); pfd[0].fd = 0; pfd[0].events = POLLIN; pfd[1].fd = sc; pfd[1].events = POLLIN; while(bufc[0] != ':' && bufc[1] != 'q') { poll(pfd, 2, -1); bzero(bufs, 1000); bzero(bufc, 1000); if(pfd[0].revents & POLLIN) { int q = read(0, bufc, 1000); tls_write(tls2, bufc, q); } if(pfd[1].revents & POLLIN) { if((outlen = tls_read(tls2, bufs, 1000)) <= 0) break; printf("Mensagem (%lu): %s\n", outlen, bufs); } } tls_close(tls); tls_free(tls); tls_config_free(config); return 0; }