/** * @brief Restore the peers on disk to #valid_peers. */ static void restore_valid_peers () { off_t file_size; uint32_t num_peers; struct GNUNET_DISK_FileHandle *fh; char *buf; ssize_t size_read; char *iter_buf; char *str_repr; const struct GNUNET_PeerIdentity *peer; if (0 == strncmp ("DISABLE", filename_valid_peers, 7)) { return; } if (GNUNET_OK != GNUNET_DISK_file_test (filename_valid_peers)) { return; } fh = GNUNET_DISK_file_open (filename_valid_peers, GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_NONE); GNUNET_assert (NULL != fh); GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_handle_size (fh, &file_size)); num_peers = file_size / 53; buf = GNUNET_malloc (file_size); size_read = GNUNET_DISK_file_read (fh, buf, file_size); GNUNET_assert (size_read == file_size); LOG (GNUNET_ERROR_TYPE_DEBUG, "Restoring %" PRIu32 " peers from file `%s'\n", num_peers, filename_valid_peers); for (iter_buf = buf; iter_buf < buf + file_size - 1; iter_buf += 53) { str_repr = GNUNET_strndup (iter_buf, 53); peer = s2i_full (str_repr); GNUNET_free (str_repr); add_valid_peer (peer); LOG (GNUNET_ERROR_TYPE_DEBUG, "Restored valid peer %s from disk\n", GNUNET_i2s_full (peer)); } iter_buf = NULL; GNUNET_free (buf); LOG (GNUNET_ERROR_TYPE_DEBUG, "num_peers: %" PRIu32 ", _size (valid_peers): %u\n", num_peers, GNUNET_CONTAINER_multipeermap_size (valid_peers)); if (num_peers != GNUNET_CONTAINER_multipeermap_size (valid_peers)) { LOG (GNUNET_ERROR_TYPE_WARNING, "Number of restored peers does not match file size. Have probably duplicates.\n"); } GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh)); LOG (GNUNET_ERROR_TYPE_DEBUG, "Restored %u valid peers from disk\n", GNUNET_CONTAINER_multipeermap_size (valid_peers)); }
/** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param cfg configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { const char *uri; const char *slash; char *subsystem; char *program; struct GNUNET_SCHEDULER_Task * rt; if (NULL == (uri = args[0])) { fprintf (stderr, _("No URI specified on command line\n")); return; } if (0 != strncasecmp ("gnunet://", uri, strlen ("gnunet://"))) { fprintf (stderr, _("Invalid URI: does not start with `%s'\n"), "gnunet://"); return; } uri += strlen ("gnunet://"); if (NULL == (slash = strchr (uri, '/'))) { fprintf (stderr, _("Invalid URI: fails to specify subsystem\n")); return; } subsystem = GNUNET_strndup (uri, slash - uri); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "uri", subsystem, &program)) { fprintf (stderr, _("No handler known for subsystem `%s'\n"), subsystem); GNUNET_free (subsystem); return; } GNUNET_free (subsystem); rt = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ), &maint_child_death, NULL); p = GNUNET_OS_start_process (GNUNET_NO, 0, NULL, NULL, NULL, program, program, args[0], NULL); GNUNET_free (program); if (NULL == p) GNUNET_SCHEDULER_cancel (rt); }
/** * Convert the 'value' of a record to a string. * * @param type type of the record * @param data value in binary encoding * @param data_size number of bytes in data * @return NULL on error, otherwise human-readable representation of the value */ char * GNUNET_NAMESTORE_value_to_string (uint32_t type, const void *data, size_t data_size) { uint16_t mx_pref; const struct soa_data *soa; const struct vpn_data *vpn; const struct srv_data *srv; const struct tlsa_data *tlsa; struct GNUNET_CRYPTO_ShortHashAsciiEncoded enc; struct GNUNET_CRYPTO_HashAsciiEncoded s_peer; const char *cdata; char* vpn_str; char* srv_str; char* tlsa_str; char* result; const char* soa_rname; const char* soa_mname; char tmp[INET6_ADDRSTRLEN]; switch (type) { case 0: return NULL; case GNUNET_DNSPARSER_TYPE_A: if (data_size != sizeof (struct in_addr)) return NULL; if (NULL == inet_ntop (AF_INET, data, tmp, sizeof (tmp))) return NULL; return GNUNET_strdup (tmp); case GNUNET_DNSPARSER_TYPE_NS: return GNUNET_strndup (data, data_size); case GNUNET_DNSPARSER_TYPE_CNAME: return GNUNET_strndup (data, data_size); case GNUNET_DNSPARSER_TYPE_SOA: if (data_size <= sizeof (struct soa_data)) return NULL; soa = data; soa_rname = (const char*) &soa[1]; soa_mname = memchr (soa_rname, 0, data_size - sizeof (struct soa_data) - 1); if (NULL == soa_mname) return NULL; soa_mname++; if (NULL == memchr (soa_mname, 0, data_size - (sizeof (struct soa_data) + strlen (soa_rname) + 1))) return NULL; GNUNET_asprintf (&result, "rname=%s mname=%s %lu,%lu,%lu,%lu,%lu", soa_rname, soa_mname, ntohl (soa->serial), ntohl (soa->refresh), ntohl (soa->retry), ntohl (soa->expire), ntohl (soa->minimum)); return result; case GNUNET_DNSPARSER_TYPE_PTR: return GNUNET_strndup (data, data_size); case GNUNET_DNSPARSER_TYPE_MX: mx_pref = ntohs(*((uint16_t*)data)); if (GNUNET_asprintf(&result, "%hu,%s", mx_pref, data+sizeof(uint16_t)) != 0) return result; else { GNUNET_free (result); return NULL; } case GNUNET_DNSPARSER_TYPE_TXT: return GNUNET_strndup (data, data_size); case GNUNET_DNSPARSER_TYPE_AAAA: if (data_size != sizeof (struct in6_addr)) return NULL; if (NULL == inet_ntop (AF_INET6, data, tmp, sizeof (tmp))) return NULL; return GNUNET_strdup (tmp); case GNUNET_NAMESTORE_TYPE_PKEY: if (data_size != sizeof (struct GNUNET_CRYPTO_ShortHashCode)) return NULL; GNUNET_CRYPTO_short_hash_to_enc (data, &enc); return GNUNET_strdup ((const char*) enc.short_encoding); case GNUNET_NAMESTORE_TYPE_PSEU: return GNUNET_strndup (data, data_size); case GNUNET_NAMESTORE_TYPE_LEHO: return GNUNET_strndup (data, data_size); case GNUNET_NAMESTORE_TYPE_VPN: cdata = data; if ( (data_size <= sizeof (struct vpn_data)) || ('\0' != cdata[data_size - 1]) ) return NULL; /* malformed */ vpn = data; GNUNET_CRYPTO_hash_to_enc (&vpn->peer, &s_peer); if (0 == GNUNET_asprintf (&vpn_str, "%u %s %s", (unsigned int) ntohs (vpn->proto), (const char*) &s_peer, (const char*) &vpn[1])) { GNUNET_free (vpn_str); return NULL; } return vpn_str; case GNUNET_DNSPARSER_TYPE_SRV: cdata = data; if ( (data_size <= sizeof (struct srv_data)) || ('\0' != cdata[data_size - 1]) ) return NULL; /* malformed */ srv = data; if (0 == GNUNET_asprintf (&srv_str, "%d %d %d %s", ntohs (srv->prio), ntohs (srv->weight), ntohs (srv->port), (const char *)&srv[1])) { GNUNET_free (srv_str); return NULL; } return srv_str; case GNUNET_DNSPARSER_TYPE_TLSA: cdata = data; if ( (data_size <= sizeof (struct tlsa_data)) || ('\0' != cdata[data_size - 1]) ) return NULL; /* malformed */ tlsa = data; if (0 == GNUNET_asprintf (&tlsa_str, "%c %c %c %s", tlsa->usage, tlsa->selector, tlsa->matching_type, (const char *) &tlsa[1])) { GNUNET_free (tlsa_str); return NULL; } return tlsa_str; default: GNUNET_break (0); } GNUNET_break (0); // not implemented return NULL; }
/** * Convert the 'value' of a record to a string. * * @param cls closure, unused * @param type type of the record * @param data value in binary encoding * @param data_size number of bytes in @a data * @return NULL on error, otherwise human-readable representation of the value */ static char * gns_value_to_string (void *cls, uint32_t type, const void *data, size_t data_size) { const char *cdata; switch (type) { case GNUNET_GNSRECORD_TYPE_PKEY: if (data_size != sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) return NULL; return GNUNET_CRYPTO_ecdsa_public_key_to_string (data); case GNUNET_GNSRECORD_TYPE_NICK: return GNUNET_strndup (data, data_size); case GNUNET_GNSRECORD_TYPE_LEHO: return GNUNET_strndup (data, data_size); case GNUNET_GNSRECORD_TYPE_GNS2DNS: { char *ns; char *ip; size_t off; char *nstr; off = 0; ns = GNUNET_DNSPARSER_parse_name (data, data_size, &off); ip = GNUNET_DNSPARSER_parse_name (data, data_size, &off); if ( (NULL == ns) || (NULL == ip) || (off != data_size) ) { GNUNET_break_op (0); GNUNET_free_non_null (ns); GNUNET_free_non_null (ip); return NULL; } GNUNET_asprintf (&nstr, "%s@%s", ns, ip); GNUNET_free_non_null (ns); GNUNET_free_non_null (ip); return nstr; } case GNUNET_GNSRECORD_TYPE_VPN: { const struct GNUNET_TUN_GnsVpnRecord *vpn; char* vpn_str; cdata = data; if ( (data_size <= sizeof (struct GNUNET_TUN_GnsVpnRecord)) || ('\0' != cdata[data_size - 1]) ) return NULL; /* malformed */ vpn = data; GNUNET_asprintf (&vpn_str, "%u %s %s", (unsigned int) ntohs (vpn->proto), (const char*) GNUNET_i2s_full (&vpn->peer), (const char*) &vpn[1]); return vpn_str; } case GNUNET_GNSRECORD_TYPE_BOX: { const struct GNUNET_GNSRECORD_BoxRecord *box; uint32_t rt; char *box_str; char *ival; if (data_size < sizeof (struct GNUNET_GNSRECORD_BoxRecord)) return NULL; /* malformed */ box = data; rt = ntohl (box->record_type); ival = GNUNET_GNSRECORD_value_to_string (rt, &box[1], data_size - sizeof (struct GNUNET_GNSRECORD_BoxRecord)); if (NULL == ival) return NULL; /* malformed */ GNUNET_asprintf (&box_str, "%u %u %u %s", (unsigned int) ntohs (box->protocol), (unsigned int) ntohs (box->service), (unsigned int) rt, ival); GNUNET_free (ival); return box_str; } default: return NULL; } }
/** * 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); }
/** * We're building a HELLO. Parse the next address from the * parsing context and append it. * * @param cls the 'struct GNUNET_PEERINFO_HelloAddressParsingContext' * @param max number of bytes available for HELLO construction * @param buffer where to copy the next address (in binary format) * @return number of bytes added to buffer */ static size_t add_address_to_hello (void *cls, size_t max, void *buffer) { struct GNUNET_PEERINFO_HelloAddressParsingContext *ctx = cls; const char *tname; const char *address; char *uri_address; char *plugin_address; const char *end; char *plugin_name; struct tm expiration_time; time_t expiration_seconds; struct GNUNET_TIME_Absolute expire; struct GNUNET_TRANSPORT_PluginFunctions *papi; void *addr; size_t addr_len; struct GNUNET_HELLO_Address haddr; size_t ret; if (NULL == ctx->pos) return 0; if ('!' != ctx->pos[0]) { ctx->ret = GNUNET_SYSERR; GNUNET_break (0); return 0; } ctx->pos++; memset (&expiration_time, 0, sizeof (expiration_time)); tname = strptime (ctx->pos, "%Y%m%d%H%M%S", &expiration_time); if (NULL == tname) { ctx->ret = GNUNET_SYSERR; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to parse HELLO message: missing expiration time\n")); GNUNET_break (0); return 0; } expiration_seconds = mktime (&expiration_time); if (expiration_seconds == (time_t) -1) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to parse HELLO message: invalid expiration time\n")); ctx->ret = GNUNET_SYSERR; GNUNET_break (0); return 0; } expire.abs_value = expiration_seconds * 1000; if ('!' != tname[0]) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to parse HELLO message: malformed\n")); ctx->ret = GNUNET_SYSERR; GNUNET_break (0); return 0; } tname++; address = strchr (tname, (int) '!'); if (NULL == address) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to parse HELLO message: missing transport plugin\n")); ctx->ret = GNUNET_SYSERR; GNUNET_break (0); return 0; } address++; end = strchr (address, (int) '!'); ctx->pos = end; plugin_name = GNUNET_strndup (tname, address - (tname+1)); papi = GPI_plugins_find (plugin_name); if (NULL == papi) { /* Not an error - we might just not have the right plugin. * Skip this part, advance to the next one and recurse. * But only if this is not the end of string. */ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Plugin `%s' not found\n"), plugin_name); GNUNET_free (plugin_name); GNUNET_break (0); return 0; } if (NULL == papi->string_to_address) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Plugin `%s' does not support URIs yet\n"), plugin_name); GNUNET_free (plugin_name); GNUNET_break (0); return 0; } uri_address = GNUNET_strndup (address, end - address); /* For URIs we use '(' and ')' instead of '[' and ']' as brackets are reserved characters in URIs; need to convert back to '[]' for the plugin */ plugin_address = map_characters (uri_address, "()", "[]"); GNUNET_free (uri_address); if (GNUNET_OK != papi->string_to_address (papi->cls, plugin_address, strlen (plugin_address) + 1, &addr, &addr_len)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to parse `%s' as an address for plugin `%s'\n"), plugin_address, plugin_name); GNUNET_free (plugin_name); GNUNET_free (plugin_address); return 0; } GNUNET_free (plugin_address); /* address.peer is unset - not used by add_address() */ haddr.address_length = addr_len; haddr.address = addr; haddr.transport_name = plugin_name; ret = GNUNET_HELLO_add_address (&haddr, expire, buffer, max); GNUNET_free (addr); GNUNET_free (plugin_name); return ret; }
/** * Convert the 'value' of a record to a string. * * @param cls closure, unused * @param type type of the record * @param data value in binary encoding * @param data_size number of bytes in @a data * @return NULL on error, otherwise human-readable representation of the value */ static char * gns_value_to_string (void *cls, uint32_t type, const void *data, size_t data_size) { const char *cdata; switch (type) { case GNUNET_GNSRECORD_TYPE_PKEY: if (data_size != sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) return NULL; return GNUNET_CRYPTO_ecdsa_public_key_to_string (data); case GNUNET_GNSRECORD_TYPE_NICK: return GNUNET_strndup (data, data_size); case GNUNET_GNSRECORD_TYPE_LEHO: return GNUNET_strndup (data, data_size); case GNUNET_GNSRECORD_TYPE_GNS2DNS: { char *ns; char *ip; size_t off; char *nstr; off = 0; ns = GNUNET_DNSPARSER_parse_name (data, data_size, &off); ip = GNUNET_DNSPARSER_parse_name (data, data_size, &off); if ( (NULL == ns) || (NULL == ip) || (off != data_size) ) { GNUNET_break_op (0); GNUNET_free_non_null (ns); GNUNET_free_non_null (ip); return NULL; } GNUNET_asprintf (&nstr, "%s@%s", ns, ip); GNUNET_free_non_null (ns); GNUNET_free_non_null (ip); return nstr; } case GNUNET_GNSRECORD_TYPE_VPN: { struct GNUNET_TUN_GnsVpnRecord vpn; char* vpn_str; cdata = data; if ( (data_size <= sizeof (vpn)) || ('\0' != cdata[data_size - 1]) ) return NULL; /* malformed */ /* need to memcpy for alignment */ memcpy (&vpn, data, sizeof (vpn)); GNUNET_asprintf (&vpn_str, "%u %s %s", (unsigned int) ntohs (vpn.proto), (const char*) GNUNET_i2s_full (&vpn.peer), (const char*) &cdata[sizeof (vpn)]); return vpn_str; } case GNUNET_GNSRECORD_TYPE_BOX: { struct GNUNET_GNSRECORD_BoxRecord box; uint32_t rt; char *box_str; char *ival; cdata = data; if (data_size < sizeof (struct GNUNET_GNSRECORD_BoxRecord)) return NULL; /* malformed */ memcpy (&box, data, sizeof (box)); rt = ntohl (box.record_type); ival = GNUNET_GNSRECORD_value_to_string (rt, &cdata[sizeof (box)], data_size - sizeof (box)); if (NULL == ival) return NULL; /* malformed */ GNUNET_asprintf (&box_str, "%u %u %u %s", (unsigned int) ntohs (box.protocol), (unsigned int) ntohs (box.service), (unsigned int) rt, ival); GNUNET_free (ival); return box_str; } case GNUNET_GNSRECORD_TYPE_REVERSE: { struct GNUNET_GNSRECORD_ReverseRecord rev; char *rev_str; char *pkey_str; if (data_size < sizeof (struct GNUNET_GNSRECORD_ReverseRecord)) return NULL; /* malformed */ memcpy (&rev, data, sizeof (rev)); cdata = data; pkey_str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&rev.pkey); GNUNET_asprintf (&rev_str, "%s %s %"SCNu64, &cdata[sizeof (rev)], pkey_str, rev.expiration.abs_value_us); GNUNET_free (pkey_str); return rev_str; } default: return NULL; } }