diff options
author | Martin Schanzenbach <mschanzenbach@posteo.de> | 2012-06-06 16:22:53 +0000 |
---|---|---|
committer | Martin Schanzenbach <mschanzenbach@posteo.de> | 2012-06-06 16:22:53 +0000 |
commit | d1e93089ddeb129ed8d37c55996959eb3dcad11c (patch) | |
tree | 73e04ccc9bd0f12d24e372c9d0c04f2251671746 | |
parent | 2e032226d7571e9349735733dd195cac9da3d43a (diff) | |
download | gnunet-d1e93089ddeb129ed8d37c55996959eb3dcad11c.tar.gz gnunet-d1e93089ddeb129ed8d37c55996959eb3dcad11c.zip |
-on the fly cert generation
-rw-r--r-- | src/gns/Makefile.am | 2 | ||||
-rw-r--r-- | src/gns/gnunet-gns-proxy.c | 231 |
2 files changed, 219 insertions, 14 deletions
diff --git a/src/gns/Makefile.am b/src/gns/Makefile.am index 277d5e323..2991bd0c8 100644 --- a/src/gns/Makefile.am +++ b/src/gns/Makefile.am | |||
@@ -207,7 +207,7 @@ gnunet_gns_DEPENDENCIES = \ | |||
207 | 207 | ||
208 | gnunet_gns_proxy_SOURCES = \ | 208 | gnunet_gns_proxy_SOURCES = \ |
209 | gnunet-gns-proxy.c gns_proxy_proto.h | 209 | gnunet-gns-proxy.c gns_proxy_proto.h |
210 | gnunet_gns_proxy_LDADD = -lmicrohttpd -lcurl \ | 210 | gnunet_gns_proxy_LDADD = -lmicrohttpd -lcurl -lssl \ |
211 | $(top_builddir)/src/gns/libgnunetgns.la \ | 211 | $(top_builddir)/src/gns/libgnunetgns.la \ |
212 | $(top_builddir)/src/util/libgnunetutil.la \ | 212 | $(top_builddir)/src/util/libgnunetutil.la \ |
213 | $(GN_LIBINTL) | 213 | $(GN_LIBINTL) |
diff --git a/src/gns/gnunet-gns-proxy.c b/src/gns/gnunet-gns-proxy.c index 3c6943687..ab99f4596 100644 --- a/src/gns/gnunet-gns-proxy.c +++ b/src/gns/gnunet-gns-proxy.c | |||
@@ -27,6 +27,14 @@ | |||
27 | #include "gns_proxy_proto.h" | 27 | #include "gns_proxy_proto.h" |
28 | #include "gns.h" | 28 | #include "gns.h" |
29 | 29 | ||
30 | /** SSL **/ | ||
31 | #include <openssl/pem.h> | ||
32 | #include <openssl/conf.h> | ||
33 | #include <openssl/x509v3.h> | ||
34 | #include <openssl/ssl.h> | ||
35 | #include <openssl/err.h> | ||
36 | #include <openssl/rand.h> | ||
37 | |||
30 | #define GNUNET_GNS_PROXY_PORT 7777 | 38 | #define GNUNET_GNS_PROXY_PORT 7777 |
31 | 39 | ||
32 | /* MHD/cURL defines */ | 40 | /* MHD/cURL defines */ |
@@ -43,6 +51,31 @@ | |||
43 | #define HTTPS_PORT 443 | 51 | #define HTTPS_PORT 443 |
44 | 52 | ||
45 | 53 | ||
54 | /** | ||
55 | * A structure for CA cert/key | ||
56 | */ | ||
57 | struct ProxyCA | ||
58 | { | ||
59 | /* The certificate */ | ||
60 | X509* cert; | ||
61 | |||
62 | /* The private key */ | ||
63 | EVP_PKEY *key; | ||
64 | }; | ||
65 | |||
66 | |||
67 | /** | ||
68 | * Structure for GNS certificates | ||
69 | */ | ||
70 | struct ProxyGNSCertificate | ||
71 | { | ||
72 | /* The certificate */ | ||
73 | X509* cert; | ||
74 | |||
75 | /* The private key */ | ||
76 | EVP_PKEY *key; | ||
77 | }; | ||
78 | |||
46 | 79 | ||
47 | /** | 80 | /** |
48 | * A structure for socks requests | 81 | * A structure for socks requests |
@@ -188,7 +221,10 @@ struct ProxyCurlTask | |||
188 | }; | 221 | }; |
189 | 222 | ||
190 | /* The port the proxy is running on (default 7777) */ | 223 | /* The port the proxy is running on (default 7777) */ |
191 | unsigned long port = GNUNET_GNS_PROXY_PORT; | 224 | static unsigned long port = GNUNET_GNS_PROXY_PORT; |
225 | |||
226 | /* The CA file (pem) to use for the proxy CA */ | ||
227 | static char* cafile; | ||
192 | 228 | ||
193 | /* The listen socket of the proxy */ | 229 | /* The listen socket of the proxy */ |
194 | static struct GNUNET_NETWORK_Handle *lsock; | 230 | static struct GNUNET_NETWORK_Handle *lsock; |
@@ -226,6 +262,9 @@ static regex_t re_dotplus; | |||
226 | /* The users local GNS zone hash */ | 262 | /* The users local GNS zone hash */ |
227 | struct GNUNET_CRYPTO_ShortHashCode local_gns_zone; | 263 | struct GNUNET_CRYPTO_ShortHashCode local_gns_zone; |
228 | 264 | ||
265 | /* The CA for SSL certificate generation */ | ||
266 | struct ProxyCA *proxy_ca; | ||
267 | |||
229 | /** | 268 | /** |
230 | * Checks if name is in tld | 269 | * Checks if name is in tld |
231 | * | 270 | * |
@@ -1021,9 +1060,6 @@ create_response (void *cls, | |||
1021 | char curlurl[512]; | 1060 | char curlurl[512]; |
1022 | int ret = MHD_YES; | 1061 | int ret = MHD_YES; |
1023 | 1062 | ||
1024 | struct hostent *phost; | ||
1025 | char *ssl_ip; | ||
1026 | |||
1027 | struct ProxyCurlTask *ctask; | 1063 | struct ProxyCurlTask *ctask; |
1028 | 1064 | ||
1029 | if (0 != strcmp (meth, "GET")) | 1065 | if (0 != strcmp (meth, "GET")) |
@@ -1474,6 +1510,148 @@ load_file (const char* filename) | |||
1474 | return buffer; | 1510 | return buffer; |
1475 | } | 1511 | } |
1476 | 1512 | ||
1513 | /** SSL stuff **/ | ||
1514 | |||
1515 | /** | ||
1516 | * Get authority from file | ||
1517 | */ | ||
1518 | static X509* | ||
1519 | load_cert_from_file (char* file) | ||
1520 | { | ||
1521 | SSL_CTX *context = NULL;; | ||
1522 | |||
1523 | context = SSL_CTX_new (SSLv23_server_method ()); | ||
1524 | |||
1525 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1526 | "Reading cert file %s\n", file); | ||
1527 | |||
1528 | SSL_CTX_use_certificate_file (context, file, SSL_FILETYPE_PEM); | ||
1529 | |||
1530 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1531 | "Extracting\n"); | ||
1532 | |||
1533 | return SSL_get_certificate (SSL_new (context)); | ||
1534 | |||
1535 | } | ||
1536 | |||
1537 | |||
1538 | /** | ||
1539 | * Get authority from file | ||
1540 | */ | ||
1541 | static struct ProxyCA* | ||
1542 | load_authority_from_file (char* file) | ||
1543 | { | ||
1544 | struct ProxyCA *ca = NULL; | ||
1545 | SSL_CTX *context; | ||
1546 | |||
1547 | ca = GNUNET_malloc (sizeof (struct ProxyCA)); | ||
1548 | |||
1549 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1550 | "Reading cert file %s\n", file); | ||
1551 | ca->cert = load_cert_from_file (file); | ||
1552 | |||
1553 | context = SSL_CTX_new (SSLv23_server_method ()); | ||
1554 | |||
1555 | SSL_CTX_use_PrivateKey_file (context, file, SSL_FILETYPE_PEM); | ||
1556 | |||
1557 | ca->key = SSL_get_privatekey (SSL_new (context)); | ||
1558 | |||
1559 | return ca; | ||
1560 | |||
1561 | } | ||
1562 | |||
1563 | |||
1564 | |||
1565 | static unsigned int | ||
1566 | generate_serial () | ||
1567 | { | ||
1568 | unsigned int serial; | ||
1569 | RAND_bytes ((unsigned char*)&serial, sizeof (serial)); | ||
1570 | |||
1571 | return serial; | ||
1572 | } | ||
1573 | |||
1574 | |||
1575 | /* The template certificate file */ | ||
1576 | char* template_cert_file; | ||
1577 | |||
1578 | /* The template certificate */ | ||
1579 | X509 *template_certificate; | ||
1580 | |||
1581 | |||
1582 | /** | ||
1583 | * Generate new certificate for specific name | ||
1584 | * | ||
1585 | */ | ||
1586 | static struct ProxyGNSCertificate* | ||
1587 | generate_gns_certificate (const char *name, char *keyfilename, char *certfilename) | ||
1588 | { | ||
1589 | X509_NAME *server_name = X509_get_subject_name (template_certificate); | ||
1590 | X509_NAME *issuer_name = X509_get_subject_name (proxy_ca->cert); | ||
1591 | X509 *request = X509_new (); | ||
1592 | int cn_nid = OBJ_txt2nid("CN"); | ||
1593 | int cn_idx = X509_NAME_get_index_by_NID(server_name, cn_nid, -1); | ||
1594 | RSA *rsa = RSA_generate_key (1024, RSA_F4, NULL, NULL); | ||
1595 | EVP_PKEY *rsa_spec = EVP_PKEY_new(); | ||
1596 | FILE* keyfile; | ||
1597 | FILE* certfile; | ||
1598 | |||
1599 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Generating key\n"); | ||
1600 | |||
1601 | EVP_PKEY_assign_RSA (rsa_spec, rsa); | ||
1602 | |||
1603 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Generating cert\n"); | ||
1604 | |||
1605 | struct ProxyGNSCertificate *pgc = | ||
1606 | GNUNET_malloc (sizeof (struct ProxyGNSCertificate)); | ||
1607 | |||
1608 | X509_NAME_delete_entry (server_name, cn_idx); | ||
1609 | |||
1610 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding name\n"); | ||
1611 | if (!X509_NAME_add_entry_by_txt (server_name, "CN", | ||
1612 | MBSTRING_UTF8, (const unsigned char*)name, | ||
1613 | -1, -1, 0)) | ||
1614 | { | ||
1615 | return NULL; | ||
1616 | } | ||
1617 | |||
1618 | X509_set_version(request, 3); | ||
1619 | X509_set_subject_name(request, server_name); | ||
1620 | X509_set_issuer_name(request, issuer_name); | ||
1621 | |||
1622 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Signing\n"); | ||
1623 | ASN1_INTEGER_set(X509_get_serialNumber(request), generate_serial()); | ||
1624 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Signing\n"); | ||
1625 | X509_gmtime_adj(X509_get_notBefore(request), -365); | ||
1626 | X509_gmtime_adj(X509_get_notAfter(request), (long)60*60*24*365); | ||
1627 | X509_set_pubkey(request, rsa_spec); | ||
1628 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Signing %d\n", proxy_ca->key); | ||
1629 | X509_sign(request, proxy_ca->key, EVP_sha1()); | ||
1630 | |||
1631 | pgc->cert = request; | ||
1632 | pgc->key = rsa_spec; | ||
1633 | |||
1634 | |||
1635 | |||
1636 | keyfile = fopen (keyfilename, "w+"); | ||
1637 | certfile = fopen (certfilename, "w+"); | ||
1638 | |||
1639 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Writing to file %d\n", rsa_spec); | ||
1640 | PEM_write_PrivateKey (keyfile, rsa_spec, | ||
1641 | NULL, NULL, 0, NULL, NULL); | ||
1642 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Writing to file %d\n", request); | ||
1643 | PEM_write_X509 (certfile, request); | ||
1644 | |||
1645 | fclose (keyfile); | ||
1646 | fclose (certfile); | ||
1647 | |||
1648 | return pgc; | ||
1649 | |||
1650 | } | ||
1651 | |||
1652 | |||
1653 | |||
1654 | |||
1477 | /** | 1655 | /** |
1478 | * Adds a socket to an SSL MHD instance | 1656 | * Adds a socket to an SSL MHD instance |
1479 | * It is important the the domain name is | 1657 | * It is important the the domain name is |
@@ -1484,11 +1662,18 @@ add_handle_to_ssl_mhd (struct GNUNET_NETWORK_Handle *h, char* domain) | |||
1484 | { | 1662 | { |
1485 | struct MhdHttpList *hd = NULL; | 1663 | struct MhdHttpList *hd = NULL; |
1486 | 1664 | ||
1487 | static char *key_pem; | 1665 | char* key_pem; |
1488 | static char *cert_pem; | 1666 | char* cert_pem; |
1667 | char key_pem_file[1024]; | ||
1668 | char cert_pem_file[1024]; | ||
1489 | 1669 | ||
1490 | key_pem = load_file ("server.key"); | 1670 | sprintf (key_pem_file, "%s.key", domain); |
1491 | cert_pem = load_file ("server.pem"); | 1671 | sprintf (cert_pem_file, "%s.pem", domain); |
1672 | |||
1673 | generate_gns_certificate (domain, key_pem_file, cert_pem_file); | ||
1674 | |||
1675 | key_pem = load_file (key_pem_file); | ||
1676 | cert_pem = load_file (cert_pem_file); | ||
1492 | 1677 | ||
1493 | for (hd = mhd_httpd_head; hd != NULL; hd = hd->next) | 1678 | for (hd = mhd_httpd_head; hd != NULL; hd = hd->next) |
1494 | { | 1679 | { |
@@ -1501,7 +1686,8 @@ add_handle_to_ssl_mhd (struct GNUNET_NETWORK_Handle *h, char* domain) | |||
1501 | /* Start new MHD */ | 1686 | /* Start new MHD */ |
1502 | /* TODO: create cert, start SSL MHD */ | 1687 | /* TODO: create cert, start SSL MHD */ |
1503 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1688 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1504 | "No previous SSL instance found... starting new one\n"); | 1689 | "No previous SSL instance found... starting new one for %s\n", |
1690 | domain); | ||
1505 | hd = GNUNET_malloc (sizeof (struct MhdHttpList)); | 1691 | hd = GNUNET_malloc (sizeof (struct MhdHttpList)); |
1506 | hd->is_ssl = GNUNET_YES; | 1692 | hd->is_ssl = GNUNET_YES; |
1507 | strcpy (hd->domain, domain); | 1693 | strcpy (hd->domain, domain); |
@@ -1898,7 +2084,7 @@ do_shutdown (void *cls, | |||
1898 | 2084 | ||
1899 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 2085 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1900 | "Cleaning up cURL task\n"); | 2086 | "Cleaning up cURL task\n"); |
1901 | 2087 | ||
1902 | if (ctask->curl != NULL) | 2088 | if (ctask->curl != NULL) |
1903 | curl_easy_cleanup (ctask->curl); | 2089 | curl_easy_cleanup (ctask->curl); |
1904 | ctask->curl = NULL; | 2090 | ctask->curl = NULL; |
@@ -1952,7 +2138,7 @@ load_local_zone_key (const struct GNUNET_CONFIGURATION_Handle *cfg) | |||
1952 | struct GNUNET_CRYPTO_ShortHashAsciiEncoded zonename; | 2138 | struct GNUNET_CRYPTO_ShortHashAsciiEncoded zonename; |
1953 | 2139 | ||
1954 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns", | 2140 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns", |
1955 | "ZONEKEY", &keyfile)) | 2141 | "ZONEKEY", &keyfile)) |
1956 | { | 2142 | { |
1957 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 2143 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
1958 | "Unable to load zone key config value!\n"); | 2144 | "Unable to load zone key config value!\n"); |
@@ -1970,8 +2156,8 @@ load_local_zone_key (const struct GNUNET_CONFIGURATION_Handle *cfg) | |||
1970 | key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); | 2156 | key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); |
1971 | GNUNET_CRYPTO_rsa_key_get_public (key, &pkey); | 2157 | GNUNET_CRYPTO_rsa_key_get_public (key, &pkey); |
1972 | GNUNET_CRYPTO_short_hash(&pkey, | 2158 | GNUNET_CRYPTO_short_hash(&pkey, |
1973 | sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), | 2159 | sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), |
1974 | &local_gns_zone); | 2160 | &local_gns_zone); |
1975 | zone = &local_gns_zone; | 2161 | zone = &local_gns_zone; |
1976 | GNUNET_CRYPTO_short_hash_to_enc (zone, &zonename); | 2162 | GNUNET_CRYPTO_short_hash_to_enc (zone, &zonename); |
1977 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 2163 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
@@ -1982,6 +2168,8 @@ load_local_zone_key (const struct GNUNET_CONFIGURATION_Handle *cfg) | |||
1982 | return GNUNET_YES; | 2168 | return GNUNET_YES; |
1983 | } | 2169 | } |
1984 | 2170 | ||
2171 | |||
2172 | |||
1985 | /** | 2173 | /** |
1986 | * Main function that will be run | 2174 | * Main function that will be run |
1987 | * | 2175 | * |
@@ -1997,6 +2185,17 @@ run (void *cls, char *const *args, const char *cfgfile, | |||
1997 | struct sockaddr_in sa; | 2185 | struct sockaddr_in sa; |
1998 | struct MhdHttpList *hd; | 2186 | struct MhdHttpList *hd; |
1999 | 2187 | ||
2188 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2189 | "Loading CA\n"); | ||
2190 | |||
2191 | SSL_library_init (); | ||
2192 | SSL_load_error_strings (); | ||
2193 | proxy_ca = load_authority_from_file (cafile); | ||
2194 | |||
2195 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2196 | "Loading Template\n"); | ||
2197 | template_certificate = load_cert_from_file (template_cert_file); | ||
2198 | |||
2000 | compile_regex (&re_dotplus, (char*) RE_DOTPLUS); | 2199 | compile_regex (&re_dotplus, (char*) RE_DOTPLUS); |
2001 | 2200 | ||
2002 | gns_handle = GNUNET_GNS_connect (cfg); | 2201 | gns_handle = GNUNET_GNS_connect (cfg); |
@@ -2105,6 +2304,12 @@ main (int argc, char *const *argv) | |||
2105 | {'p', "port", NULL, | 2304 | {'p', "port", NULL, |
2106 | gettext_noop ("listen on specified port"), 1, | 2305 | gettext_noop ("listen on specified port"), 1, |
2107 | &GNUNET_GETOPT_set_string, &port}, | 2306 | &GNUNET_GETOPT_set_string, &port}, |
2307 | {'a', "authority", NULL, | ||
2308 | gettext_noop ("pem file to use as CA"), 1, | ||
2309 | &GNUNET_GETOPT_set_string, &cafile}, | ||
2310 | {'t', "template", NULL, | ||
2311 | gettext_noop ("template certificate file to use"), 1, | ||
2312 | &GNUNET_GETOPT_set_string, &template_cert_file}, | ||
2108 | GNUNET_GETOPT_OPTION_END | 2313 | GNUNET_GETOPT_OPTION_END |
2109 | }; | 2314 | }; |
2110 | 2315 | ||