const struct GNUNET_MessageHeader * GNUNET_MQ_extract_nested_mh_ (const struct GNUNET_MessageHeader *mh, uint16_t base_size) { uint16_t whole_size; uint16_t nested_size; const struct GNUNET_MessageHeader *nested_msg; whole_size = ntohs (mh->size); GNUNET_assert (whole_size >= base_size); nested_size = whole_size - base_size; if (0 == nested_size) return NULL; if (nested_size < sizeof (struct GNUNET_MessageHeader)) { GNUNET_break_op (0); return NULL; } nested_msg = (const struct GNUNET_MessageHeader *) ((char *) mh + base_size); if (ntohs (nested_msg->size) != nested_size) { GNUNET_break_op (0); return NULL; } return nested_msg; }
/** * Decode the signature from the data-format back to the "normal", internal * format. * * @param buf the buffer where the public key data is stored * @param len the length of the data in @a buf * @return NULL on error */ struct GNUNET_CRYPTO_rsa_Signature * GNUNET_CRYPTO_rsa_signature_decode (const char *buf, size_t len) { struct GNUNET_CRYPTO_rsa_Signature *sig; int ret; gcry_mpi_t s; sig = GNUNET_new (struct GNUNET_CRYPTO_rsa_Signature); if (0 != gcry_sexp_new (&sig->sexp, buf, len, 0)) { GNUNET_break_op (0); GNUNET_free (sig); return NULL; } /* verify that this is an RSA signature */ ret = key_from_sexp (&s, sig->sexp, "sig-val", "s"); if (0 != ret) ret = key_from_sexp (&s, sig->sexp, "rsa", "s"); if (0 != ret) { /* this is no RSA Signature */ GNUNET_break_op (0); gcry_sexp_release (sig->sexp); GNUNET_free (sig); return NULL; } gcry_mpi_release (s); return sig; }
/** * Parse given JSON object to fixed size data * * @param cls closure, NULL * @param root the json object representing data * @param[out] spec where to write the data * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error */ static int parse_fixed_data (void *cls, json_t *root, struct GNUNET_JSON_Specification *spec) { const char *enc; unsigned int len; if (NULL == (enc = json_string_value (root))) { GNUNET_break_op (0); return GNUNET_SYSERR; } len = strlen (enc); if (((len * 5) / 8) != spec->ptr_size) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, len, spec->ptr, spec->ptr_size)) { GNUNET_break_op (0); return GNUNET_SYSERR; } return GNUNET_OK; }
/** * Function called to obtain the key for a block. * * @param cls closure * @param type block type * @param block block to get the key for * @param block_size number of bytes in @a block * @param key set to the key (query) for the given block * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported * (or if extracting a key from a block of this type does not work) */ static int block_plugin_regex_get_key (void *cls, enum GNUNET_BLOCK_Type type, const void *block, size_t block_size, struct GNUNET_HashCode *key) { switch (type) { case GNUNET_BLOCK_TYPE_REGEX: if (GNUNET_OK != REGEX_BLOCK_get_key (block, block_size, key)) { GNUNET_break_op (0); return GNUNET_NO; } return GNUNET_OK; case GNUNET_BLOCK_TYPE_REGEX_ACCEPT: if (sizeof (struct RegexAcceptBlock) != block_size) { GNUNET_break_op (0); return GNUNET_NO; } *key = ((struct RegexAcceptBlock *) block)->key; return GNUNET_OK; default: GNUNET_break (0); return GNUNET_SYSERR; } }
/** * Parse a DNS MX record. * * @param udp_payload reference to UDP packet * @param udp_payload_length length of @a udp_payload * @param off pointer to the offset of the query to parse in the MX record (to be * incremented by the size of the record), unchanged on error * @return the parsed MX record, NULL on error */ struct GNUNET_DNSPARSER_MxRecord * GNUNET_DNSPARSER_parse_mx (const char *udp_payload, size_t udp_payload_length, size_t *off) { struct GNUNET_DNSPARSER_MxRecord *mx; uint16_t mxpref; size_t old_off; old_off = *off; if (*off + sizeof (uint16_t) > udp_payload_length) { GNUNET_break_op (0); return NULL; } GNUNET_memcpy (&mxpref, &udp_payload[*off], sizeof (uint16_t)); (*off) += sizeof (uint16_t); mx = GNUNET_new (struct GNUNET_DNSPARSER_MxRecord); mx->preference = ntohs (mxpref); mx->mxhost = GNUNET_DNSPARSER_parse_name (udp_payload, udp_payload_length, off); if (NULL == mx->mxhost) { GNUNET_break_op (0); GNUNET_DNSPARSER_free_mx (mx); *off = old_off; return NULL; } return mx; }
/** * Parse a DNS query entry. * * @param udp_payload entire UDP payload * @param udp_payload_length length of @a udp_payload * @param off pointer to the offset of the query to parse in the udp_payload (to be * incremented by the size of the query) * @param q where to write the query information * @return #GNUNET_OK on success, #GNUNET_SYSERR if the query is malformed */ int GNUNET_DNSPARSER_parse_query (const char *udp_payload, size_t udp_payload_length, size_t *off, struct GNUNET_DNSPARSER_Query *q) { char *name; struct GNUNET_TUN_DnsQueryLine ql; name = GNUNET_DNSPARSER_parse_name (udp_payload, udp_payload_length, off); if (NULL == name) { GNUNET_break_op (0); return GNUNET_SYSERR; } q->name = name; if (*off + sizeof (struct GNUNET_TUN_DnsQueryLine) > udp_payload_length) { GNUNET_break_op (0); return GNUNET_SYSERR; } GNUNET_memcpy (&ql, &udp_payload[*off], sizeof (ql)); *off += sizeof (ql); q->type = ntohs (ql.type); q->dns_traffic_class = ntohs (ql.dns_traffic_class); return GNUNET_OK; }
/** * An incoming flood message has been received which claims * to have more bits matching than any we know in this time * period. Verify the signature and/or proof of work. * * @param incoming_flood the message to verify * @return #GNUNET_YES if the message is verified * #GNUNET_NO if the key/signature don't verify */ static int verify_message_crypto (const struct GNUNET_NSE_FloodMessage *incoming_flood) { if (GNUNET_YES != check_proof_of_work (&incoming_flood->origin.public_key, incoming_flood->proof_of_work)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Proof of work invalid: %llu!\n", (unsigned long long) GNUNET_ntohll (incoming_flood->proof_of_work)); GNUNET_break_op (0); return GNUNET_NO; } if ((nse_work_required > 0) && (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_NSE_SEND, &incoming_flood->purpose, &incoming_flood->signature, &incoming_flood->origin.public_key))) { GNUNET_break_op (0); return GNUNET_NO; } return GNUNET_YES; }
/** * Function to handle a ring message incoming over cadet * * @param cls closure, NULL * @param channel the channel over which the message arrived * @param channel_ctx the channel context, can be NULL * or point to the `struct Channel` * @param message the incoming message * @return #GNUNET_OK */ static int handle_cadet_ring_message (void *cls, struct GNUNET_CADET_Channel *channel, void **channel_ctx, const struct GNUNET_MessageHeader *message) { struct Channel *ch = *channel_ctx; struct Line *line = ch->line; const struct CadetPhoneRingMessage *msg; struct GNUNET_MQ_Envelope *env; struct ClientPhoneRingMessage *cring; struct CadetPhoneRingInfoPS rs; msg = (const struct CadetPhoneRingMessage *) message; rs.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING); rs.purpose.size = htonl (sizeof (struct CadetPhoneRingInfoPS)); rs.line_port = line->line_port; rs.target_peer = my_identity; rs.expiration_time = msg->expiration_time; if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING, &rs.purpose, &msg->signature, &msg->caller_id)) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (0 == GNUNET_TIME_absolute_get_remaining (GNUNET_TIME_absolute_ntoh (msg->expiration_time)).rel_value_us) { /* ancient call, replay? */ GNUNET_break_op (0); /* Note that our reliance on time here is awkward; better would be to use a more complex challenge-response protocol against replay attacks. Left for future work ;-). */ return GNUNET_SYSERR; } if (CS_CALLEE_INIT != ch->status) { GNUNET_break_op (0); return GNUNET_SYSERR; } GNUNET_CADET_receive_done (channel); ch->status = CS_CALLEE_RINGING; env = GNUNET_MQ_msg (cring, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RING); cring->cid = ch->cid; cring->caller_id = msg->caller_id; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending RING message to client. CID is %u\n", (unsigned int) ch->cid); GNUNET_MQ_send (line->mq, env); return GNUNET_OK; }
/** * Unblind a blind-signed signature. The signature should have been generated * with #GNUNET_CRYPTO_rsa_sign() using a hash that was blinded with * #GNUNET_CRYPTO_rsa_blind(). * * @param sig the signature made on the blinded signature purpose * @param bkey the blinding key used to blind the signature purpose * @param pkey the public key of the signer * @return unblinded signature on success, NULL on error */ struct GNUNET_CRYPTO_rsa_Signature * GNUNET_CRYPTO_rsa_unblind (struct GNUNET_CRYPTO_rsa_Signature *sig, struct GNUNET_CRYPTO_rsa_BlindingKey *bkey, struct GNUNET_CRYPTO_rsa_PublicKey *pkey) { gcry_mpi_t n; gcry_mpi_t s; gcry_mpi_t r_inv; gcry_mpi_t ubsig; int ret; struct GNUNET_CRYPTO_rsa_Signature *sret; ret = key_from_sexp (&n, pkey->sexp, "public-key", "n"); if (0 != ret) ret = key_from_sexp (&n, pkey->sexp, "rsa", "n"); if (0 != ret) { GNUNET_break_op (0); return NULL; } ret = key_from_sexp (&s, sig->sexp, "sig-val", "s"); if (0 != ret) ret = key_from_sexp (&s, sig->sexp, "rsa", "s"); if (0 != ret) { gcry_mpi_release (n); GNUNET_break_op (0); return NULL; } r_inv = gcry_mpi_new (0); if (1 != gcry_mpi_invm (r_inv, bkey->r, n)) { GNUNET_break_op (0); gcry_mpi_release (n); gcry_mpi_release (r_inv); gcry_mpi_release (s); return NULL; } ubsig = gcry_mpi_new (0); gcry_mpi_mulm (ubsig, s, r_inv, n); gcry_mpi_release (n); gcry_mpi_release (r_inv); gcry_mpi_release (s); sret = GNUNET_new (struct GNUNET_CRYPTO_rsa_Signature); GNUNET_assert (0 == gcry_sexp_build (&sret->sexp, NULL, "(sig-val (rsa (s %M)))", ubsig)); gcry_mpi_release (ubsig); return sret; }
/** * Called with any anomaly report received from a peer. * * Each time the function must call #GNUNET_CADET_receive_done on the channel * in order to receive the next message. This doesn't need to be immediate: * can be delayed if some processing is done on the message. * * @param cls Closure (set from #GNUNET_CADET_connect). * @param channel Connection to the other end. * @param channel_ctx Place to store local state associated with the channel. * @param message The actual message. * @return #GNUNET_OK to keep the channel open, * #GNUNET_SYSERR to close it (signal serious error). */ static int handle_anomaly_report (void *cls, struct GNUNET_CADET_Channel *channel, void **channel_ctx, const struct GNUNET_MessageHeader *message) { struct ClientPeerContext *cp = *channel_ctx; struct GNUNET_SENSOR_crypto_pow_block *report_block; struct GNUNET_SENSOR_AnomalyReportMessage *anomaly_msg; struct GNUNET_SENSOR_SensorInfo *sensor; struct GNUNET_SENSOR_DashboardAnomalyEntry *anomaly_entry; struct GNUNET_TIME_Absolute expiry; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received an anomaly report message from peer `%s'.\n", GNUNET_i2s (&cp->peerid)); report_block = (struct GNUNET_SENSOR_crypto_pow_block *) &message[1]; if (sizeof (struct GNUNET_SENSOR_AnomalyReportMessage) != GNUNET_SENSOR_crypto_verify_pow_sign (report_block, pow_matching_bits, &cp->peerid.public_key, (void **) &anomaly_msg)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Received invalid anomaly report from peer `%s'.\n", GNUNET_i2s (&cp->peerid)); GNUNET_break_op (0); return GNUNET_SYSERR; } sensor = GNUNET_CONTAINER_multihashmap_get (sensors, &anomaly_msg->sensorname_hash); if (NULL == sensor) { GNUNET_break_op (0); return GNUNET_SYSERR; } anomaly_entry = GNUNET_new (struct GNUNET_SENSOR_DashboardAnomalyEntry); anomaly_entry->anomalous = ntohs (anomaly_msg->anomalous); anomaly_entry->anomalous_neighbors = anomaly_msg->anomalous_neighbors; expiry = (GNUNET_YES == anomaly_entry->anomalous) ? GNUNET_TIME_UNIT_FOREVER_ABS : GNUNET_TIME_absolute_get (); GNUNET_PEERSTORE_store (peerstore, anomalies_subsystem, &cp->peerid, sensor->name, anomaly_entry, sizeof (struct GNUNET_SENSOR_DashboardAnomalyEntry), expiry, GNUNET_PEERSTORE_STOREOPTION_REPLACE, NULL, NULL); GNUNET_free (anomaly_entry); GNUNET_CADET_receive_done (channel); return GNUNET_OK; }
/** * Parses a sensor reading message struct * * @param msg message header received * @param sensors multihashmap of loaded sensors * @return sensor reading struct or NULL if error */ static struct ClientSensorReading * parse_reading_message (const struct GNUNET_MessageHeader *msg, struct GNUNET_CONTAINER_MultiHashMap *sensors) { uint16_t msg_size; uint16_t value_size; struct GNUNET_SENSOR_ValueMessage *vm; struct GNUNET_SENSOR_SensorInfo *sensor; struct ClientSensorReading *reading; msg_size = ntohs (msg->size); if (msg_size < sizeof (struct GNUNET_SENSOR_ValueMessage)) { GNUNET_break_op (0); return NULL; } vm = (struct GNUNET_SENSOR_ValueMessage *) msg; value_size = ntohs (vm->value_size); if ((sizeof (struct GNUNET_SENSOR_ValueMessage) + value_size) != msg_size) { GNUNET_break_op (0); return NULL; } sensor = GNUNET_CONTAINER_multihashmap_get (sensors, &vm->sensorname_hash); if (NULL == sensor) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unknown sensor name in reading message.\n"); return NULL; } if ((sensor->version_minor != ntohs (vm->sensorversion_minor)) || (sensor->version_major != ntohs (vm->sensorversion_major))) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Sensor version mismatch in reading message.\n"); return NULL; } if (0 == strcmp (sensor->expected_datatype, "numeric") && sizeof (double) != value_size) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Invalid value size for a numerical sensor.\n"); return NULL; } reading = GNUNET_new (struct ClientSensorReading); reading->sensor = sensor; reading->timestamp = vm->timestamp; reading->value_size = value_size; reading->value = GNUNET_memdup (&vm[1], value_size); return reading; }
/** * Decode the public key from the data-format back * to the "normal", internal format. * * @param buf the buffer where the public key data is stored * @param len the length of the data in @a buf * @return NULL on error */ struct GNUNET_CRYPTO_rsa_PublicKey * GNUNET_CRYPTO_rsa_public_key_decode (const char *buf, size_t len) { struct GNUNET_CRYPTO_rsa_PublicKey *key; gcry_mpi_t n; int ret; key = GNUNET_new (struct GNUNET_CRYPTO_rsa_PublicKey); if (0 != gcry_sexp_new (&key->sexp, buf, len, 0)) { GNUNET_break_op (0); GNUNET_free (key); return NULL; } /* verify that this is an RSA public key */ ret = key_from_sexp (&n, key->sexp, "public-key", "n"); if (0 != ret) ret = key_from_sexp (&n, key->sexp, "rsa", "n"); if (0 != ret) { /* this is no public RSA key */ GNUNET_break (0); gcry_sexp_release (key->sexp); GNUNET_free (key); return NULL; } gcry_mpi_release (n); return key; }
/** * Extract the public key of the given private key. * * @param priv the private key * @retur NULL on error, otherwise the public key */ struct GNUNET_CRYPTO_rsa_PublicKey * GNUNET_CRYPTO_rsa_private_key_get_public (const struct GNUNET_CRYPTO_rsa_PrivateKey *priv) { struct GNUNET_CRYPTO_rsa_PublicKey *pub; gcry_mpi_t ne[2]; int rc; gcry_sexp_t result; rc = key_from_sexp (ne, priv->sexp, "public-key", "ne"); if (0 != rc) rc = key_from_sexp (ne, priv->sexp, "private-key", "ne"); if (0 != rc) rc = key_from_sexp (ne, priv->sexp, "rsa", "ne"); if (0 != rc) { GNUNET_break_op (0); return NULL; } rc = gcry_sexp_build (&result, NULL, "(public-key(rsa(n %m)(e %m)))", ne[0], ne[1]); gcry_mpi_release (ne[0]); gcry_mpi_release (ne[1]); pub = GNUNET_new (struct GNUNET_CRYPTO_rsa_PublicKey); pub->sexp = result; return pub; }
/** * Handle request connect message * * @param cls closure (always NULL) * @param client identification of the client * @param message the actual message */ static void clients_handle_request_connect (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct TransportRequestConnectMessage *trcm = (const struct TransportRequestConnectMessage *) message; GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# REQUEST CONNECT messages received"), 1, GNUNET_NO); if (0 == memcmp (&trcm->peer, &GST_my_identity, sizeof (struct GNUNET_PeerIdentity))) { GNUNET_break_op (0); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Received a request connect message myself `%s'\n", GNUNET_i2s (&trcm->peer)); } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received a request connect message for peer `%s'\n", GNUNET_i2s (&trcm->peer)); (void) GST_blacklist_test_allowed (&trcm->peer, NULL, &try_connect_if_allowed, NULL); } GNUNET_SERVER_receive_done (client, GNUNET_OK); }
/** * Handler for Bob's a client request message. Check @a msg is * well-formed. * * @param cls identification of the client * @param msg the actual message * @return #GNUNET_OK if @a msg is well-formed */ static int check_bob_client_message (void *cls, const struct BobComputationMessage *msg) { struct BobServiceSession *s = cls; uint32_t contained_count; uint32_t total_count; uint16_t msize; if (GNUNET_SCALARPRODUCT_STATUS_INIT != s->status) { GNUNET_break (0); return GNUNET_SYSERR; } msize = ntohs (msg->header.size); total_count = ntohl (msg->element_count_total); contained_count = ntohl (msg->element_count_contained); if ( (0 == total_count) || (0 == contained_count) || (UINT16_MAX < contained_count) || (msize != (sizeof (struct BobComputationMessage) + contained_count * sizeof (struct GNUNET_SCALARPRODUCT_Element))) ) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (NULL != find_matching_client_session (&msg->session_key)) { GNUNET_break (0); return GNUNET_SYSERR; } return GNUNET_OK; }
/** * Parse a DNS CERT record. * * @param udp_payload reference to UDP packet * @param udp_payload_length length of @a udp_payload * @param off pointer to the offset of the query to parse in the CERT record (to be * incremented by the size of the record), unchanged on error * @return the parsed CERT record, NULL on error */ struct GNUNET_DNSPARSER_CertRecord * GNUNET_DNSPARSER_parse_cert (const char *udp_payload, size_t udp_payload_length, size_t *off) { struct GNUNET_DNSPARSER_CertRecord *cert; struct GNUNET_TUN_DnsCertRecord dcert; if (*off + sizeof (struct GNUNET_TUN_DnsCertRecord) >= udp_payload_length) { GNUNET_break_op (0); return NULL; } GNUNET_memcpy (&dcert, &udp_payload[*off], sizeof (struct GNUNET_TUN_DnsCertRecord)); (*off) += sizeof (struct GNUNET_TUN_DnsCertRecord); cert = GNUNET_new (struct GNUNET_DNSPARSER_CertRecord); cert->cert_type = ntohs (dcert.cert_type); cert->cert_tag = ntohs (dcert.cert_tag); cert->algorithm = dcert.algorithm; cert->certificate_size = udp_payload_length - (*off); cert->certificate_data = GNUNET_malloc (cert->certificate_size); GNUNET_memcpy (cert->certificate_data, &udp_payload[*off], cert->certificate_size); (*off) += cert->certificate_size; return cert; }
/** * We got a reply from the stream. Process it. * * @param cls the struct StreamHandle * @param status the status of the stream at the time this function is called * @param data traffic from the other side * @param size the number of bytes available in data read; will be 0 on timeout * @return number of bytes of processed from 'data' (any data remaining should be * given to the next time the read processor is called). */ static size_t handle_stream_reply (void *cls, enum GNUNET_STREAM_Status status, const void *data, size_t size) { struct StreamHandle *sh = cls; sh->rh = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %u bytes from stream to %s\n", (unsigned int) size, GNUNET_i2s (&sh->target)); if (GNUNET_SYSERR == GNUNET_SERVER_mst_receive (sh->mst, NULL, data, size, GNUNET_NO, GNUNET_NO)) { GNUNET_break_op (0); reset_stream_async (sh); return size; } sh->rh = GNUNET_STREAM_read (sh->stream, GNUNET_TIME_UNIT_FOREVER_REL, &handle_stream_reply, sh); return size; }
/** * Function to handle a suspend message incoming over cadet * * @param cls closure, NULL * @param channel the channel over which the message arrived * @param channel_ctx the channel context, can be NULL * or point to the `struct Channel` * @param message the incoming message * @return #GNUNET_OK */ static int handle_cadet_suspend_message (void *cls, struct GNUNET_CADET_Channel *channel, void **channel_ctx, const struct GNUNET_MessageHeader *message) { struct Channel *ch = *channel_ctx; struct Line *line = ch->line; struct GNUNET_MQ_Envelope *env; struct ClientPhoneSuspendMessage *suspend; GNUNET_CADET_receive_done (channel); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Suspending channel CID: %u\n", ch->cid); switch (ch->status) { case CS_CALLEE_INIT: GNUNET_break_op (0); break; case CS_CALLEE_RINGING: GNUNET_break_op (0); break; case CS_CALLEE_CONNECTED: ch->suspended_remote = GNUNET_YES; break; case CS_CALLEE_SHUTDOWN: return GNUNET_OK; case CS_CALLER_CALLING: GNUNET_break_op (0); break; case CS_CALLER_CONNECTED: ch->suspended_remote = GNUNET_YES; break; case CS_CALLER_SHUTDOWN: return GNUNET_OK; } env = GNUNET_MQ_msg (suspend, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND); suspend->cid = ch->cid; GNUNET_MQ_send (line->mq, env); return GNUNET_OK; }
/** * Function to handle a pickup message incoming over cadet * * @param cls closure, NULL * @param channel the channel over which the message arrived * @param channel_ctx the channel context, can be NULL * or point to the `struct Channel` * @param message the incoming message * @return #GNUNET_OK if message was OK, * #GNUNET_SYSERR if message violated the protocol */ static int handle_cadet_pickup_message (void *cls, struct GNUNET_CADET_Channel *channel, void **channel_ctx, const struct GNUNET_MessageHeader *message) { struct Channel *ch = *channel_ctx; struct Line *line = ch->line; struct GNUNET_MQ_Envelope *env; struct ClientPhonePickedupMessage *pick; GNUNET_CADET_receive_done (channel); switch (ch->status) { case CS_CALLEE_INIT: case CS_CALLEE_RINGING: case CS_CALLEE_CONNECTED: GNUNET_break_op (0); destroy_line_cadet_channels (ch); return GNUNET_SYSERR; case CS_CALLEE_SHUTDOWN: GNUNET_break_op (0); destroy_line_cadet_channels (ch); return GNUNET_SYSERR; case CS_CALLER_CALLING: ch->status = CS_CALLER_CONNECTED; break; case CS_CALLER_CONNECTED: GNUNET_break_op (0); return GNUNET_OK; case CS_CALLER_SHUTDOWN: GNUNET_break_op (0); mq_done_finish_caller_shutdown (ch); return GNUNET_SYSERR; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending PICKED UP message to client\n"); env = GNUNET_MQ_msg (pick, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICKED_UP); pick->cid = ch->cid; GNUNET_MQ_send (line->mq, env); return GNUNET_OK; }
/** * Functions with this signature are called whenever a * complete query message is received. * * Do not call GNUNET_SERVER_mst_destroy in callback * * @param cls closure with the 'struct StreamClient' * @param client identification of the client, NULL * @param message the actual message * @return GNUNET_OK on success, GNUNET_SYSERR to stop further processing */ static int request_cb (void *cls, void *client, const struct GNUNET_MessageHeader *message) { struct StreamClient *sc = cls; const struct StreamQueryMessage *sqm; switch (ntohs (message->type)) { case GNUNET_MESSAGE_TYPE_FS_STREAM_QUERY: if (sizeof (struct StreamQueryMessage) != ntohs (message->size)) { GNUNET_break_op (0); terminate_stream_async (sc); return GNUNET_SYSERR; } sqm = (const struct StreamQueryMessage *) message; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received query for `%s' via stream\n", GNUNET_h2s (&sqm->query)); GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# queries received via stream"), 1, GNUNET_NO); refresh_timeout_task (sc); sc->qe = GNUNET_DATASTORE_get_key (GSF_dsh, 0, &sqm->query, ntohl (sqm->type), 0 /* priority */, GSF_datastore_queue_size, GNUNET_TIME_UNIT_FOREVER_REL, &handle_datastore_reply, sc); if (NULL == sc->qe) continue_reading (sc); return GNUNET_OK; default: GNUNET_break_op (0); terminate_stream_async (sc); return GNUNET_SYSERR; } }
/** * Handle a request from Alice to calculate a scalarproduct with us (Bob). * * @param cls closure (set from #GNUNET_CADET_connect) * @param channel connection to the other end * @param channel_ctx place to store the `struct CadetIncomingSession *` * @param message the actual message * @return #GNUNET_OK to keep the connection open, * #GNUNET_SYSERR to close it (signal serious error) */ static int handle_alices_computation_request (void *cls, struct GNUNET_CADET_Channel *channel, void **channel_ctx, const struct GNUNET_MessageHeader *message) { struct CadetIncomingSession *in = *channel_ctx; struct BobServiceSession *s; const struct EccServiceRequestMessage *msg; msg = (const struct EccServiceRequestMessage *) message; if (GNUNET_YES == in->in_map) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (NULL != find_matching_cadet_session (&msg->session_id)) { /* not unique, got one like this already */ GNUNET_break_op (0); return GNUNET_SYSERR; } in->session_id = msg->session_id; GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_put (cadet_sessions, &in->session_id, in, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); s = find_matching_client_session (&in->session_id); if (NULL == s) { /* no client waiting for this request, wait for client */ return GNUNET_OK; } GNUNET_assert (NULL == s->cadet); /* pair them up */ in->s = s; s->cadet = in; if (s->client_received_element_count == s->total) start_intersection (s); return GNUNET_OK; }
/** * Get the size of an address entry in a HELLO message. * * @param buf pointer to the start of the address entry * @param max maximum size of the entry (end of buf) * @param ralen set to the address length * @return size of the entry, or 0 if max is not large enough */ static size_t get_hello_address_size (const char *buf, size_t max, uint16_t * ralen) { const char *pos; uint16_t alen; size_t left; size_t slen; left = max; pos = buf; slen = 1; while ((left > 0) && ('\0' != *pos)) { left--; pos++; slen++; } if (left == 0) { /* 0-termination not found */ GNUNET_break_op (0); return 0; } pos++; if (left < sizeof (uint16_t) + sizeof (struct GNUNET_TIME_AbsoluteNBO)) { /* not enough space for addrlen */ GNUNET_break_op (0); return 0; } memcpy (&alen, pos, sizeof (uint16_t)); alen = ntohs (alen); *ralen = alen; slen += alen + sizeof (uint16_t) + sizeof (struct GNUNET_TIME_AbsoluteNBO); if (max < slen) { /* not enough space for addr */ GNUNET_break_op (0); return 0; } return slen; }
static void manage_zone_operations (struct GNUNET_NAMESTORE_ZoneIterator *ze, const struct GNUNET_MessageHeader *msg, int type, size_t size) { /* handle different message type */ switch (type) { case GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE: if (size < sizeof (struct ZoneIterationResponseMessage)) { GNUNET_break_op (0); break; } handle_zone_iteration_response (ze, (struct ZoneIterationResponseMessage *) msg, size); break; default: GNUNET_break_op (0); break; } }
/** * Extract a type map from a TYPE_MAP message. * * @param msg a type map message * @return NULL on error */ struct GSC_TypeMap * GSC_TYPEMAP_get_from_message (const struct GNUNET_MessageHeader *msg) { struct GSC_TypeMap *ret; uint16_t size; uLongf dlen; size = ntohs (msg->size); switch (ntohs (msg->type)) { case GNUNET_MESSAGE_TYPE_CORE_BINARY_TYPE_MAP: GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# type maps received"), 1, GNUNET_NO); if (size != sizeof (struct GSC_TypeMap)) { GNUNET_break_op (0); return NULL; } ret = GNUNET_new (struct GSC_TypeMap); memcpy (ret, &msg[1], sizeof (struct GSC_TypeMap)); return ret; case GNUNET_MESSAGE_TYPE_CORE_COMPRESSED_TYPE_MAP: GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# type maps received"), 1, GNUNET_NO); ret = GNUNET_new (struct GSC_TypeMap); dlen = sizeof (struct GSC_TypeMap); if ((Z_OK != uncompress ((Bytef *) ret, &dlen, (const Bytef *) &msg[1], (uLong) size)) || (dlen != sizeof (struct GSC_TypeMap))) { GNUNET_break_op (0); GNUNET_free (ret); return NULL; } return ret; default: GNUNET_break (0); return NULL; } }
/** * Builds a path from a PeerIdentity array. * * @param peers PeerIdentity array. * @param size Size of the @c peers array. * @param myid ID of local peer, to find @c own_pos. * @param own_pos Output parameter: own position in the path. * * @return Fixed and shortened path. */ struct CadetPeerPath * path_build_from_peer_ids (struct GNUNET_PeerIdentity *peers, unsigned int size, GNUNET_PEER_Id myid, unsigned int *own_pos) { struct CadetPeerPath *path; GNUNET_PEER_Id shortid; unsigned int i; unsigned int j; unsigned int offset; /* Create path */ LOG (GNUNET_ERROR_TYPE_DEBUG, " Creating path...\n"); path = path_new (size); *own_pos = 0; offset = 0; for (i = 0; i < size; i++) { LOG (GNUNET_ERROR_TYPE_DEBUG, " - %u: taking %s\n", i, GNUNET_i2s (&peers[i])); shortid = GNUNET_PEER_intern (&peers[i]); /* Check for loops / duplicates */ for (j = 0; j < i - offset; j++) { if (path->peers[j] == shortid) { LOG (GNUNET_ERROR_TYPE_DEBUG, " already exists at pos %u\n", j); offset = i - j; LOG (GNUNET_ERROR_TYPE_DEBUG, " offset now %u\n", offset); GNUNET_PEER_change_rc (shortid, -1); } } LOG (GNUNET_ERROR_TYPE_DEBUG, " storing at %u\n", i - offset); path->peers[i - offset] = shortid; if (path->peers[i - offset] == myid) *own_pos = i - offset; } path->length -= offset; if (path->peers[*own_pos] != myid) { /* create path: self not found in path through self */ GNUNET_break_op (0); path_destroy (path); return NULL; } return path; }
/** * Parse given JSON object to variable size data * * @param cls closure, NULL * @param root the json object representing data * @param[out] spec where to write the data * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error */ static int parse_variable_data (void *cls, json_t *root, struct GNUNET_JSON_Specification *spec) { const char *str; size_t size; void *data; int res; str = json_string_value (root); if (NULL == str) { GNUNET_break_op (0); return GNUNET_SYSERR; } size = (strlen (str) * 5) / 8; if (size >= 1024) { GNUNET_break_op (0); return GNUNET_SYSERR; } data = GNUNET_malloc (size); res = GNUNET_STRINGS_string_to_data (str, strlen (str), data, size); if (GNUNET_OK != res) { GNUNET_break_op (0); GNUNET_free (data); return GNUNET_SYSERR; } *(void**) spec->ptr = data; *spec->size_ptr = size; return GNUNET_OK; }
/** * This function is called whenever an encrypted HELLO message is * received. * * @param cls closure with the peer identity of the sender * @param message the actual HELLO message * @return #GNUNET_OK if @a message is well-formed * #GNUNET_SYSERR if @a message is invalid */ static int check_hello (void *cls, const struct GNUNET_HELLO_Message *message) { struct GNUNET_PeerIdentity pid; if (GNUNET_OK != GNUNET_HELLO_get_id (message, &pid)) { GNUNET_break_op (0); return GNUNET_SYSERR; } return GNUNET_OK; }
static void manage_record_operations (struct GNUNET_NAMESTORE_QueueEntry *qe, const struct GNUNET_MessageHeader *msg, int type, size_t size) { /* handle different message type */ switch (type) { case GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE: if (size < sizeof (struct LookupNameResponseMessage)) { GNUNET_break_op (0); break; } handle_lookup_name_response (qe, (struct LookupNameResponseMessage *) msg, size); break; case GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT_RESPONSE: if (size != sizeof (struct RecordPutResponseMessage)) { GNUNET_break_op (0); break; } handle_record_put_response (qe, (struct RecordPutResponseMessage *) msg, size); break; case GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE: if (size != sizeof (struct RecordCreateResponseMessage)) { GNUNET_break_op (0); break; } handle_record_create_response (qe, (struct RecordCreateResponseMessage *) msg, size); break; case GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE_RESPONSE: if (size != sizeof (struct RecordRemoveResponseMessage)) { GNUNET_break_op (0); break; } handle_record_remove_response (qe, (struct RecordRemoveResponseMessage *) msg, size); break; case GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE: if (size < sizeof (struct ZoneToNameResponseMessage)) { GNUNET_break_op (0); break; } handle_zone_to_name_response (qe, (struct ZoneToNameResponseMessage *) msg, size); break; default: GNUNET_break_op (0); break; } }
/** * 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 * conversation_value_to_string (void *cls, uint32_t type, const void *data, size_t data_size) { char *s; switch (type) { case GNUNET_GNSRECORD_TYPE_PHONE: { const struct GNUNET_CONVERSATION_PhoneRecord *pr; char *ret; char *pkey; if (data_size != sizeof (struct GNUNET_CONVERSATION_PhoneRecord)) { GNUNET_break_op (0); return NULL; } pr = data; if (1 != ntohl (pr->version)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("PHONE version %u not supported\n"), ntohl (pr->version)); return NULL; } pkey = GNUNET_CRYPTO_eddsa_public_key_to_string (&pr->peer.public_key); s = GNUNET_STRINGS_data_to_string_alloc (&pr->line_port, sizeof (struct GNUNET_HashCode)); GNUNET_asprintf (&ret, "%s-%s", s, pkey); GNUNET_free (s); GNUNET_free (pkey); return ret; } default: return NULL; } }
/** * Functions of this signature are called whenever data is available from the * stream. * * @param cls the closure from GNUNET_STREAM_read * @param status the status of the stream at the time this function is called * @param data traffic from the other side * @param size the number of bytes available in data read; will be 0 on timeout * @return number of bytes of processed from 'data' (any data remaining should be * given to the next time the read processor is called). */ static size_t process_request (void *cls, enum GNUNET_STREAM_Status status, const void *data, size_t size) { struct StreamClient *sc = cls; int ret; sc->rh = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %u byte query via stream\n", (unsigned int) size); switch (status) { case GNUNET_STREAM_OK: ret = GNUNET_SERVER_mst_receive (sc->mst, NULL, data, size, GNUNET_NO, GNUNET_YES); if (GNUNET_NO == ret) return size; /* more messages in MST */ if (GNUNET_SYSERR == ret) { GNUNET_break_op (0); terminate_stream_async (sc); return size; } break; case GNUNET_STREAM_TIMEOUT: case GNUNET_STREAM_SHUTDOWN: case GNUNET_STREAM_SYSERR: case GNUNET_STREAM_BROKEN: terminate_stream_async (sc); return size; default: GNUNET_break (0); return size; } continue_reading (sc); return size; }