diff options
-rw-r--r-- | src/core/gnunet-service-core.c | 86 | ||||
-rw-r--r-- | src/core/gnunet-service-core_kx.c | 23 | ||||
-rw-r--r-- | src/core/gnunet-service-core_kx.h | 3 | ||||
-rw-r--r-- | src/fs/fs_uri.c | 3 | ||||
-rw-r--r-- | src/include/gnunet_crypto_lib.h | 11 | ||||
-rw-r--r-- | src/include/gnunet_server_lib.h | 18 | ||||
-rw-r--r-- | src/mesh/gnunet-service-mesh.c | 154 | ||||
-rw-r--r-- | src/nse/gnunet-service-nse.c | 195 | ||||
-rw-r--r-- | src/peerinfo-tool/gnunet-peerinfo.c | 14 | ||||
-rw-r--r-- | src/transport/gnunet-service-transport.c | 109 | ||||
-rw-r--r-- | src/transport/test_plugin_transport.c | 68 | ||||
-rw-r--r-- | src/util/crypto_random.c | 37 | ||||
-rw-r--r-- | src/util/crypto_rsa.c | 46 | ||||
-rw-r--r-- | src/util/gnunet-rsa.c | 10 | ||||
-rw-r--r-- | src/util/server.c | 95 |
15 files changed, 576 insertions, 296 deletions
diff --git a/src/core/gnunet-service-core.c b/src/core/gnunet-service-core.c index 59d938364d..f5d01cd27e 100644 --- a/src/core/gnunet-service-core.c +++ b/src/core/gnunet-service-core.c @@ -48,21 +48,39 @@ const struct GNUNET_CONFIGURATION_Handle *GSC_cfg; */ struct GNUNET_STATISTICS_Handle *GSC_stats; +/** + * Handle to the server of the core service. + */ +static struct GNUNET_SERVER_Handle *GSC_server; + +/** + * Hostkey generation context + */ +struct GNUNET_CRYPTO_RsaKeyGenerationContext *GST_keygen; + /** * Last task run during shutdown. Disconnects us from * the transport. + * + * @param cls NULL, unused + * @param tc scheduler context, unused */ static void -cleaning_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core service shutting down.\n"); + if (NULL != GST_keygen) + { + GNUNET_CRYPTO_rsa_key_create_stop (GST_keygen); + GST_keygen = NULL; + } GSC_CLIENTS_done (); GSC_NEIGHBOURS_done (); GSC_SESSIONS_done (); GSC_KX_done (); GSC_TYPEMAP_done (); - if (GSC_stats != NULL) + if (NULL != GSC_stats) { GNUNET_STATISTICS_destroy (GSC_stats, GNUNET_NO); GSC_stats = NULL; @@ -71,6 +89,42 @@ cleaning_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } + +/** + * Callback for hostkey read/generation + * + * @param cls NULL + * @param pk the private key + * @param emsg error message + */ +static void +key_generation_cb (void *cls, + struct GNUNET_CRYPTO_RsaPrivateKey *pk, + const char *emsg) +{ + GST_keygen = NULL; + if (NULL == pk) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Failed to read hostkey: %s\n"), + emsg); + GNUNET_SCHEDULER_shutdown (); + return; + } + if ((GNUNET_OK != GSC_KX_init (pk)) || + (GNUNET_OK != GSC_NEIGHBOURS_init ())) + { + GNUNET_SCHEDULER_shutdown (); + return; + } + GSC_SESSIONS_init (); + GSC_CLIENTS_init (GSC_server); + GNUNET_SERVER_resume (GSC_server); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Core service of `%4s' ready.\n"), + GNUNET_i2s (&GSC_my_identity)); +} + + /** * Initiate core service. * @@ -82,24 +136,36 @@ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *c) { + char *keyfile; + GSC_cfg = c; + GSC_server = server; + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_filename (GSC_cfg, "GNUNETD", "HOSTKEY", + &keyfile)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _ + ("Core service is lacking HOSTKEY configuration setting. Exiting.\n")); + GNUNET_SCHEDULER_shutdown (); + return; + } GSC_stats = GNUNET_STATISTICS_create ("core", GSC_cfg); - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleaning_task, + GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); + GNUNET_SERVER_suspend (server); GSC_TYPEMAP_init (); - if ((GNUNET_OK != GSC_KX_init ()) || (GNUNET_OK != GSC_NEIGHBOURS_init ())) + GST_keygen = GNUNET_CRYPTO_rsa_key_create_start (keyfile, &key_generation_cb, NULL); + GNUNET_free (keyfile); + if (NULL == GST_keygen) { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Transport service is unable to access hostkey. Exiting.\n")); GNUNET_SCHEDULER_shutdown (); - return; } - GSC_SESSIONS_init (); - GSC_CLIENTS_init (server); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Core service of `%4s' ready.\n"), - GNUNET_i2s (&GSC_my_identity)); } - /** * The main function for the transport service. * diff --git a/src/core/gnunet-service-core_kx.c b/src/core/gnunet-service-core_kx.c index f5bea09e5f..755d0c34cf 100644 --- a/src/core/gnunet-service-core_kx.c +++ b/src/core/gnunet-service-core_kx.c @@ -1686,30 +1686,13 @@ deliver_message (void *cls, void *client, const struct GNUNET_MessageHeader *m) /** * Initialize KX subsystem. * + * @param pk private key to use for the peer * @return GNUNET_OK on success, GNUNET_SYSERR on failure */ int -GSC_KX_init () +GSC_KX_init (struct GNUNET_CRYPTO_RsaPrivateKey *pk) { - char *keyfile; - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_filename (GSC_cfg, "GNUNETD", "HOSTKEY", - &keyfile)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _ - ("Core service is lacking HOSTKEY configuration setting. Exiting.\n")); - return GNUNET_SYSERR; - } - my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); - GNUNET_free (keyfile); - if (NULL == my_private_key) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Core service could not access hostkey. Exiting.\n")); - return GNUNET_SYSERR; - } + my_private_key = pk; GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key); GNUNET_CRYPTO_hash (&my_public_key, sizeof (my_public_key), &GSC_my_identity.hashPubKey); diff --git a/src/core/gnunet-service-core_kx.h b/src/core/gnunet-service-core_kx.h index 5ecd2c17f8..fcb561e01c 100644 --- a/src/core/gnunet-service-core_kx.h +++ b/src/core/gnunet-service-core_kx.h @@ -121,10 +121,11 @@ GSC_KX_stop (struct GSC_KeyExchangeInfo *kx); /** * Initialize KX subsystem. * + * @param pk private key to use for the peer * @return GNUNET_OK on success, GNUNET_SYSERR on failure */ int -GSC_KX_init (void); +GSC_KX_init (struct GNUNET_CRYPTO_RsaPrivateKey *pk); /** diff --git a/src/fs/fs_uri.c b/src/fs/fs_uri.c index ad21692c9a..0f41689183 100644 --- a/src/fs/fs_uri.c +++ b/src/fs/fs_uri.c @@ -903,8 +903,7 @@ GNUNET_FS_uri_loc_create (const struct GNUNET_FS_Uri *baseUri, _("Lacking key configuration settings.\n")); return NULL; } - my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); - if (my_private_key == NULL) + if (NULL == (my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not access hostkey file `%s'.\n"), keyfile); diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h index b73d26d1e8..710ef31790 100644 --- a/src/include/gnunet_crypto_lib.h +++ b/src/include/gnunet_crypto_lib.h @@ -1085,6 +1085,17 @@ void GNUNET_CRYPTO_random_disable_entropy_gathering (void); +/** + * Check if we are using weak random number generation. + * + * @return GNUNET_YES if weak number generation is on + * (thus will return YES if 'GNUNET_CRYPTO_random_disable_entropy_gathering' + * was called previously). + */ +int +GNUNET_CRYPTO_random_is_weak (void); + + #if 0 /* keep Emacsens' auto-indent happy */ { #endif diff --git a/src/include/gnunet_server_lib.h b/src/include/gnunet_server_lib.h index 73fe8000e6..aaf47aca51 100644 --- a/src/include/gnunet_server_lib.h +++ b/src/include/gnunet_server_lib.h @@ -155,6 +155,24 @@ GNUNET_SERVER_create (GNUNET_CONNECTION_AccessCheck access, void *access_cls, /** + * Suspend accepting connections from the listen socket temporarily. + * + * @param server server to stop accepting connections. + */ +void +GNUNET_SERVER_suspend (struct GNUNET_SERVER_Handle *server); + + +/** + * Resume accepting connections from the listen socket. + * + * @param server server to stop accepting connections. + */ +void +GNUNET_SERVER_resume (struct GNUNET_SERVER_Handle *server); + + +/** * Stop the listen socket and get ready to shutdown the server * once only 'monitor' clients are left. * diff --git a/src/mesh/gnunet-service-mesh.c b/src/mesh/gnunet-service-mesh.c index 2ce30c82fc..e40a3de966 100644 --- a/src/mesh/gnunet-service-mesh.c +++ b/src/mesh/gnunet-service-mesh.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2001 - 2011 Christian Grothoff (and other contributing authors) + (C) 2001-2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -816,6 +816,12 @@ static long long unsigned int dht_replication_level; static long long unsigned int max_tunnels; static long long unsigned int max_msgs_queue; + +/** + * Hostkey generation context + */ +static struct GNUNET_CRYPTO_RsaKeyGenerationContext *keygen; + /** * DLL with all the clients, head. */ @@ -7684,6 +7690,7 @@ shutdown_peer (void *cls, const struct GNUNET_HashCode * key, void *value) return GNUNET_YES; } + /** * Task run during shutdown. * @@ -7700,6 +7707,11 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_CORE_disconnect (core_handle); core_handle = NULL; } + if (NULL != keygen) + { + GNUNET_CRYPTO_rsa_key_create_stop (keygen); + keygen = NULL; + } GNUNET_CONTAINER_multihashmap_iterate (tunnels, &shutdown_tunnel, NULL); GNUNET_CONTAINER_multihashmap_iterate (peers, &shutdown_peer, NULL); if (dht_handle != NULL) @@ -7720,6 +7732,76 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shut down\n"); } + +/** + * Callback for hostkey read/generation + * + * @param cls NULL + * @param pk the private key + * @param emsg error message + */ +static void +key_generation_cb (void *cls, + struct GNUNET_CRYPTO_RsaPrivateKey *pk, + const char *emsg) +{ + struct MeshPeerInfo *peer; + struct MeshPeerPath *p; + + keygen = NULL; + if (NULL == pk) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Mesh service could not access hostkey. Exiting.\n")); + GNUNET_SCHEDULER_shutdown (); + return; + } + my_private_key = pk; + GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key); + GNUNET_CRYPTO_hash (&my_public_key, sizeof (my_public_key), + &my_full_id.hashPubKey); + myid = GNUNET_PEER_intern (&my_full_id); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Mesh for peer [%s] starting\n", + GNUNET_i2s(&my_full_id)); + +// transport_handle = GNUNET_TRANSPORT_connect(c, +// &my_full_id, +// NULL, +// NULL, +// NULL, +// NULL); + + + + next_tid = 0; + next_local_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_SERV; + + + GNUNET_SERVER_add_handlers (server_handle, client_handlers); + nc = GNUNET_SERVER_notification_context_create (server_handle, 1); + GNUNET_SERVER_disconnect_notify (server_handle, + &handle_local_client_disconnect, NULL); + + + clients = NULL; + clients_tail = NULL; + next_client_id = 0; + + announce_applications_task = GNUNET_SCHEDULER_NO_TASK; + announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id, cls); + + /* Create a peer_info for the local peer */ + peer = peer_info_get (&my_full_id); + p = path_new (1); + p->peers[0] = myid; + GNUNET_PEER_change_rc (myid, 1); + peer_info_add_path (peer, p, GNUNET_YES); + GNUNET_SERVER_resume (server_handle); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Mesh service running\n"); +} + + /** * Process mesh requests. * @@ -7731,8 +7813,6 @@ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *c) { - struct MeshPeerInfo *peer; - struct MeshPeerPath *p; char *keyfile; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "starting to run\n"); @@ -7873,76 +7953,28 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, dht_replication_level = 10; } - - my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); - GNUNET_free (keyfile); - if (my_private_key == NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Mesh service could not access hostkey. Exiting.\n")); - GNUNET_SCHEDULER_shutdown (); - return; - } - GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key); - GNUNET_CRYPTO_hash (&my_public_key, sizeof (my_public_key), - &my_full_id.hashPubKey); - myid = GNUNET_PEER_intern (&my_full_id); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Mesh for peer [%s] starting\n", - GNUNET_i2s(&my_full_id)); - -// transport_handle = GNUNET_TRANSPORT_connect(c, -// &my_full_id, -// NULL, -// NULL, -// NULL, -// NULL); - - dht_handle = GNUNET_DHT_connect (c, 64); - if (dht_handle == NULL) - { - GNUNET_break (0); - } - - stats = GNUNET_STATISTICS_create ("mesh", c); - - - next_tid = 0; - next_local_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_SERV; - tunnels = GNUNET_CONTAINER_multihashmap_create (32); incoming_tunnels = GNUNET_CONTAINER_multihashmap_create (32); peers = GNUNET_CONTAINER_multihashmap_create (32); applications = GNUNET_CONTAINER_multihashmap_create (32); types = GNUNET_CONTAINER_multihashmap_create (32); - GNUNET_SERVER_add_handlers (server_handle, client_handlers); - nc = GNUNET_SERVER_notification_context_create (server_handle, 1); - GNUNET_SERVER_disconnect_notify (server_handle, - &handle_local_client_disconnect, NULL); - - - clients = NULL; - clients_tail = NULL; - next_client_id = 0; - - announce_applications_task = GNUNET_SCHEDULER_NO_TASK; - announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id, cls); - - /* Create a peer_info for the local peer */ - peer = peer_info_get (&my_full_id); - p = path_new (1); - p->peers[0] = myid; - GNUNET_PEER_change_rc (myid, 1); - peer_info_add_path (peer, p, GNUNET_YES); + dht_handle = GNUNET_DHT_connect (c, 64); + if (NULL == dht_handle) + { + GNUNET_break (0); + } + stats = GNUNET_STATISTICS_create ("mesh", c); + GNUNET_SERVER_suspend (server_handle); /* Scheduled the task to clean up when shutdown is called */ GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "end of run()\n"); + keygen = GNUNET_CRYPTO_rsa_key_create_start (keyfile, &key_generation_cb, NULL); + GNUNET_free (keyfile); } + /** * The main function for the mesh service. * diff --git a/src/nse/gnunet-service-nse.c b/src/nse/gnunet-service-nse.c index 3031e68532..435f227744 100644 --- a/src/nse/gnunet-service-nse.c +++ b/src/nse/gnunet-service-nse.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) + (C) 2009, 2010, 2011, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -304,6 +304,16 @@ static struct GNUNET_PeerIdentity my_identity; */ static uint64_t my_proof; +/** + * Handle to this serivce's server. + */ +static struct GNUNET_SERVER_Handle *srv; + +/** + * Hostkey generation context + */ +static struct GNUNET_CRYPTO_RsaKeyGenerationContext *keygen; + /** * Initialize a message to clients with the current network @@ -576,7 +586,7 @@ transmit_ready (void *cls, size_t size, void *buf) GNUNET_SCHEDULER_add_delayed (get_transmit_delay (0), &transmit_task_cb, peer_entry); } - if ((ntohl (size_estimate_messages[idx].hop_count) == 0) && + if ((0 == ntohl (size_estimate_messages[idx].hop_count)) && (GNUNET_SCHEDULER_NO_TASK != proof_task)) { GNUNET_STATISTICS_update (stats, @@ -584,7 +594,7 @@ transmit_ready (void *cls, size_t size, void *buf) 1, GNUNET_NO); return 0; } - if (ntohs (size_estimate_messages[idx].header.size) == 0) + if (0 == ntohs (size_estimate_messages[idx].header.size)) { GNUNET_STATISTICS_update (stats, "# flood messages not generated (lack of history)", @@ -661,7 +671,8 @@ update_network_size_estimate () * @param ts timestamp to use */ static void -setup_flood_message (unsigned int slot, struct GNUNET_TIME_Absolute ts) +setup_flood_message (unsigned int slot, + struct GNUNET_TIME_Absolute ts) { struct GNUNET_NSE_FloodMessage *fm; uint32_t matching_bits; @@ -699,7 +710,9 @@ setup_flood_message (unsigned int slot, struct GNUNET_TIME_Absolute ts) * @return GNUNET_OK (continue to iterate) */ static int -schedule_current_round (void *cls, const struct GNUNET_HashCode * key, void *value) +schedule_current_round (void *cls, + const struct GNUNET_HashCode * key, + void *value) { struct NSEPeerEntry *peer_entry = value; struct GNUNET_TIME_Relative delay; @@ -958,7 +971,7 @@ update_flood_times (void *cls, const struct GNUNET_HashCode * key, void *value) struct NSEPeerEntry *peer_entry = value; struct GNUNET_TIME_Relative delay; - if (peer_entry->th != NULL) + if (NULL != peer_entry->th) return GNUNET_OK; /* already active */ if (peer_entry == exclude) return GNUNET_OK; /* trigger of the update */ @@ -966,14 +979,14 @@ update_flood_times (void *cls, const struct GNUNET_HashCode * key, void *value) { /* still stuck in previous round, no point to update, check that * we are active here though... */ - if (GNUNET_SCHEDULER_NO_TASK == peer_entry->transmit_task && - NULL == peer_entry->th) + if ( (GNUNET_SCHEDULER_NO_TASK == peer_entry->transmit_task) && + (NULL == peer_entry->th) ) { GNUNET_break (0); } return GNUNET_OK; } - if (peer_entry->transmit_task != GNUNET_SCHEDULER_NO_TASK) + if (GNUNET_SCHEDULER_NO_TASK != peer_entry->transmit_task) { GNUNET_SCHEDULER_cancel (peer_entry->transmit_task); peer_entry->transmit_task = GNUNET_SCHEDULER_NO_TASK; @@ -1099,7 +1112,7 @@ handle_p2p_size_estimate (void *cls, const struct GNUNET_PeerIdentity *peer, GNUNET_SCHEDULER_cancel (peer_entry->transmit_task); peer_entry->transmit_task = GNUNET_SCHEDULER_NO_TASK; } - if (peer_entry->th != NULL) + if (NULL != peer_entry->th) { GNUNET_CORE_notify_transmit_ready_cancel (peer_entry->th); peer_entry->th = NULL; @@ -1228,7 +1241,7 @@ handle_core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) GNUNET_SCHEDULER_cancel (pos->transmit_task); pos->transmit_task = GNUNET_SCHEDULER_NO_TASK; } - if (pos->th != NULL) + if (NULL != pos->th) { GNUNET_CORE_notify_transmit_ready_cancel (pos->th); pos->th = NULL; @@ -1247,44 +1260,49 @@ handle_core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - if (flood_task != GNUNET_SCHEDULER_NO_TASK) + if (GNUNET_SCHEDULER_NO_TASK != flood_task) { GNUNET_SCHEDULER_cancel (flood_task); flood_task = GNUNET_SCHEDULER_NO_TASK; } - if (proof_task != GNUNET_SCHEDULER_NO_TASK) + if (GNUNET_SCHEDULER_NO_TASK != proof_task) { GNUNET_SCHEDULER_cancel (proof_task); proof_task = GNUNET_SCHEDULER_NO_TASK; write_proof (); /* remember progress */ } - if (nc != NULL) + if (NULL != keygen) + { + GNUNET_CRYPTO_rsa_key_create_stop (keygen); + keygen = NULL; + } + if (NULL != nc) { GNUNET_SERVER_notification_context_destroy (nc); nc = NULL; } - if (coreAPI != NULL) + if (NULL != coreAPI) { GNUNET_CORE_disconnect (coreAPI); coreAPI = NULL; } - if (stats != NULL) + if (NULL != stats) { GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; } - if (peers != NULL) + if (NULL != peers) { GNUNET_CONTAINER_multihashmap_destroy (peers); peers = NULL; } - if (my_private_key != NULL) + if (NULL != my_private_key) { GNUNET_CRYPTO_rsa_key_free (my_private_key); my_private_key = NULL; } #if ENABLE_HISTOGRAM - if (wh != NULL) + if (NULL != wh) { GNUNET_break (GNUNET_OK == GNUNET_BIO_write_close (wh)); wh = NULL; @@ -1341,19 +1359,17 @@ core_init (void *cls, struct GNUNET_CORE_Handle *server, /** - * Handle network size estimate clients. + * Callback for hostkey read/generation * - * @param cls closure - * @param server the initialized server - * @param c configuration to use + * @param cls NULL + * @param pk the private key + * @param emsg error message */ static void -run (void *cls, struct GNUNET_SERVER_Handle *server, - const struct GNUNET_CONFIGURATION_Handle *c) +key_generation_cb (void *cls, + struct GNUNET_CRYPTO_RsaPrivateKey *pk, + const char *emsg) { - char *keyfile; - char *proof; - static const struct GNUNET_SERVER_MessageHandler handlers[] = { {&handle_start_message, NULL, GNUNET_MESSAGE_TYPE_NSE_START, sizeof (struct GNUNET_MessageHeader)}, @@ -1364,52 +1380,18 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, sizeof (struct GNUNET_NSE_FloodMessage)}, {NULL, 0, 0} }; - cfg = c; - - if ((GNUNET_OK != - GNUNET_CONFIGURATION_get_value_time (cfg, "NSE", "INTERVAL", - &gnunet_nse_interval)) || - (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_time (cfg, "NSE", "WORKDELAY", - &proof_find_delay)) || - (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (cfg, "NSE", "WORKBITS", - &nse_work_required))) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _ - ("NSE service is lacking key configuration settings. Exiting.\n")); - GNUNET_SCHEDULER_shutdown (); - return; - } - if (nse_work_required >= sizeof (struct GNUNET_HashCode) * 8) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Invalid work requirement for NSE service. Exiting.\n")); - GNUNET_SCHEDULER_shutdown (); - return; - } - + char *proof; - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_filename (cfg, "GNUNETD", "HOSTKEY", - &keyfile)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _ - ("NSE service is lacking key configuration settings. Exiting.\n")); - GNUNET_SCHEDULER_shutdown (); - return; - } - my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); - GNUNET_free (keyfile); - if (my_private_key == NULL) + keygen = NULL; + if (NULL == pk) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("NSE service could not access hostkey. Exiting.\n")); + _("NSE service could not access hostkey: %s\n"), + emsg); GNUNET_SCHEDULER_shutdown (); return; } + my_private_key = pk; GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key); GNUNET_CRYPTO_hash (&my_public_key, sizeof (my_public_key), &my_identity.hashPubKey); @@ -1419,11 +1401,8 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("NSE service is lacking key configuration settings. Exiting.\n")); - if (my_private_key != NULL) - { - GNUNET_CRYPTO_rsa_key_free (my_private_key); - my_private_key = NULL; - } + GNUNET_CRYPTO_rsa_key_free (my_private_key); + my_private_key = NULL; GNUNET_SCHEDULER_shutdown (); return; } @@ -1437,8 +1416,8 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, &find_proof, NULL); peers = GNUNET_CONTAINER_multihashmap_create (128); - GNUNET_SERVER_add_handlers (server, handlers); - nc = GNUNET_SERVER_notification_context_create (server, 1); + GNUNET_SERVER_add_handlers (srv, handlers); + nc = GNUNET_SERVER_notification_context_create (srv, 1); /* Connect to core service and register core handlers */ coreAPI = GNUNET_CORE_connect (cfg, /* Main configuration */ NULL, /* Closure passed to functions */ @@ -1450,8 +1429,11 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, NULL, /* Don't want notified about all outbound messages */ GNUNET_NO, /* For header only outbound notification */ core_handlers); /* Register these handlers */ - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, - NULL); + if (NULL == coreAPI) + { + GNUNET_SCHEDULER_shutdown (); + return; + } #if ENABLE_HISTOGRAM if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename (cfg, "NSE", "HISTOGRAM", &proof)) @@ -1460,17 +1442,70 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, GNUNET_free (proof); } #endif - if (coreAPI == NULL) + stats = GNUNET_STATISTICS_create ("nse", cfg); + GNUNET_SERVER_resume (srv); +} + + +/** + * Handle network size estimate clients. + * + * @param cls closure + * @param server the initialized server + * @param c configuration to use + */ +static void +run (void *cls, + struct GNUNET_SERVER_Handle *server, + const struct GNUNET_CONFIGURATION_Handle *c) +{ + char *keyfile; + + cfg = c; + srv = server; + if ((GNUNET_OK != + GNUNET_CONFIGURATION_get_value_time (cfg, "NSE", "INTERVAL", + &gnunet_nse_interval)) || + (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_time (cfg, "NSE", "WORKDELAY", + &proof_find_delay)) || + (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_number (cfg, "NSE", "WORKBITS", + &nse_work_required))) { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _ + ("NSE service is lacking key configuration settings. Exiting.\n")); GNUNET_SCHEDULER_shutdown (); return; } - stats = GNUNET_STATISTICS_create ("nse", cfg); + if (nse_work_required >= sizeof (struct GNUNET_HashCode) * 8) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Invalid work requirement for NSE service. Exiting.\n")); + GNUNET_SCHEDULER_shutdown (); + return; + } + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_filename (cfg, "GNUNETD", "HOSTKEY", + &keyfile)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _ + ("NSE service is lacking key configuration settings. Exiting.\n")); + GNUNET_SCHEDULER_shutdown (); + return; + } + GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, + NULL); + GNUNET_SERVER_suspend (srv); + keygen = GNUNET_CRYPTO_rsa_key_create_start (keyfile, &key_generation_cb, NULL); + GNUNET_free (keyfile); } /** - * The main function for the statistics service. + * The main function for the network size estimation service. * * @param argc number of arguments from the command line * @param argv command line arguments diff --git a/src/peerinfo-tool/gnunet-peerinfo.c b/src/peerinfo-tool/gnunet-peerinfo.c index d3637af44c..ddadcddd2c 100644 --- a/src/peerinfo-tool/gnunet-peerinfo.c +++ b/src/peerinfo-tool/gnunet-peerinfo.c @@ -394,10 +394,10 @@ print_peer_info (void *cls, const struct GNUNET_PeerIdentity *peer, struct GNUNET_CRYPTO_HashAsciiEncoded enc; struct PrintContext *pc; - if (peer == NULL) + if (NULL == peer) { pic = NULL; /* end of iteration */ - if (err_msg != NULL) + if (NULL != err_msg) { FPRINTF (stderr, _("Error in communication with PEERINFO service: %s\n"), @@ -812,13 +812,14 @@ run (void *cls, char *const *args, const char *cfgfile, char *fn; cfg = c; - if (args[0] != NULL) + if (NULL != args[0]) { - FPRINTF (stderr, _("Invalid command line argument `%s'\n"), args[0]); + FPRINTF (stderr, + _("Invalid command line argument `%s'\n"), + args[0]); return; } - peerinfo = GNUNET_PEERINFO_connect (cfg); - if (peerinfo == NULL) + if (NULL == (peerinfo = GNUNET_PEERINFO_connect (cfg))) { FPRINTF (stderr, "%s", _("Could not access PEERINFO service. Exiting.\n")); return; @@ -834,7 +835,6 @@ run (void *cls, char *const *args, const char *cfgfile, "GNUNETD", "HOSTKEYFILE"); return; } - if (NULL == (priv = GNUNET_CRYPTO_rsa_key_create_from_file (fn))) { FPRINTF (stderr, _("Loading hostkey from `%s' failed.\n"), fn); diff --git a/src/transport/gnunet-service-transport.c b/src/transport/gnunet-service-transport.c index 677d0033c9..f9a4c7b9ec 100644 --- a/src/transport/gnunet-service-transport.c +++ b/src/transport/gnunet-service-transport.c @@ -62,6 +62,16 @@ struct GNUNET_PeerIdentity GST_my_identity; struct GNUNET_PEERINFO_Handle *GST_peerinfo; /** + * Hostkey generation context + */ +struct GNUNET_CRYPTO_RsaKeyGenerationContext *GST_keygen; + +/** + * Handle to our service's server. + */ +static struct GNUNET_SERVER_Handle *GST_server; + +/** * Our public key. */ struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded GST_my_public_key; @@ -271,7 +281,7 @@ plugin_env_receive_callback (void *cls, const struct GNUNET_PeerIdentity *peer, break; case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_ACK: GST_neighbours_handle_session_ack (message, peer, &address, session, ats, - ats_count); + ats_count); break; case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_DISCONNECT: GST_neighbours_handle_disconnect_message (peer, message); @@ -539,6 +549,11 @@ neighbours_address_notification (void *cls, static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { + if (NULL != GST_keygen) + { + GNUNET_CRYPTO_rsa_key_create_stop (GST_keygen); + GST_keygen = NULL; + } GST_neighbours_stop (); GST_validation_stop (); GST_plugins_unload (); @@ -549,17 +564,17 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GST_blacklist_stop (); GST_hello_stop (); - if (GST_peerinfo != NULL) + if (NULL != GST_peerinfo) { GNUNET_PEERINFO_disconnect (GST_peerinfo); GST_peerinfo = NULL; } - if (GST_stats != NULL) + if (NULL != GST_stats) { GNUNET_STATISTICS_destroy (GST_stats, GNUNET_NO); GST_stats = NULL; } - if (GST_my_private_key != NULL) + if (NULL != GST_my_private_key) { GNUNET_CRYPTO_rsa_key_free (GST_my_private_key); GST_my_private_key = NULL; @@ -568,41 +583,32 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) /** - * Initiate transport service. + * Callback for hostkey read/generation * - * @param cls closure - * @param server the initialized server - * @param c configuration to use + * @param cls NULL + * @param pk the private key + * @param emsg error message */ static void -run (void *cls, struct GNUNET_SERVER_Handle *server, - const struct GNUNET_CONFIGURATION_Handle *c) +key_generation_cb (void *cls, + struct GNUNET_CRYPTO_RsaPrivateKey *pk, + const char *emsg) { - char *keyfile; struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded tmp; - /* setup globals */ - GST_cfg = c; - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_filename (c, "GNUNETD", "HOSTKEY", - &keyfile)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _ - ("Transport service is lacking key configuration settings. Exiting.\n")); - GNUNET_SCHEDULER_shutdown (); - return; - } - GST_my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); - GNUNET_free (keyfile); - if (GST_my_private_key == NULL) + + GST_keygen = NULL; + if (NULL == pk) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Transport service could not access hostkey. Exiting.\n")); + _("Transport service could not access hostkey: %s. Exiting.\n"), + emsg); GNUNET_SCHEDULER_shutdown (); return; } - GST_stats = GNUNET_STATISTICS_create ("transport", c); - GST_peerinfo = GNUNET_PEERINFO_connect (c); + GST_my_private_key = pk; + + GST_stats = GNUNET_STATISTICS_create ("transport", GST_cfg); + GST_peerinfo = GNUNET_PEERINFO_connect (GST_cfg); memset (&GST_my_public_key, '\0', sizeof (GST_my_public_key)); memset (&tmp, '\0', sizeof (tmp)); GNUNET_CRYPTO_rsa_key_get_public (GST_my_private_key, &GST_my_public_key); @@ -614,7 +620,7 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); - if (GST_peerinfo == NULL) + if (NULL == GST_peerinfo) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not access PEERINFO service. Exiting.\n")); @@ -625,7 +631,7 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, /* start subsystems */ GST_hello_start (&process_hello_update, NULL); GNUNET_assert (NULL != GST_hello_get()); - GST_blacklist_start (server); + GST_blacklist_start (GST_server); GST_ats = GNUNET_ATS_scheduling_init (GST_cfg, &ats_request_address_change, NULL); GST_plugins_load (&plugin_env_receive_callback, @@ -636,8 +642,47 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, &neighbours_connect_notification, &neighbours_disconnect_notification, &neighbours_address_notification); - GST_clients_start (server); + GST_clients_start (GST_server); GST_validation_start (); + GNUNET_SERVER_resume (GST_server); +} + + +/** + * Initiate transport service. + * + * @param cls closure + * @param server the initialized server + * @param c configuration to use + */ +static void +run (void *cls, struct GNUNET_SERVER_Handle *server, + const struct GNUNET_CONFIGURATION_Handle *c) +{ + char *keyfile; + + /* setup globals */ + GST_cfg = c; + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_filename (c, "GNUNETD", "HOSTKEY", + &keyfile)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _ + ("Transport service is lacking key configuration settings. Exiting.\n")); + GNUNET_SCHEDULER_shutdown (); + return; + } + GST_server = server; + GNUNET_SERVER_suspend (server); + GST_keygen = GNUNET_CRYPTO_rsa_key_create_start (keyfile, &key_generation_cb, NULL); + GNUNET_free (keyfile); + if (NULL == GST_keygen) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Transport service is unable to access hostkey. Exiting.\n")); + GNUNET_SCHEDULER_shutdown (); + } } diff --git a/src/transport/test_plugin_transport.c b/src/transport/test_plugin_transport.c index e6a016c512..6882f919c3 100644 --- a/src/transport/test_plugin_transport.c +++ b/src/transport/test_plugin_transport.c @@ -139,6 +139,7 @@ struct AddressWrapper char *addrstring; }; + static void end () { @@ -186,6 +187,7 @@ end () } } + static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { @@ -245,6 +247,7 @@ end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) ok = 1; } + static void wait_end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { @@ -290,6 +293,7 @@ env_receive (void *cls, static int got_reply; + /** * Take the given address and append it to the set of results sent back to * the client. @@ -435,7 +439,8 @@ env_notify_address (void *cls, } } -struct GNUNET_ATS_Information + +static struct GNUNET_ATS_Information env_get_address_type (void *cls, const struct sockaddr *addr, size_t addrlen) @@ -446,19 +451,22 @@ env_get_address_type (void *cls, return ats; } -const struct GNUNET_MessageHeader * -env_get_our_hello (void) + +static const struct GNUNET_MessageHeader * +env_get_our_hello () { return (const struct GNUNET_MessageHeader *) hello; } -void env_session_end (void *cls, - const struct GNUNET_PeerIdentity *peer, - struct Session * session) -{ +static void +env_session_end (void *cls, + const struct GNUNET_PeerIdentity *peer, + struct Session * session) +{ } + static void setup_plugin_environment () { @@ -482,6 +490,7 @@ handle_helper_message (void *cls, void *client, return GNUNET_OK; } + /** * Runs the test. * @@ -502,33 +511,31 @@ run (void *cls, char *const *args, const char *cfgfile, cfg = c; /* parse configuration */ - if ((GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (c, - "TRANSPORT", - "NEIGHBOUR_LIMIT", - &tneigh)) || - (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (c, - "GNUNETD", "HOSTKEY", - &keyfile))) + if ( (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (c, + "TRANSPORT", + "NEIGHBOUR_LIMIT", + &tneigh)) || + (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (c, + "GNUNETD", "HOSTKEY", + &keyfile))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Transport service is lacking key configuration settings. Exiting.\n")); - return; } - stats = GNUNET_STATISTICS_create ("transport", cfg); - if (NULL == stats) + if (NULL == (stats = GNUNET_STATISTICS_create ("transport", cfg))) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Could not create statistics. Exiting.\n")); - end_badly_now (); - return; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Could not create statistics. Exiting.\n")); + end_badly_now (); + return; } max_connect_per_transport = (uint32_t) tneigh; my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); GNUNET_free (keyfile); - if (my_private_key == NULL) + if (NULL == my_private_key) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Transport service could not access hostkey. Exiting.\n")); @@ -638,7 +645,7 @@ run (void *cls, char *const *args, const char *cfgfile, /** - * The main function for the transport service. + * The main function for the test * * @param argc number of arguments from the command line * @param argv command line arguments @@ -656,20 +663,19 @@ main (int argc, char *const *argv) "test_plugin_transport", "-c", "test_plugin_transport_data.conf", - "-L", "WARNING", NULL }; GNUNET_log_setup ("test-plugin-transport", "WARNING", NULL); ok = 1; /* set to fail */ - ret = (GNUNET_OK == GNUNET_PROGRAM_run (5, - argv_prog, - "test-plugin-transport", - "testcase", - options, - &run, - (void *) argv)) ? ok : 1; + ret = (GNUNET_OK == GNUNET_PROGRAM_run (3, + argv_prog, + "test-plugin-transport", + "testcase", + options, + &run, + (void *) argv)) ? ok : 1; GNUNET_DISK_directory_remove ("/tmp/test-gnunetd-plugin-transport"); return ret; } diff --git a/src/util/crypto_random.c b/src/util/crypto_random.c index dbf71d78a4..8dce1080cc 100644 --- a/src/util/crypto_random.c +++ b/src/util/crypto_random.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2001, 2002, 2003, 2004, 2005, 2006 Christian Grothoff (and other contributing authors) + (C) 2001, 2002, 2003, 2004, 2005, 2006, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -34,6 +34,14 @@ #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall) + +/** + * GNUNET_YES if we are using a 'weak' (low-entropy) PRNG. + */ +static int weak_random; + + + /* TODO: ndurner, move this to plibc? */ /* The code is derived from glibc, obviously */ #if MINGW @@ -49,14 +57,18 @@ #undef RAND_MAX #endif #define RAND_MAX 0x7fffffff /* Hopefully this is correct */ + + static int32_t glibc_weak_rand32_state = 1; + void glibc_weak_srand32 (int32_t s) { glibc_weak_rand32_state = s; } + int32_t glibc_weak_rand32 () { @@ -74,11 +86,12 @@ glibc_weak_rand32 () * @return number between 0 and 1. */ static double -weak_random () +get_weak_random () { return ((double) RANDOM () / RAND_MAX); } + /** * Seed a weak random generator. Only GNUNET_CRYPTO_QUALITY_WEAK-mode generator * can be seeded. @@ -91,6 +104,7 @@ GNUNET_CRYPTO_seed_weak_random (int32_t seed) SRANDOM (seed); } + /** * Produce a random value. * @@ -134,7 +148,7 @@ GNUNET_CRYPTO_random_u32 (enum GNUNET_CRYPTO_Quality mode, uint32_t i) while (ret >= ul); return ret % i; case GNUNET_CRYPTO_QUALITY_WEAK: - ret = i * weak_random (); + ret = i * get_weak_random (); if (ret >= i) ret = i - 1; return ret; @@ -211,7 +225,7 @@ GNUNET_CRYPTO_random_u64 (enum GNUNET_CRYPTO_Quality mode, uint64_t max) return ret % max; case GNUNET_CRYPTO_QUALITY_WEAK: - ret = max * weak_random (); + ret = max * get_weak_random (); if (ret >= max) ret = max - 1; return ret; @@ -221,6 +235,19 @@ GNUNET_CRYPTO_random_u64 (enum GNUNET_CRYPTO_Quality mode, uint64_t max) return 0; } + +/** + * Check if we are using weak random number generation. + * + * @return GNUNET_YES if weak number generation is on + */ +int +GNUNET_CRYPTO_random_is_weak () +{ + return weak_random; +} + + /** * This function should only be called in testcases * where strong entropy gathering is not desired @@ -229,6 +256,7 @@ GNUNET_CRYPTO_random_u64 (enum GNUNET_CRYPTO_Quality mode, uint64_t max) void GNUNET_CRYPTO_random_disable_entropy_gathering () { + weak_random = GNUNET_YES; gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0); } @@ -239,6 +267,7 @@ GNUNET_CRYPTO_random_disable_entropy_gathering () */ static struct GNUNET_OS_Process *genproc; + /** * Function called by libgcrypt whenever we are * blocked gathering entropy. diff --git a/src/util/crypto_rsa.c b/src/util/crypto_rsa.c index 4afda1f6e2..8843464a2f 100644 --- a/src/util/crypto_rsa.c +++ b/src/util/crypto_rsa.c @@ -629,11 +629,17 @@ try_read_key (const char *filename) (void) GNUNET_DISK_file_close (fd); return NULL; } + if (0 == fs) + { + GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fd)); + return NULL; + } if (fs > UINT16_MAX) { LOG (GNUNET_ERROR_TYPE_ERROR, - _("File `%s' does not contain a valid private key. Deleting it.\n"), - filename); + _("File `%s' does not contain a valid private key (too long, %llu bytes). Deleting it.\n"), + filename, + (unsigned long long) fs); GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fd)); if (0 != UNLINK (filename)) LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", filename); @@ -648,8 +654,9 @@ try_read_key (const char *filename) (NULL == (ret = GNUNET_CRYPTO_rsa_decode_key ((char *) enc, len)))) { LOG (GNUNET_ERROR_TYPE_ERROR, - _("File `%s' does not contain a valid private key. Deleting it.\n"), - filename); + _("File `%s' does not contain a valid private key (failed decode, %llu bytes). Deleting it.\n"), + filename, + (unsigned long long) fs); GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fd)); if (0 != UNLINK (filename)) LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", filename); @@ -664,6 +671,23 @@ try_read_key (const char *filename) /** + * Wait for a short time (we're trying to lock a file or want + * to give another process a shot at finishing a disk write, etc.). + * Sleeps for 100ms (as that should be long enough for virtually all + * modern systems to context switch and allow another process to do + * some 'real' work). + */ +static void +short_wait () +{ + struct GNUNET_TIME_Relative timeout; + + timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100); + GNUNET_NETWORK_socket_select (NULL, NULL, NULL, timeout); +} + + +/** * Create a new private key by reading it from a file. If the * files does not exist, create a new key and write it to the * file. Caller must free return value. Note that this function @@ -723,7 +747,7 @@ GNUNET_CRYPTO_rsa_key_create_from_file (const char *filename) sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded), GNUNET_YES)) { - sleep (1); + short_wait (1); if (0 == ++cnt % 10) { ec = errno; @@ -781,7 +805,7 @@ GNUNET_CRYPTO_rsa_key_create_from_file (const char *filename) _ ("This may be ok if someone is currently generating a hostkey.\n")); } - sleep (1); + short_wait (1); continue; } if (GNUNET_YES != GNUNET_DISK_file_test (filename)) @@ -817,7 +841,7 @@ GNUNET_CRYPTO_rsa_key_create_from_file (const char *filename) _ ("This may be ok if someone is currently generating a hostkey.\n")); } - sleep (2); /* wait a bit longer! */ + short_wait (1); /* wait a bit longer! */ continue; } break; @@ -996,6 +1020,7 @@ GNUNET_CRYPTO_rsa_key_create_start (const char *filename, { struct GNUNET_CRYPTO_RsaKeyGenerationContext *gc; struct GNUNET_CRYPTO_RsaPrivateKey *pk; + const char *weak_random; if (NULL != (pk = try_read_key (filename))) { @@ -1023,13 +1048,18 @@ GNUNET_CRYPTO_rsa_key_create_start (const char *filename, GNUNET_free (gc); return NULL; } + weak_random = NULL; + if (GNUNET_YES == + GNUNET_CRYPTO_random_is_weak ()) + weak_random = "-w"; gc->gnunet_rsa = GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_ERR, NULL, gc->gnunet_rsa_out, "gnunet-rsa", - "gnunet-rsa", + "gnunet-rsa", gc->filename, + weak_random, NULL); if (NULL == gc->gnunet_rsa) { diff --git a/src/util/gnunet-rsa.c b/src/util/gnunet-rsa.c index 61e1b66dff..e9fbf15dff 100644 --- a/src/util/gnunet-rsa.c +++ b/src/util/gnunet-rsa.c @@ -43,6 +43,11 @@ static int print_peer_identity; */ static int print_short_identity; +/** + * Use weak random number generator for key generation. + */ +static int weak_random; + /** * The private information of an RSA key pair. @@ -104,6 +109,8 @@ run (void *cls, char *const *args, const char *cfgfile, fprintf (stderr, _("No hostkey file specified on command line\n")); return; } + if (0 != weak_random) + GNUNET_CRYPTO_random_disable_entropy_gathering (); pk = GNUNET_CRYPTO_rsa_key_create_from_file (args[0]); if (NULL == pk) return; @@ -159,6 +166,9 @@ main (int argc, char *const *argv) { 's', "print-short-identity", NULL, gettext_noop ("print the short hash of the public key in ASCII format"), 0, &GNUNET_GETOPT_set_one, &print_short_identity }, + { 'w', "weak-random", NULL, + gettext_noop ("use insecure, weak random number generator for key generation (for testing only)"), + 0, &GNUNET_GETOPT_set_one, &weak_random }, GNUNET_GETOPT_OPTION_END }; diff --git a/src/util/server.c b/src/util/server.c index ff45846776..4622e0779c 100644 --- a/src/util/server.c +++ b/src/util/server.c @@ -334,43 +334,6 @@ process_listen_socket (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) /** - * Add a listen task with the scheduler for this server. - * - * @param server handle to our server for which we are adding the listen - * socket - */ -static void -schedule_listen_task (struct GNUNET_SERVER_Handle *server) -{ - struct GNUNET_NETWORK_FDSet *r; - unsigned int i; - - if (NULL == server->listen_sockets[0]) - return; /* nothing to do, no listen sockets! */ - if (NULL == server->listen_sockets[1]) - { - /* simplified method: no fd set needed; this is then much simpler and - much more efficient */ - server->listen_task = - GNUNET_SCHEDULER_add_read_net_with_priority (GNUNET_TIME_UNIT_FOREVER_REL, - GNUNET_SCHEDULER_PRIORITY_HIGH, - server->listen_sockets[0], - &process_listen_socket, server); - return; - } - r = GNUNET_NETWORK_fdset_create (); - i = 0; - while (NULL != server->listen_sockets[i]) - GNUNET_NETWORK_fdset_set (r, server->listen_sockets[i++]); - server->listen_task = - GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH, - GNUNET_TIME_UNIT_FOREVER_REL, r, NULL, - &process_listen_socket, server); - GNUNET_NETWORK_fdset_destroy (r); -} - - -/** * Scheduler says our listen socket is ready. Process it! * * @param cls handle to our server for which we are processing the listen @@ -389,7 +352,7 @@ process_listen_socket (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) { /* ignore shutdown, someone else will take care of it! */ - schedule_listen_task (server); + GNUNET_SERVER_resume (server); return; } i = 0; @@ -412,7 +375,7 @@ process_listen_socket (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) i++; } /* listen for more! */ - schedule_listen_task (server); + GNUNET_SERVER_resume (server); } @@ -536,7 +499,7 @@ GNUNET_SERVER_create_with_sockets (GNUNET_CONNECTION_AccessCheck access, server->access_cls = access_cls; server->require_found = require_found; if (NULL != lsocks) - schedule_listen_task (server); + GNUNET_SERVER_resume (server); return server; } @@ -671,6 +634,58 @@ test_monitor_clients (struct GNUNET_SERVER_Handle *server) /** + * Suspend accepting connections from the listen socket temporarily. + * + * @param server server to stop accepting connections. + */ +void +GNUNET_SERVER_suspend (struct GNUNET_SERVER_Handle *server) +{ + if (GNUNET_SCHEDULER_NO_TASK != server->listen_task) + { + GNUNET_SCHEDULER_cancel (server->listen_task); + server->listen_task = GNUNET_SCHEDULER_NO_TASK; + } +} + + +/** + * Resume accepting connections from the listen socket. + * + * @param server server to stop accepting connections. + */ +void +GNUNET_SERVER_resume (struct GNUNET_SERVER_Handle *server) +{ + struct GNUNET_NETWORK_FDSet *r; + unsigned int i; + + if (NULL == server->listen_sockets[0]) + return; /* nothing to do, no listen sockets! */ + if (NULL == server->listen_sockets[1]) + { + /* simplified method: no fd set needed; this is then much simpler and + much more efficient */ + server->listen_task = + GNUNET_SCHEDULER_add_read_net_with_priority (GNUNET_TIME_UNIT_FOREVER_REL, + GNUNET_SCHEDULER_PRIORITY_HIGH, + server->listen_sockets[0], + &process_listen_socket, server); + return; + } + r = GNUNET_NETWORK_fdset_create (); + i = 0; + while (NULL != server->listen_sockets[i]) + GNUNET_NETWORK_fdset_set (r, server->listen_sockets[i++]); + server->listen_task = + GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH, + GNUNET_TIME_UNIT_FOREVER_REL, r, NULL, + &process_listen_socket, server); + GNUNET_NETWORK_fdset_destroy (r); +} + + +/** * Stop the listen socket and get ready to shutdown the server * once only 'monitor' clients are left. * |