📄 identity.c
字号:
&hosts_[i]->identity, sizeof (GNUNET_PeerIdentity)))) { entry = hosts_[i]; for (j = 0; j < entry->protocolCount; j++) { if (protocol == entry->protocols[j]) { entry->protocols[j] = entry->protocols[entry->protocolCount - 1]; GNUNET_array_grow (entry->protocols, entry->protocolCount, entry->protocolCount - 1); } } for (j = 0; j < entry->helloCount; j++) { if (protocol == ntohs (entry->hellos[j]->protocol)) { GNUNET_free (entry->hellos[j]); entry->hellos[j] = entry->hellos[entry->helloCount - 1]; GNUNET_array_grow (entry->hellos, entry->helloCount, entry->helloCount - 1); } } /* also remove hello file itself */ fn = getHostFileName (identity, protocol); if (0 != UNLINK (fn)) GNUNET_GE_LOG_STRERROR_FILE (ectx, GNUNET_GE_WARNING | GNUNET_GE_USER | GNUNET_GE_BULK, "unlink", fn); GNUNET_free (fn); if (entry->protocolCount == 0) { if (entry->helloCount > 0) { for (j = 0; j < entry->helloCount; j++) GNUNET_free (entry->hellos[j]); GNUNET_array_grow (entry->hellos, entry->helloCount, 0); } hosts_[i] = hosts_[--numberOfHosts_]; GNUNET_free (entry); } GNUNET_mutex_unlock (lock_); GNUNET_GE_ASSERT (ectx, numberOfHosts_ <= sizeOfHosts_); return; /* deleted */ } } GNUNET_mutex_unlock (lock_);}/** * Bind a host address (hello) to a hostId. * @param msg the verified (!) hello message */static voidbindAddress (const GNUNET_MessageHello * msg){ char *fn; char *buffer; GNUNET_MessageHello *oldMsg; int size; HostEntry *host; int i; GNUNET_PeerIdentity have; getPeerIdentity (&msg->publicKey, &have); if (0 != memcmp (&have, &msg->senderIdentity, sizeof (GNUNET_PeerIdentity))) { GNUNET_GE_BREAK (NULL, 0); return; } GNUNET_GE_ASSERT (ectx, numberOfHosts_ <= sizeOfHosts_); GNUNET_GE_ASSERT (ectx, msg != NULL); fn = getHostFileName (&msg->senderIdentity, ntohs (msg->protocol)); buffer = GNUNET_malloc (GNUNET_MAX_BUFFER_SIZE); if (GNUNET_disk_file_test (ectx, fn) == GNUNET_YES) { size = GNUNET_disk_file_read (ectx, fn, GNUNET_MAX_BUFFER_SIZE, buffer); if (size >= sizeof (GNUNET_MessageHello)) { oldMsg = (GNUNET_MessageHello *) buffer; if ((unsigned int) size == GNUNET_sizeof_hello (oldMsg)) { if (ntohl (oldMsg->expiration_time) > ntohl (msg->expiration_time)) { GNUNET_free (fn); GNUNET_free (buffer); return; /* have more recent hello in stock */ } } } } GNUNET_disk_file_write (ectx, fn, msg, GNUNET_sizeof_hello (msg), "644"); GNUNET_free (fn); GNUNET_free (buffer); GNUNET_mutex_lock (lock_); addHostToKnown (&msg->senderIdentity, ntohs (msg->protocol)); host = findHost (&msg->senderIdentity); GNUNET_GE_ASSERT (ectx, host != NULL); for (i = 0; i < host->helloCount; i++) { if (msg->protocol == host->hellos[i]->protocol) { GNUNET_free (host->hellos[i]); host->hellos[i] = NULL; break; } } if (i == host->helloCount) GNUNET_array_grow (host->hellos, host->helloCount, host->helloCount + 1); host->hellos[i] = GNUNET_malloc (GNUNET_sizeof_hello (msg)); memcpy (host->hellos[i], msg, GNUNET_sizeof_hello (msg)); GNUNET_mutex_unlock (lock_); GNUNET_GE_ASSERT (ectx, numberOfHosts_ <= sizeOfHosts_);}/** * Obtain the public key and address of a known host. If no specific * protocol is specified (GNUNET_TRANSPORT_PROTOCOL_NUMBER_ANY), hellos for cheaper * protocols are returned with preference (randomness!). * * @param hostId the host id * @param protocol the protocol that we need, * GNUNET_TRANSPORT_PROTOCOL_NUMBER_ANY if we do not care which protocol * @param tryTemporaryList is it ok to check the unverified hellos? * @param result where to store the result * @returns GNUNET_SYSERR on failure, GNUNET_OK on success */static GNUNET_MessageHello *identity2Hello (const GNUNET_PeerIdentity * hostId, unsigned short protocol, int tryTemporaryList){ GNUNET_MessageHello *result; HostEntry *host; char *fn; GNUNET_MessageHello buffer; GNUNET_PeerIdentity have; int size; int i; int j; GNUNET_GE_ASSERT (ectx, numberOfHosts_ <= sizeOfHosts_); GNUNET_mutex_lock (lock_); if (GNUNET_YES == tryTemporaryList) { /* ok, then first try temporary hosts (in memory, cheapest!) */ for (i = 0; i < MAX_TEMP_HOSTS; i++) { host = &tempHosts[i]; if ((host->helloCount > 0) && (0 == memcmp (hostId, &host->identity, sizeof (GNUNET_PeerIdentity)))) { if (protocol == GNUNET_TRANSPORT_PROTOCOL_NUMBER_ANY) { j = GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK, host->helloCount); } else { j = 0; while ((j < host->helloCount) && (host->protocols[j] != protocol)) j++; } if (j == host->helloCount) { /* not found */ GNUNET_mutex_unlock (lock_); return NULL; } result = GNUNET_malloc (GNUNET_sizeof_hello (host->hellos[j])); memcpy (result, host->hellos[j], GNUNET_sizeof_hello (host->hellos[j])); GNUNET_mutex_unlock (lock_); return result; } } } host = findHost (hostId); if ((host == NULL) || (host->protocolCount == 0)) { GNUNET_mutex_unlock (lock_); return NULL; } if (protocol == GNUNET_TRANSPORT_PROTOCOL_NUMBER_ANY) protocol = host->protocols[GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK, host->protocolCount)]; for (i = 0; i < host->helloCount; i++) { if (ntohs (host->hellos[i]->protocol) == protocol) { result = GNUNET_malloc (GNUNET_sizeof_hello (host->hellos[i])); memcpy (result, host->hellos[i], GNUNET_sizeof_hello (host->hellos[i])); GNUNET_mutex_unlock (lock_); return result; } } /* do direct read */ fn = getHostFileName (hostId, protocol); if (1 != GNUNET_disk_file_test (ectx, fn)) { GNUNET_free (fn); GNUNET_mutex_unlock (lock_); return NULL; } size = GNUNET_disk_file_read (ectx, fn, sizeof (GNUNET_MessageHello), &buffer); if (size != sizeof (GNUNET_MessageHello)) { if (0 == UNLINK (fn)) GNUNET_GE_LOG (ectx, GNUNET_GE_WARNING | GNUNET_GE_USER | GNUNET_GE_BULK, _ ("Removed file `%s' containing invalid HELLO data.\n"), fn); else GNUNET_GE_LOG_STRERROR_FILE (ectx, GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_USER | GNUNET_GE_BULK, "unlink", fn); GNUNET_free (fn); GNUNET_mutex_unlock (lock_); return NULL; } result = GNUNET_malloc (GNUNET_sizeof_hello (&buffer)); size = GNUNET_disk_file_read (ectx, fn, GNUNET_sizeof_hello (&buffer), result); getPeerIdentity (&result->publicKey, &have); if (((unsigned int) size != GNUNET_sizeof_hello (&buffer)) || (0 != memcmp (&have, hostId, sizeof (GNUNET_PeerIdentity))) || (0 != memcmp (&have, &result->senderIdentity, sizeof (GNUNET_PeerIdentity)))) { if (0 == UNLINK (fn)) GNUNET_GE_LOG (ectx, GNUNET_GE_WARNING | GNUNET_GE_USER | GNUNET_GE_BULK, _ ("Removed file `%s' containing invalid HELLO data.\n"), fn); else GNUNET_GE_LOG_STRERROR_FILE (ectx, GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_USER | GNUNET_GE_BULK, "unlink", fn); GNUNET_free (fn); GNUNET_free (result); GNUNET_mutex_unlock (lock_); return NULL; } GNUNET_free (fn); GNUNET_array_grow (host->hellos, host->helloCount, host->helloCount + 1); host->hellos[host->helloCount - 1] = GNUNET_malloc (GNUNET_sizeof_hello (&buffer)); memcpy (host->hellos[host->helloCount - 1], result, GNUNET_sizeof_hello (&buffer)); GNUNET_mutex_unlock (lock_); return result;}/** * @param signer the identity of the host that * presumably signed the message * @param message the signed message * @param size the size of the message * @param sig the signature * @return GNUNET_OK on success, GNUNET_SYSERR on error (verification failed) */static intverifyPeerSignature (const GNUNET_PeerIdentity * signer, const void *message, int size, const GNUNET_RSA_Signature * sig){ GNUNET_MessageHello *hello; int res; hello = identity2Hello (signer, GNUNET_TRANSPORT_PROTOCOL_NUMBER_ANY, GNUNET_YES); if (hello == NULL) {#if DEBUG_IDENTITY GNUNET_EncName enc; IF_GELOG (ectx, GNUNET_GE_INFO | GNUNET_GE_USER | GNUNET_GE_BULK, GNUNET_hash_to_enc (&signer->hashPubKey, &enc)); GNUNET_GE_LOG (ectx, GNUNET_GE_INFO | GNUNET_GE_USER | GNUNET_GE_BULK, _ ("Signature failed verification: peer `%s' not known.\n"), &enc);#endif return GNUNET_SYSERR; } res = GNUNET_RSA_verify (message, size, sig, &hello->publicKey); if (res == GNUNET_SYSERR) GNUNET_GE_LOG (ectx, GNUNET_GE_ERROR | GNUNET_GE_REQUEST | GNUNET_GE_DEVELOPER | GNUNET_GE_USER, _("Signature failed verification: signature invalid.\n")); GNUNET_free (hello); return res;}/** * Blacklist a host. This method is called if a host * failed to respond to a connection attempt. * * @param identity the ID of the peer to blacklist * @param desperation how desperate are we to connect? [0,MAXHOSTS] * @param strict should we reject incoming connection attempts as well? * @return GNUNET_OK on success GNUNET_SYSERR on error */static intblacklistHost (const GNUNET_PeerIdentity * identity, unsigned int desperation, int strict){ GNUNET_EncName hn; HostEntry *entry; int i; GNUNET_CronTime now; GNUNET_GE_ASSERT (ectx, numberOfHosts_ <= sizeOfHosts_); GNUNET_mutex_lock (lock_); entry = findHost (identity); if (entry == NULL) { for (i = 0; i < MAX_TEMP_HOSTS; i++) { if (0 == memcmp (identity, &tempHosts[i].identity, sizeof (GNUNET_PeerIdentity))) { entry = &tempHosts[i]; break; } } } if (entry == NULL) { GNUNET_mutex_unlock (lock_); return GNUNET_SYSERR; } now = GNUNET_get_time (); if ((entry->strict == GNUNET_YES) && (strict == GNUNET_NO)) { /* stronger blacklisting in place! */ GNUNET_mutex_unlock (lock_); return GNUNET_OK; } if (strict) { entry->delta = desperation * GNUNET_CRON_SECONDS; } else { if (entry->until < now) entry->delta = GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK, 1 + desperation * GNUNET_CRON_SECONDS); else entry->delta += GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK, 1 + desperation * GNUNET_CRON_SECONDS); } if (entry->delta > 4 * GNUNET_CRON_HOURS) entry->delta = 4 * GNUNET_CRON_HOURS; entry->until = now + entry->delta; entry->strict = strict; GNUNET_hash_to_enc (&identity->hashPubKey, &hn);#if DEBUG_IDENTITY GNUNET_GE_LOG (ectx, GNUNET_GE_INFO | GNUNET_GE_REQUEST | GNUNET_GE_DEVELOPER, "Blacklisting host `%s' for %llu seconds" " until %llu (strict=%d).\n", &hn, entry->delta / GNUNET_CRON_SECONDS, entry->until, strict);#endif GNUNET_mutex_unlock (lock_); return GNUNET_OK;}/** * Is the host currently blacklisted (i.e. we refuse to talk)? * * @param identity host to check * @return GNUNET_YES if true, else GNUNET_NO */static intisBlacklisted (const GNUNET_PeerIdentity * identity, int strict){ GNUNET_CronTime now; HostEntry *entry; GNUNET_GE_ASSERT (ectx, numberOfHosts_ <= sizeOfHosts_); GNUNET_mutex_lock (lock_); entry = findHost (identity); if (entry == NULL) { GNUNET_mutex_unlock (lock_); return GNUNET_NO; } now = GNUNET_get_time (); if ((now < entry->until) && ((entry->strict == GNUNET_YES) || (strict == GNUNET_NO))) {#if DEBUG_IDENTITY GNUNET_EncName enc; IF_GELOG (ectx, GNUNET_GE_INFO | GNUNET_GE_USER | GNUNET_GE_BULK, GNUNET_hash_to_enc (&identity->hashPubKey, &enc)); GNUNET_GE_LOG (ectx, GNUNET_GE_INFO | GNUNET_GE_USER | GNUNET_GE_BULK, _ ("Peer `%s' is currently strictly blacklisted (for another %llums).\n"), &enc, entry->until - now);#endif GNUNET_mutex_unlock (lock_); return GNUNET_YES; } else { GNUNET_mutex_unlock (lock_); return GNUNET_NO; }}/** * Whitelist a host. This method is called if a host * successfully established a connection. It typically * resets the exponential backoff to the smallest value. * @return GNUNET_OK on success GNUNET_SYSERR on error */static intwhitelistHost (const GNUNET_PeerIdentity * identity){ HostEntry *entry; int i; GNUNET_GE_ASSERT (ectx, numberOfHosts_ <= sizeOfHosts_); GNUNET_mutex_lock (lock_); entry = findHost (identity); if (entry == NULL) { for (i = 0; i < MAX_TEMP_HOSTS; i++) { if (0 == memcmp (identity, &tempHosts[i].identity, sizeof (GNUNET_PeerIdentity))) { entry = &tempHosts[i]; break; } } } if (entry == NULL) { GNUNET_mutex_unlock (lock_); return GNUNET_SYSERR; } entry->delta = 30 * GNUNET_CRON_SECONDS; entry->until = 0; entry->strict = GNUNET_NO; GNUNET_mutex_unlock (lock_); return GNUNET_OK;}/** * Call a method for each known host. * * @param callback the method to call for each host * @param now the time to use for excluding hosts * due to blacklisting, use 0 * to go through all hosts. * @param data an argument to pass to the method * @return the number of hosts matching */static intforEachHost (GNUNET_CronTime now, GNUNET_HostProcessor callback, void *data){ int i; int j; int count;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -