📄 connect.c
字号:
/* This file is part of GNUnet. (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008 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 by the Free Software Foundation; either version 2, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*//** * @file session/connect.c * @brief module responsible for the sessionkey exchange * which establishes a session with another peer * @author Christian Grothoff */#include "platform.h"#include "gnunet_util.h"#include "gnunet_protocols.h"#include "gnunet_transport_service.h"#include "gnunet_identity_service.h"#include "gnunet_pingpong_service.h"#include "gnunet_session_service.h"#include "gnunet_stats_service.h"#include "gnunet_topology_service.h"#include "cache.h"#define hello_HELPER_TABLE_START_SIZE 64#define DEBUG_SESSION GNUNET_NO#define EXTRA_CHECKS ALLOW_EXTRA_CHECKSstatic GNUNET_CoreAPIForPlugins *coreAPI;static GNUNET_Identity_ServiceAPI *identity;static GNUNET_Transport_ServiceAPI *transport;static GNUNET_Pingpong_ServiceAPI *pingpong;static GNUNET_Topology_ServiceAPI *topology;static GNUNET_Stats_ServiceAPI *stats;static struct GNUNET_Mutex *lock;static struct GNUNET_GE_Context *ectx;static int stat_skeySent;static int stat_skeyRejected;static int stat_skeyAccepted;static int stat_sessionEstablished;static int stat_pongSent;static int stat_pingSent;/** * @brief message for session key exchange. */typedef struct{ GNUNET_MessageHeader header; /** * time when this key was created (network byte order) * Must be the first field after the header since * the signature starts at this offset. */ GNUNET_Int32Time creationTime; /** * The encrypted session key. May ALSO contain * encrypted PINGs and PONGs. */ GNUNET_RSA_EncryptedData key; /** * Who is the intended recipient? */ GNUNET_PeerIdentity target; /** * GNUNET_RSA_Signature of the stuff above. */ GNUNET_RSA_Signature signature;} P2P_setkey_MESSAGE;#if DEBUG_SESSION/** * Not thread-safe, only use for debugging! */static const char *printSKEY (const GNUNET_AES_SessionKey * sk){ static char r[512]; static char t[12]; int i; strcpy (r, ""); for (i = 0; i < GNUNET_SESSIONKEY_LEN; i++) { GNUNET_snprintf (t, 12, "%02x", sk->key[i]); strcat (r, t); } return r;}#endif/** * We received a GNUNET_RSA_sign of life from this host. * * @param hostId the peer that gave a GNUNET_RSA_sign of live */static voidnotifyPONG (void *arg){ GNUNET_PeerIdentity *hostId = arg;#if DEBUG_SESSION GNUNET_EncName enc;#endif GNUNET_GE_ASSERT (ectx, hostId != NULL);#if DEBUG_SESSION IF_GELOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_USER | GNUNET_GE_REQUEST, GNUNET_hash_to_enc (&hostId->hashPubKey, &enc)); GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_USER | GNUNET_GE_REQUEST, "Received `%s' from `%s', marking session as up.\n", "PONG", &enc);#endif GNUNET_GE_ASSERT (ectx, hostId != NULL); if (stats != NULL) stats->change (stat_sessionEstablished, 1); coreAPI->p2p_connection_confirm (hostId); GNUNET_free (hostId);}/** * Check if the received session key is properly signed * and if connections to this peer are allowed according * to policy. * * @param hostId the sender of the key * @param sks the session key message * @return GNUNET_SYSERR if invalid, GNUNET_OK if valid, GNUNET_NO if * connections are disallowed */static intverifySKS (const GNUNET_PeerIdentity * hostId, const P2P_setkey_MESSAGE * sks){ const GNUNET_RSA_Signature *signature = &sks->signature; char *limited; GNUNET_EncName enc; if ((sks == NULL) || (hostId == NULL)) { GNUNET_GE_BREAK (ectx, 0); return GNUNET_SYSERR; } /* check if we are allowed to accept connections from that peer */ limited = NULL; GNUNET_GC_get_configuration_value_string (coreAPI->cfg, "GNUNETD", "LIMIT-ALLOW", "", &limited); if (strlen (limited) > 0) { GNUNET_hash_to_enc (&hostId->hashPubKey, &enc); if (NULL == strstr (limited, (char *) &enc)) {#if DEBUG_SESSION GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_USER | GNUNET_GE_REQUEST, "Connection from peer `%s' was rejected (not allowed).\n", &enc);#endif GNUNET_free (limited); return GNUNET_NO; } } GNUNET_free (limited); limited = NULL; GNUNET_GC_get_configuration_value_string (coreAPI->cfg, "GNUNETD", "LIMIT-DENY", "", &limited); if (strlen (limited) > 0) { GNUNET_hash_to_enc (&hostId->hashPubKey, &enc); if (NULL != strstr (limited, (char *) &enc)) {#if DEBUG_SESSION GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_USER | GNUNET_GE_REQUEST, "Connection from peer `%s' was rejected (explicitly denied).\n", &enc);#endif GNUNET_free (limited); return GNUNET_NO; } } GNUNET_free (limited); if (GNUNET_OK != identity->verifyPeerSignature (hostId, sks, sizeof (P2P_setkey_MESSAGE) - sizeof (GNUNET_RSA_Signature), signature)) {#if DEBUG_SESSION GNUNET_EncName enc; IF_GELOG (ectx, GNUNET_GE_INFO | GNUNET_GE_USER | GNUNET_GE_REQUEST, GNUNET_hash_to_enc (&hostId->hashPubKey, &enc)); GNUNET_GE_LOG (ectx, GNUNET_GE_INFO | GNUNET_GE_USER | GNUNET_GE_REQUEST, _("Session key from peer `%s' could not be verified.\n"), &enc);#endif return GNUNET_SYSERR; /*reject! */ } return GNUNET_OK; /* ok */}/** * Force creation of a new Session key for the given host. * * @param hostId the identity of the other host * @param sk the GNUNET_AES_SessionKey to use * @param created the timestamp to use * @param ping optional PING to include (otherwise NULL) * @param pong optional PONG to include (otherwise NULL) * @param ret the address where to write the signed * session key message * @return message on success, NULL on failure */static P2P_setkey_MESSAGE *makeSessionKeySigned (const GNUNET_PeerIdentity * hostId, const GNUNET_AES_SessionKey * sk, GNUNET_Int32Time created, const GNUNET_MessageHeader * ping, const GNUNET_MessageHeader * pong){ GNUNET_MessageHello *foreignHello; int size; P2P_setkey_MESSAGE *msg; char *pt; GNUNET_EncName enc; GNUNET_PeerIdentity hc; GNUNET_GE_ASSERT (ectx, sk != NULL); foreignHello = identity->identity2Hello (hostId, GNUNET_TRANSPORT_PROTOCOL_NUMBER_ANY, GNUNET_YES); /* create and encrypt sessionkey */ if (NULL == foreignHello) { GNUNET_hash_to_enc (&hostId->hashPubKey, &enc); GNUNET_GE_LOG (ectx, GNUNET_GE_INFO | GNUNET_GE_USER | GNUNET_GE_REQUEST, _("Cannot encrypt sessionkey, peer `%s' not known!\n"), &enc); return NULL; /* other host not known */ } identity->getPeerIdentity (&foreignHello->publicKey, &hc); if ((0 != memcmp (&hc, hostId, sizeof (GNUNET_PeerIdentity))) || (0 != memcmp (&hc, &foreignHello->senderIdentity, sizeof (GNUNET_PeerIdentity)))) { GNUNET_GE_BREAK_OP (NULL, 0 == memcmp (&hc, &foreignHello->senderIdentity, sizeof (GNUNET_PeerIdentity))); GNUNET_GE_BREAK_OP (NULL, 0 == memcmp (&hc, hostId, sizeof (GNUNET_PeerIdentity))); GNUNET_GE_BREAK_OP (NULL, 0); GNUNET_free (foreignHello); return NULL; } size = sizeof (P2P_setkey_MESSAGE); if (ping != NULL) size += ntohs (ping->size); if (pong != NULL) size += ntohs (pong->size); if (GNUNET_OK != GNUNET_session_cache_get (&hc, created, sk, size, (GNUNET_MessageHeader **) & msg)) { msg = GNUNET_malloc (size); msg->target = *hostId; if (GNUNET_SYSERR == GNUNET_RSA_encrypt (sk, sizeof (GNUNET_AES_SessionKey), &foreignHello->publicKey, &msg->key)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -