GNUnet debian-0.24.3-23-g589b01d60
gnunet-service-pils.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2024 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
31#include "platform.h"
32#include "gnunet_util_lib.h"
33#include "gnunet_constants.h"
34#include "gnunet_protocols.h"
35#include "gnunet_signatures.h"
36#include "gnunet_pils_service.h"
37#include "pils.h"
38
39
40/* Shorthand for Logging */
41#define LOG(kind, ...) GNUNET_log_from (kind, "pils", __VA_ARGS__)
42
46static const struct GNUNET_CONFIGURATION_Handle *cfg;
47
48
53
54
62
63
68
69
74
78static unsigned char ikm[256 / 8];
79
84{
88 struct P_Client *next;
89
93 struct P_Client *prev;
94
99
104};
105
106
110static struct P_Client *clients_head;
111
112
116static struct P_Client *clients_tail;
117
122static int have_id;
123
128
139static void
141{
142 char *keyfile;
144
145 if (GNUNET_OK !=
147 "PEER",
148 "PRIVATE_KEY",
149 &keyfile))
150 {
152 "PEER",
153 "PRIVATE_KEY");
155 return;
156 }
157 if (GNUNET_SYSERR ==
160 &key))
161 {
163 "Failed to setup peer's private key\n");
164 GNUNET_free (keyfile);
166 return;
167 }
168 GNUNET_free (keyfile);
169 GNUNET_assert (sizeof ikm == sizeof key.d);
170 memcpy (ikm, key.d, sizeof ikm);
171}
172
173static void
174print_uri (void *cls,
175 const struct GNUNET_PeerIdentity *pid,
176 const char *uri)
177{
179 "%s\n", uri);
180}
181
189static void
191{
193 struct GNUNET_HashCode new_addresses_hash;
194 LOG (GNUNET_ERROR_TYPE_INFO, "Going to generate a new peer id\n");
195 generate_pid_task = NULL;
196
197 if (NULL == parser)
198 {
200 }
201 else
202 {
204 }
206 "Got new address list to derive PID:\n");
209 &new_addresses_hash);
210 /*if (0 == GNUNET_CRYPTO_hash_cmp (&new_addresses_hash,
211 &addresses_hash))
212 {
213 LOG (GNUNET_ERROR_TYPE_DEBUG,
214 "Address hash unchanged at %s, ignoring...\n",
215 GNUNET_h2s (&addresses_hash));
216 GNUNET_HELLO_builder_free (builder);
217 return;
218 }*/
219 addresses_hash = new_addresses_hash;
221 (uint8_t*) ikm,
227 "Successfully generated a new peer id %s - inform clients\n",
229
230 {
231 struct P_Client *client;
232 struct PeerIdUpdateMessage *msg;
234 struct GNUNET_TIME_Absolute et;
235 size_t block_bytes;
237
238 struct PilsHelloSignaturePurpose hsp = {
239 .purpose.size = htonl (sizeof (hsp)),
240 .purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_HELLO),
241 .expiration_time = GNUNET_TIME_absolute_hton (et)
242 };
246 &hsp.purpose,
247 &sig));
249
251 block_bytes,
253 msg->hash = addresses_hash;
254 msg->block_len = htonl (block_bytes);
256 builder,
258 &sig,
259 et,
260 (char *) &msg[1]);
261 client = clients_head;
262 while (NULL != client)
263 {
265 client = client->next;
266 }
267 }
268}
269
270
278static int
280 const struct FeedAddressesMessage *msg)
281{
282 size_t msg_size;
283 uint32_t block_bytes;
284 (void) cls;
285
286 msg_size = ntohs (msg->header.size);
287 block_bytes = ntohl (msg->block_len);
288 if (msg_size != sizeof (*msg) + block_bytes)
289 {
291 "The msg_size (%lu) is not %lu (header) + %u (block)\n",
292 msg_size,
293 sizeof (*msg),
294 block_bytes);
295 return GNUNET_SYSERR;
296 }
297 return GNUNET_OK;
298}
299
300
310static void
312 const struct FeedAddressesMessage *message)
313{
314 struct P_Client *client = cls;
316 uint32_t block_bytes;
317
319 "PILS received FEED_ADDRESSES message from client\n");
320
321 /* If there's a peer id generation scheduled, just kill it and generate an id
322 * on the more recent address */
323 block_bytes = ntohl (message->block_len);
325 block_bytes,
326 GNUNET_YES);
328
331}
332
333
340static void
341handle_decaps (void *cls,
342 const struct DecapsMessage *message)
343{
344 struct P_Client *client = cls;
345 struct DecapsResultMessage *rmsg;
346 struct GNUNET_MQ_Envelope *env;
348
350 "PILS received KEM_DECAPS message from client\n");
351
353 &message->c,
354 &rmsg->key))
355 {
357 "PILS failed to decapsulate encapsulation received from client\n");
358 memset (&rmsg->key, 0, sizeof (rmsg->key));
359 }
360
361 rmsg->rid = message->rid;
362 GNUNET_MQ_send (client->mq, env);
364}
365
366
374static int
375check_sign (void *cls, const struct SignRequestMessage *msg)
376{
378 size_t msg_size;
379 (void) cls;
380
381 msg_size = ntohs (msg->header.size);
382 if (msg_size <= sizeof (*msg) + sizeof (struct
384 {
386 "The msg_size (%lu) is not big enough for msg (%lu) + purpose struct (%lu)\n",
387 msg_size,
388 sizeof (*msg),
389 sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose));
390 return GNUNET_SYSERR;
391 }
392 purp = (struct GNUNET_CRYPTO_EccSignaturePurpose*) &msg[1];
393 if (msg_size <= sizeof (*msg) + ntohs (purp->size))
394 {
396 "The msg_size (%lu) is not big enough for msg (%lu) + purpose (%u)\n",
397 msg_size,
398 sizeof (*msg),
399 ntohs (purp->size));
400 return GNUNET_SYSERR;
401 }
402 return GNUNET_OK;
403}
404
405
412static void
413handle_sign (void *cls,
414 const struct SignRequestMessage *message)
415{
416 struct P_Client *client = cls;
417 struct SignResultMessage *rmsg;
418 struct GNUNET_MQ_Envelope *env;
421
423 "PILS received SIGN message from client\n");
424
425 purp = (struct GNUNET_CRYPTO_EccSignaturePurpose*) &message[1];
427 purp,
428 &rmsg->sig))
429 {
431 "PILS failed to sign message received from client\n");
432 memset (&rmsg->sig, 0, sizeof (rmsg->sig));
433 }
435 "PILS sent SIGN_RESULT message to client %p\n",
436 client->mq);
438 rmsg->rid = message->rid;
439 GNUNET_MQ_send (client->mq, env);
441}
442
443
449static void
450shutdown_task (void *cls)
451{
452 struct P_Client *c;
453 (void) cls;
454
456 "PILS shutting down\n");
457 c = clients_head;
458 while (NULL != c)
459 {
460 struct P_Client *c_delete = c;
461
462 c = c->next;
464 /* No need to remove from DLL or free here - #client_disconnect_cb(), which
465 * is called by GNUNET_SERVICE_client_drop(), takes care of this. */
466 }
467 if (NULL != signed_hello)
469 cfg = NULL;
470 if (NULL != generate_pid_task)
473}
474
475
483static void
484run (void *cls,
485 const struct GNUNET_CONFIGURATION_Handle *c,
487{
488 cfg = c;
490 "PILS starting\n");
492 load_ikm ();
493 /* Generate an initial peer id from no addresses at all
494 * This is needed for scenarios in which we have only local addresses. */
495 do_generate_pid (NULL);
497}
498
499
511static void *
513 struct GNUNET_SERVICE_Client *c,
514 struct GNUNET_MQ_Handle *mq)
515{
516 struct P_Client *client;
517 (void) cls;
518
519 LOG (GNUNET_ERROR_TYPE_DEBUG, "A client `%p' connected\n",
520 mq);
521 client = GNUNET_new (struct P_Client);
522 client->client = c;
523 client->mq = mq;
526 client);
527 if (GNUNET_YES == have_id)
528 {
530 }
531 return client;
532}
533
534
544static void
546 struct GNUNET_SERVICE_Client *c,
547 void *internal_cls)
548{
549 struct P_Client *client_iter;
550 (void) cls;
551
552 client_iter = clients_head;
553 while (NULL != client_iter)
554 {
555 struct P_Client *client_next = client_iter->next;
556
557 if (client_iter->client == c)
558 {
561 client_iter);
562 GNUNET_free (client_iter);
563 }
564 client_iter = client_next;
565 }
566}
567
568
573 "pils",
575 &run,
578 NULL,
579 GNUNET_MQ_hd_var_size (feed_addresses,
582 NULL),
585 struct DecapsMessage,
586 NULL),
589 struct SignRequestMessage,
590 NULL),
592
593
594/* end of gnunet-service-pils.c */
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
static struct HostSet * builder
NULL if we are not currently iterating over peer information.
struct GNUNET_HashCode key
The key used in the DHT.
static struct GNUNET_FS_Uri * uri
Value of URI provided on command-line (when not publishing a file but just creating UBlocks to refer ...
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
static struct GNUNET_MQ_Envelope * signed_hello
Current signed HELLO.
static void handle_decaps(void *cls, const struct DecapsMessage *message)
Handler for decaps request message from client.
struct GNUNET_CRYPTO_EddsaPrivateKey my_private_key
The current private key.
static struct GNUNET_SCHEDULER_Task * generate_pid_task
Task to schedule the generation of the peer id.
static unsigned char ikm[256/8]
The initial key material for the peer.
struct GNUNET_HashCode addresses_hash
Hash of the canonicalized addresses.
static const struct GNUNET_CONFIGURATION_Handle * cfg
Handle to our current configuration.
static int check_feed_addresses(void *cls, const struct FeedAddressesMessage *msg)
Checker for feed messages.
static void print_uri(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
static void handle_feed_addresses(void *cls, const struct FeedAddressesMessage *message)
Handler for feed addresses message from client.
static struct P_Client * clients_tail
Tail of the liked list of clients.
static void shutdown_task(void *cls)
Task run during shutdown.
struct GNUNET_CRYPTO_EddsaPublicKey my_public_key
The current public key.
static struct P_Client * clients_head
Head of the liked list of clients.
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *service)
Set up the service.
static void load_ikm()
Get the initial secret key for generating the peer id.
GNUNET_SERVICE_MAIN(GNUNET_OS_project_data_gnunet(), "pils", GNUNET_SERVICE_OPTION_NONE, &run, &client_connect_cb, &client_disconnect_cb, NULL, GNUNET_MQ_hd_var_size(feed_addresses, GNUNET_MESSAGE_TYPE_PILS_FEED_ADDRESSES, struct FeedAddressesMessage, NULL), GNUNET_MQ_hd_fixed_size(decaps, GNUNET_MESSAGE_TYPE_PILS_KEM_DECAPS, struct DecapsMessage, NULL), GNUNET_MQ_hd_var_size(sign, GNUNET_MESSAGE_TYPE_PILS_SIGN_REQUEST, struct SignRequestMessage, NULL), GNUNET_MQ_handler_end())
Define "main" method using service macro.
static int have_id
Peer ID was calculated already at least once.
static void handle_sign(void *cls, const struct SignRequestMessage *message)
Handler for sign request message from client.
static void do_generate_pid(const struct GNUNET_HELLO_Parser *parser)
Generate the peer id from the addresses hash and the initial secret key.
static int check_sign(void *cls, const struct SignRequestMessage *msg)
Handler for sign request message from client.
static void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *c, struct GNUNET_MQ_Handle *mq)
Callback called when a client connects to the service.
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *c, void *internal_cls)
Callback called when a client disconnected from the service.
#define LOG(kind,...)
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
void GNUNET_PILS_derive_pid(size_t seed_key_bytes, const uint8_t seed_key[seed_key_bytes], const struct GNUNET_HashCode *addrs_hash, struct GNUNET_CRYPTO_EddsaPrivateKey *outkey)
Generate the peer id from the addresses hash and the initial secret key.
Definition: pils_api.c:507
Constants for network protocols.
#define GNUNET_SIGNATURE_PURPOSE_HELLO
Signature by which a peer affirms its address.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_kem_decaps(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, const struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct GNUNET_ShortHashCode *prk)
Decapsulate a key for a private EdDSA key.
Definition: crypto_hpke.c:285
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_key_from_file(const char *filename, int do_create, struct GNUNET_CRYPTO_EddsaPrivateKey *pkey)
Create a new private key by reading it from a file.
void GNUNET_CRYPTO_eddsa_key_get_public(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, struct GNUNET_CRYPTO_EddsaPublicKey *pub)
Extract the public key for the given private key.
Definition: crypto_ecc.c:201
void GNUNET_CRYPTO_eddsa_key_clear(struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
Clear memory that was used to store a private key.
Definition: crypto_ecc.c:447
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_sign_(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, struct GNUNET_CRYPTO_EddsaSignature *sig)
EdDSA sign a given block.
Definition: crypto_ecc.c:625
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
void GNUNET_HELLO_parser_free(struct GNUNET_HELLO_Parser *parser)
Release resources of a builder.
Definition: hello-uri.c:379
void GNUNET_HELLO_builder_to_block(const struct GNUNET_HELLO_Builder *builder, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig, struct GNUNET_TIME_Absolute expiration_time, char *outbuf)
Generate DHT block from a builder.
Definition: hello-uri.c:1244
struct GNUNET_HELLO_Builder * GNUNET_HELLO_builder_new()
Allocate builder.
Definition: hello-uri.c:343
struct GNUNET_HELLO_Parser * GNUNET_HELLO_parser_from_block_(const void *block, size_t block_size, int noverify)
Parse block.
Definition: hello-uri.c:533
void GNUNET_HELLO_builder_iterate(const struct GNUNET_HELLO_Builder *builder, GNUNET_HELLO_UriCallback uc, void *uc_cls)
Iterate over URIs in a builder.
Definition: hello-uri.c:956
struct GNUNET_HELLO_Builder * GNUNET_HELLO_builder_from_parser(const struct GNUNET_HELLO_Parser *parser, struct GNUNET_PeerIdentity *pid)
Allocate builder from parser.
Definition: hello-uri.c:360
size_t GNUNET_HELLO_get_builder_to_block_size(const struct GNUNET_HELLO_Builder *builder)
Get projected block size for builder.
Definition: hello-uri.c:1312
#define GNUNET_HELLO_ADDRESS_EXPIRATION
For how long are HELLO signatures valid?
void GNUNET_HELLO_builder_hash_addresses(const struct GNUNET_HELLO_Builder *builder, struct GNUNET_HashCode *hash)
Compute hash over addresses in builder.
Definition: hello-uri.c:1134
#define GNUNET_log(kind,...)
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
const char * GNUNET_p2s(const struct GNUNET_CRYPTO_EddsaPublicKey *p)
Convert a public key value to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
void GNUNET_MQ_send_copy(struct GNUNET_MQ_Handle *mq, const struct GNUNET_MQ_Envelope *ev)
Send a copy of a message with the given message queue.
Definition: mq.c:384
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:305
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
Definition: gnunet_mq_lib.h:61
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:76
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_gnunet(void)
Return default project data used by 'libgnunetutil' for GNUnet.
#define GNUNET_MESSAGE_TYPE_PILS_SIGN_REQUEST
The client requests data to be signed with the peer identity.
#define GNUNET_MESSAGE_TYPE_PILS_KEM_DECAPS
Decaps request.
#define GNUNET_MESSAGE_TYPE_PILS_FEED_ADDRESSES
The client (core) provides new addresses to the service, so the service can generate the new peer id.
#define GNUNET_MESSAGE_TYPE_PILS_DECAPS_RESULT
Decaps result.
#define GNUNET_MESSAGE_TYPE_PILS_PEER_ID
Message passing the new peer id from the service to the client.
#define GNUNET_MESSAGE_TYPE_PILS_SIGN_RESULT
The service sends the requested signature to the client.
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:567
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition: scheduler.c:1339
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:980
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2462
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2433
@ GNUNET_SERVICE_OPTION_NONE
Use defaults.
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:316
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition: time.c:640
Common type definitions for the peer identity lifecycle service and API.
Message to request a decapsulation from PILS.
Definition: pils.h:143
uint32_t rid
Request ID.
Definition: pils.h:157
struct GNUNET_CRYPTO_HpkeEncapsulation c
Encapsulation to decapsulate.
Definition: pils.h:152
Message containing the decapsulated key.
Definition: pils.h:164
uint32_t rid
Request ID.
Definition: pils.h:178
struct GNUNET_ShortHashCode key
The decapsulated key.
Definition: pils.h:173
Message requesting a signature on data with the current peer id.
Definition: pils.h:123
uint32_t block_len
For alignment.
Definition: pils.h:132
header of what an ECC signature signs this must be followed by "size - 8" bytes of the actual signed ...
uint32_t size
How many bytes does this signature sign? (including this purpose header); in network byte order (!...
Private ECC key encoded for transmission.
Public ECC key (always for curve Ed25519) encoded in a format suitable for network transmission and E...
an ECC signature using EdDSA.
Context for building (or parsing) HELLO URIs.
Definition: hello-uri.c:184
Context for parsing HELLOs.
Definition: hello-uri.c:232
A 512-bit hashcode.
Handle to a message queue.
Definition: mq.c:87
The identity of the host (wraps the signing key of the peer).
struct GNUNET_CRYPTO_EddsaPublicKey public_key
Entry in list of pending tasks.
Definition: scheduler.c:136
Handle to a client that is connected to a service.
Definition: service.c:249
struct GNUNET_MQ_Handle * mq
Message queue for the client.
Definition: service.c:273
Handle to a service.
Definition: service.c:116
Time for absolute times used by GNUnet, in microseconds.
Data structure for each client connected to the CORE service.
struct GNUNET_MQ_Handle * mq
Message queue to talk to client.
struct P_Client * next
Clients are kept in a linked list.
struct P_Client * prev
Clients are kept in a linked list.
struct GNUNET_SERVICE_Client * client
Handle for the client with the server API.
Message containing the current peer id and the hash from which it was generated.
Definition: pils.h:40
Message signed as part of a HELLO block/URL.
Definition: hello-uri.c:50
struct GNUNET_HashCode h_addrs
Hash over all addresses.
Definition: hello-uri.c:64
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
Purpose must be GNUNET_SIGNATURE_PURPOSE_HELLO.
Definition: hello-uri.c:54
Message to request a signature from PILS.
Definition: pils.h:213
uint32_t rid
Request ID.
Definition: pils.h:222
Message containing the signature.
Definition: pils.h:185
uint32_t rid
Request ID.
Definition: pils.h:204
struct GNUNET_PeerIdentity peer_id
The peer identity that produces the signature.
Definition: pils.h:194
struct GNUNET_CRYPTO_EddsaSignature sig
The signature.
Definition: pils.h:199