/** * Convert an absolute domain name in the ".zkey" pTLD to the * respective public key. * * @param zkey string "X.zkey" where X is the coordinates of the public * key in an encoding suitable for DNS labels. * @param pkey set to a public key on the eliptic curve * @return #GNUNET_SYSERR if @a zkey has the wrong syntax */ int GNUNET_GNSRECORD_zkey_to_pkey (const char *zkey, struct GNUNET_CRYPTO_EcdsaPublicKey *pkey) { char *cpy; char *dot; const char *x; cpy = GNUNET_strdup (zkey); x = cpy; if (NULL == (dot = strchr (x, (int) '.'))) goto error; *dot = '\0'; if (0 != strcasecmp (dot + 1, "zkey")) goto error; if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_public_key_from_string (x, strlen (x), pkey)) goto error; GNUNET_free (cpy); return GNUNET_OK; error: GNUNET_free (cpy); return GNUNET_SYSERR; }
/** * We got a block back from the namestore. Decrypt it * and continue to process the result. * * @param cls the 'struct Request' we are processing * @param zone private key of the zone; NULL on disconnect * @param label label of the records; NULL on disconnect * @param rd_count number of entries in @a rd array, 0 if label was deleted * @param rd array of records with data to store */ static void lookup_block_processor (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { struct Request *request = cls; request->qe = NULL; if (0 == rd_count) { if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_public_key_from_string (request->public_key, strlen (request->public_key), &request->pub)) { GNUNET_break (0); request->phase = RP_FAIL; run_httpd_now (); return; } request->qe = GNUNET_NAMESTORE_zone_to_name (ns, &fcfs_zone_pkey, &request->pub, &zone_to_name_cb, request); return; } GNUNET_break (0 != rd_count); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Found %u existing records for domain `%s'\n"), rd_count, request->domain_name); request->phase = RP_FAIL; run_httpd_now (); return; }
/** * Function called with the result from the check if the namestore * service is actually running. If it is, we start the actual * operation. * * @param cls closure with our configuration * @param result #GNUNET_YES if the namestore service is running */ static void testservice_task (void *cls, int result) { const struct GNUNET_CONFIGURATION_Handle *cfg = cls; struct GNUNET_CRYPTO_EcdsaPublicKey pub; struct GNUNET_GNSRECORD_Data rd; if (GNUNET_YES != result) { FPRINTF (stderr, _("Service `%s' is not running\n"), "namestore"); return; } if (! (add|del|list|(NULL != nickstring)|(NULL != uri)|(NULL != reverse_pkey)) ) { /* nothing more to be done */ fprintf (stderr, _("No options given\n")); GNUNET_SCHEDULER_shutdown (); return; } GNUNET_CRYPTO_ecdsa_key_get_public (&zone_pkey, &pub); ns = GNUNET_NAMESTORE_connect (cfg); if (NULL == ns) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to connect to namestore\n")); return; } if (add) { if (NULL == name) { fprintf (stderr, _("Missing option `%s' for operation `%s'\n"), "-n", _("add")); GNUNET_SCHEDULER_shutdown (); ret = 1; return; } if (NULL == typestring) { fprintf (stderr, _("Missing option `%s' for operation `%s'\n"), "-t", _("add")); GNUNET_SCHEDULER_shutdown (); ret = 1; return; } type = GNUNET_GNSRECORD_typename_to_number (typestring); if (UINT32_MAX == type) { fprintf (stderr, _("Unsupported type `%s'\n"), typestring); GNUNET_SCHEDULER_shutdown (); ret = 1; return; } if (NULL == value) { fprintf (stderr, _("Missing option `%s' for operation `%s'\n"), "-V", _("add")); ret = 1; GNUNET_SCHEDULER_shutdown (); return; } if (GNUNET_OK != GNUNET_GNSRECORD_string_to_value (type, value, &data, &data_size)) { fprintf (stderr, _("Value `%s' invalid for record type `%s'\n"), value, typestring); GNUNET_SCHEDULER_shutdown (); ret = 1; return; } if (NULL == expirationstring) { fprintf (stderr, _("Missing option `%s' for operation `%s'\n"), "-e", _("add")); GNUNET_SCHEDULER_shutdown (); ret = 1; return; } if (0 == strcmp (expirationstring, "never")) { etime_abs = GNUNET_TIME_UNIT_FOREVER_ABS; etime_is_rel = GNUNET_NO; } else if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative (expirationstring, &etime_rel)) { etime_is_rel = GNUNET_YES; } else if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_absolute (expirationstring, &etime_abs)) { etime_is_rel = GNUNET_NO; } else { fprintf (stderr, _("Invalid time format `%s'\n"), expirationstring); GNUNET_SCHEDULER_shutdown (); ret = 1; return; } add_qe = GNUNET_NAMESTORE_records_lookup (ns, &zone_pkey, name, &get_existing_record, NULL ); } if (del) { if (NULL == name) { fprintf (stderr, _("Missing option `%s' for operation `%s'\n"), "-n", _("del")); GNUNET_SCHEDULER_shutdown (); ret = 1; return; } del_qe = GNUNET_NAMESTORE_records_lookup (ns, &zone_pkey, name, &del_monitor, NULL); } if (list) { list_it = GNUNET_NAMESTORE_zone_iteration_start (ns, &zone_pkey, &display_record, NULL); } if (NULL != reverse_pkey) { struct GNUNET_CRYPTO_EcdsaPublicKey pubkey; if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_public_key_from_string (reverse_pkey, strlen (reverse_pkey), &pubkey)) { fprintf (stderr, _("Invalid public key for reverse lookup `%s'\n"), reverse_pkey); GNUNET_SCHEDULER_shutdown (); } reverse_qe = GNUNET_NAMESTORE_zone_to_name (ns, &zone_pkey, &pubkey, &handle_reverse_lookup, NULL); } if (NULL != uri) { char sh[105]; char sname[64]; struct GNUNET_CRYPTO_EcdsaPublicKey pkey; GNUNET_STRINGS_utf8_tolower (uri, uri); if ( (2 != (sscanf (uri, "gnunet://gns/%52s/%63s", sh, sname)) ) || (GNUNET_OK != GNUNET_CRYPTO_ecdsa_public_key_from_string (sh, strlen (sh), &pkey)) ) { fprintf (stderr, _("Invalid URI `%s'\n"), uri); GNUNET_SCHEDULER_shutdown (); ret = 1; return; } memset (&rd, 0, sizeof (rd)); rd.data = &pkey; rd.data_size = sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey); rd.record_type = GNUNET_GNSRECORD_TYPE_PKEY; if (GNUNET_YES == etime_is_rel) { rd.expiration_time = etime_rel.rel_value_us; rd.flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; } else if (GNUNET_NO == etime_is_rel) rd.expiration_time = etime_abs.abs_value_us; else rd.expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; if (1 == is_shadow) rd.flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD; add_qe_uri = GNUNET_NAMESTORE_records_store (ns, &zone_pkey, sname, 1, &rd, &add_continuation, &add_qe_uri); } if (NULL != nickstring) { if (0 == strlen(nickstring)) { fprintf (stderr, _("Invalid nick `%s'\n"), nickstring); GNUNET_SCHEDULER_shutdown (); ret = 1; return; } add_qe_uri = GNUNET_NAMESTORE_set_nick(ns, &zone_pkey, nickstring, &add_continuation, &add_qe_uri); } if (monitor) { zm = GNUNET_NAMESTORE_zone_monitor_start (cfg, &zone_pkey, GNUNET_YES, &display_record, &sync_cb, NULL); } }
/** * Convert human-readable version of a 'value' of a record to the binary * representation. * * @param cls closure, unused * @param type type of the record * @param s human-readable string * @param data set to value in binary encoding (will be allocated) * @param data_size set to number of bytes in @a data * @return #GNUNET_OK on success */ static int gns_string_to_value (void *cls, uint32_t type, const char *s, void **data, size_t *data_size) { struct GNUNET_CRYPTO_EcdsaPublicKey pkey; if (NULL == s) return GNUNET_SYSERR; switch (type) { case GNUNET_GNSRECORD_TYPE_PKEY: if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_public_key_from_string (s, strlen (s), &pkey)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to parse PKEY record `%s'\n"), s); return GNUNET_SYSERR; } *data = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey); memcpy (*data, &pkey, sizeof (pkey)); *data_size = sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey); return GNUNET_OK; case GNUNET_GNSRECORD_TYPE_NICK: *data = GNUNET_strdup (s); *data_size = strlen (s); return GNUNET_OK; case GNUNET_GNSRECORD_TYPE_LEHO: *data = GNUNET_strdup (s); *data_size = strlen (s); return GNUNET_OK; case GNUNET_GNSRECORD_TYPE_GNS2DNS: { char nsbuf[514]; char *cpy; char *at; size_t off; cpy = GNUNET_strdup (s); at = strchr (cpy, '@'); if (NULL == at) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to parse GNS2DNS record `%s'\n"), s); GNUNET_free (cpy); return GNUNET_SYSERR; } *at = '\0'; at++; off = 0; if ( (GNUNET_OK != GNUNET_DNSPARSER_builder_add_name (nsbuf, sizeof (nsbuf), &off, cpy)) || (GNUNET_OK != GNUNET_DNSPARSER_builder_add_name (nsbuf, sizeof (nsbuf), &off, at)) ) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to serialize GNS2DNS record with value `%s'\n"), s); GNUNET_free (cpy); return GNUNET_SYSERR; } GNUNET_free (cpy); *data_size = off; *data = GNUNET_malloc (off); memcpy (*data, nsbuf, off); return GNUNET_OK; } case GNUNET_GNSRECORD_TYPE_VPN: { struct GNUNET_TUN_GnsVpnRecord *vpn; char s_peer[103 + 1]; char s_serv[253 + 1]; unsigned int proto; if (3 != SSCANF (s, "%u %103s %253s", &proto, s_peer, s_serv)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to parse VPN record string `%s'\n"), s); return GNUNET_SYSERR; } *data_size = sizeof (struct GNUNET_TUN_GnsVpnRecord) + strlen (s_serv) + 1; *data = vpn = GNUNET_malloc (*data_size); if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string ((char*) s_peer, strlen (s_peer), &vpn->peer.public_key)) { GNUNET_free (vpn); *data_size = 0; return GNUNET_SYSERR; } vpn->proto = htons ((uint16_t) proto); strcpy ((char*)&vpn[1], s_serv); return GNUNET_OK; } case GNUNET_GNSRECORD_TYPE_BOX: { struct GNUNET_GNSRECORD_BoxRecord *box; size_t rest; unsigned int protocol; unsigned int service; unsigned int record_type; void *bval; size_t bval_size; if (3 != SSCANF (s, "%u %u %u ", &protocol, &service, &record_type)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to parse BOX record string `%s'\n"), s); return GNUNET_SYSERR; } rest = snprintf (NULL, 0, "%u %u %u ", protocol, service, record_type); if (GNUNET_OK != GNUNET_GNSRECORD_string_to_value (record_type, &s[rest], &bval, &bval_size)) return GNUNET_SYSERR; *data_size = sizeof (struct GNUNET_GNSRECORD_BoxRecord) + bval_size; *data = box = GNUNET_malloc (*data_size); box->protocol = htons (protocol); box->service = htons (service); box->record_type = htonl (record_type); memcpy (&box[1], bval, bval_size); GNUNET_free (bval); return GNUNET_OK; } default: return GNUNET_SYSERR; } }
/** * Main request handler. */ static int access_handler_callback (void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t * upload_data_size, void **con_cls) { static int dummy; static const struct Entry map[] = { { "prefix", "prefix" }, { "name", "name" }, { "suffix", "suffix" }, { "street", "street" }, { "city", "city" }, { "phone", "phone" }, { "fax", "fax" }, { "email", "email"}, { "homepage", "homepage" }, { "orga", "orga"}, { "departmenti18n", "departmentde"}, { "departmenten", "departmenten"}, { "subdepartmenti18n", "subdepartmentde"}, { "subdepartmenten", "subdepartmenten"}, { "jobtitlei18n", "jobtitlegerman"}, { "jobtitleen", "jobtitleenglish"}, { "subdepartmenten", "subdepartmenten"}, { NULL, NULL } }; if (0 != strcmp (method, MHD_HTTP_METHOD_GET)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Refusing `%s' request to HTTP server\n"), method); return MHD_NO; } if (NULL == *con_cls) { (*con_cls) = &dummy; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending 100 CONTINUE reply\n"); return MHD_YES; /* send 100 continue */ } if (0 == strcasecmp (url, "/")) return MHD_queue_response (connection, MHD_HTTP_OK, main_response); if (0 == strcasecmp (url, "/submit.pdf")) { unsigned int i; char *p; char *tmp; char *deffile; struct GNUNET_CRYPTO_EcdsaPublicKey pub; size_t slen; FILE *f; struct stat st; struct MHD_Response *response; int fd; int ret; const char *gpg_fp = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "gpgfingerprint"); const char *gns_nick = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "gnsnick"); const char *gnskey = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "gnskey"); if ( (NULL == gnskey) || (GNUNET_OK != GNUNET_CRYPTO_ecdsa_public_key_from_string (gnskey, strlen (gnskey), &pub))) { return MHD_queue_response (connection, MHD_HTTP_OK, invalid_gnskey_response); } tmp = GNUNET_DISK_mkdtemp (gnskey); if (NULL == tmp) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "mktemp", gnskey); return MHD_NO; } GNUNET_asprintf (&deffile, "%s%s%s", tmp, DIR_SEPARATOR_STR, "def.tex"); f = FOPEN (deffile, "w"); if (NULL == f) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", deffile); GNUNET_free (deffile); GNUNET_DISK_directory_remove (tmp); GNUNET_free (tmp); return MHD_NO; } for (i=0; NULL != map[i].formname; i++) { const char *val = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, map[i].formname); if (NULL != val) FPRINTF (f, "\\def\\%s{%s}\n", map[i].texname, val); else FPRINTF (f, "\\def\\%s{}\n", map[i].texname); } if (NULL != gpg_fp) { char *gpg1; char *gpg2; slen = strlen (gpg_fp); gpg1 = GNUNET_strndup (gpg_fp, slen / 2); gpg2 = GNUNET_strdup (&gpg_fp[slen / 2]); FPRINTF (f, "\\def\\gpglineone{%s}\n\\def\\gpglinetwo{%s}\n", gpg1, gpg2); GNUNET_free (gpg2); GNUNET_free (gpg1); } FPRINTF (f, "\\def\\gns{%s/%s}\n", gnskey, (NULL == gns_nick) ? "" : gns_nick); FCLOSE (f); GNUNET_asprintf (&p, "cd %s; cp %s gns-bcd.tex | pdflatex --enable-write18 gns-bcd.tex > /dev/null 2> /dev/null", tmp, resfile); GNUNET_free (deffile); ret = system (p); if (WIFSIGNALED (ret) || (0 != WEXITSTATUS(ret))) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "system", p); GNUNET_asprintf (&deffile, "%s%s%s", tmp, DIR_SEPARATOR_STR, "gns-bcd.pdf"); fd = OPEN (deffile, O_RDONLY); if (-1 == fd) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", deffile); GNUNET_free (deffile); GNUNET_free (p); GNUNET_DISK_directory_remove (tmp); GNUNET_free (tmp); return MHD_NO; } GNUNET_break (0 == STAT (deffile, &st)); if (NULL == (response = MHD_create_response_from_fd ((size_t) st.st_size, fd))) { GNUNET_break (0); GNUNET_break (0 == CLOSE (fd)); GNUNET_free (deffile); GNUNET_free (p); GNUNET_DISK_directory_remove (tmp); GNUNET_free (tmp); return MHD_NO; } (void) MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, "application/pdf"); ret = MHD_queue_response (connection, MHD_HTTP_OK, response); MHD_destroy_response (response); GNUNET_free (deffile); GNUNET_free (p); GNUNET_DISK_directory_remove (tmp); GNUNET_free (tmp); return ret; } return MHD_queue_response (connection, MHD_HTTP_NOT_FOUND, not_found_response); }
/** * Convert human-readable version of a 'value' of a record to the binary * representation. * * @param cls closure, unused * @param type type of the record * @param s human-readable string * @param data set to value in binary encoding (will be allocated) * @param data_size set to number of bytes in @a data * @return #GNUNET_OK on success */ static int gns_string_to_value (void *cls, uint32_t type, const char *s, void **data, size_t *data_size) { struct GNUNET_CRYPTO_EcdsaPublicKey pkey; if (NULL == s) return GNUNET_SYSERR; switch (type) { case GNUNET_GNSRECORD_TYPE_PKEY: if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_public_key_from_string (s, strlen (s), &pkey)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to parse PKEY record `%s'\n"), s); return GNUNET_SYSERR; } *data = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey); GNUNET_memcpy (*data, &pkey, sizeof (pkey)); *data_size = sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey); return GNUNET_OK; case GNUNET_GNSRECORD_TYPE_NICK: *data = GNUNET_strdup (s); *data_size = strlen (s); return GNUNET_OK; case GNUNET_GNSRECORD_TYPE_LEHO: *data = GNUNET_strdup (s); *data_size = strlen (s); return GNUNET_OK; case GNUNET_GNSRECORD_TYPE_GNS2DNS: { char nsbuf[514]; char *cpy; char *at; size_t off; cpy = GNUNET_strdup (s); at = strchr (cpy, '@'); if (NULL == at) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to parse GNS2DNS record `%s'\n"), s); GNUNET_free (cpy); return GNUNET_SYSERR; } *at = '\0'; at++; off = 0; if ( (GNUNET_OK != GNUNET_DNSPARSER_builder_add_name (nsbuf, sizeof (nsbuf), &off, cpy)) || (GNUNET_OK != GNUNET_DNSPARSER_builder_add_name (nsbuf, sizeof (nsbuf), &off, at)) ) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to serialize GNS2DNS record with value `%s'\n"), s); GNUNET_free (cpy); return GNUNET_SYSERR; } GNUNET_free (cpy); *data_size = off; *data = GNUNET_malloc (off); GNUNET_memcpy (*data, nsbuf, off); return GNUNET_OK; } case GNUNET_GNSRECORD_TYPE_VPN: { struct GNUNET_TUN_GnsVpnRecord *vpn; char s_peer[103 + 1]; char s_serv[253 + 1]; unsigned int proto; if (3 != SSCANF (s, "%u %103s %253s", &proto, s_peer, s_serv)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to parse VPN record string `%s'\n"), s); return GNUNET_SYSERR; } *data_size = sizeof (struct GNUNET_TUN_GnsVpnRecord) + strlen (s_serv) + 1; *data = vpn = GNUNET_malloc (*data_size); if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string ((char*) s_peer, strlen (s_peer), &vpn->peer.public_key)) { GNUNET_free (vpn); *data_size = 0; return GNUNET_SYSERR; } vpn->proto = htons ((uint16_t) proto); strcpy ((char*)&vpn[1], s_serv); return GNUNET_OK; } case GNUNET_GNSRECORD_TYPE_BOX: { struct GNUNET_GNSRECORD_BoxRecord *box; size_t rest; unsigned int protocol; unsigned int service; unsigned int record_type; void *bval; size_t bval_size; if (3 != SSCANF (s, "%u %u %u ", &protocol, &service, &record_type)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to parse BOX record string `%s'\n"), s); return GNUNET_SYSERR; } rest = snprintf (NULL, 0, "%u %u %u ", protocol, service, record_type); if (GNUNET_OK != GNUNET_GNSRECORD_string_to_value (record_type, &s[rest], &bval, &bval_size)) return GNUNET_SYSERR; *data_size = sizeof (struct GNUNET_GNSRECORD_BoxRecord) + bval_size; *data = box = GNUNET_malloc (*data_size); box->protocol = htons (protocol); box->service = htons (service); box->record_type = htonl (record_type); GNUNET_memcpy (&box[1], bval, bval_size); GNUNET_free (bval); return GNUNET_OK; } case GNUNET_GNSRECORD_TYPE_REVERSE: { struct GNUNET_GNSRECORD_ReverseRecord *rev; char known_by[253 + 1]; struct GNUNET_TIME_Absolute expiration; /* TODO: From crypto_ecc.c * Why is this not a constant??? */ size_t enclen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8; if (enclen % 5 > 0) enclen += 5 - enclen % 5; enclen /= 5; /* 260/5 = 52 */ char pkey_str[enclen + 1]; if (3 != SSCANF (s, "%253s %52s %"SCNu64, known_by, pkey_str, &expiration.abs_value_us)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to parse REVERSE record string `%s'\n"), s); return GNUNET_SYSERR; } *data_size = sizeof (struct GNUNET_GNSRECORD_ReverseRecord) + strlen (known_by) + 1; *data = rev = GNUNET_malloc (*data_size); GNUNET_CRYPTO_ecdsa_public_key_from_string (pkey_str, strlen (pkey_str), &rev->pkey); rev->expiration = expiration; GNUNET_memcpy (&rev[1], known_by, strlen (known_by)); return GNUNET_OK; } default: return GNUNET_SYSERR; } }