123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690 |
- /* Copyright 2001,2002 Roger Dingledine, Matej Pfajfar. */
- /* See LICENSE for licensing information */
- /* $Id$ */
- #include "or.h"
- /********* START VARIABLES **********/
- tracked_onion_t *tracked_onions = NULL; /* linked list of tracked onions */
- tracked_onion_t *last_tracked_onion = NULL;
- /********* END VARIABLES ************/
- int decide_aci_type(uint32_t local_addr, uint16_t local_port,
- uint32_t remote_addr, uint16_t remote_port) {
- if(local_addr > remote_addr)
- return ACI_TYPE_HIGHER;
- if(local_addr < remote_addr)
- return ACI_TYPE_LOWER;
- if(local_port > remote_port)
- return ACI_TYPE_HIGHER;
- /* else */
- return ACI_TYPE_LOWER;
- }
- int process_onion(circuit_t *circ, connection_t *conn) {
- aci_t aci_type;
- if(!decrypt_onion((onion_layer_t *)circ->onion,circ->onionlen,conn->prkey)) {
- log(LOG_DEBUG,"command_process_create_cell(): decrypt_onion() failed, closing circuit.");
- return -1;
- }
- log(LOG_DEBUG,"command_process_create_cell(): Onion decrypted.");
- /* check freshness */
- if (((onion_layer_t *)circ->onion)->expire < time(NULL)) /* expired onion */
- {
- log(LOG_NOTICE,"I have just received an expired onion. This could be a replay attack.");
- return -1;
- }
- aci_type = decide_aci_type(conn->local.sin_addr.s_addr, conn->local.sin_port,
- ((onion_layer_t *)circ->onion)->addr,((onion_layer_t *)circ->onion)->port);
-
- if(circuit_init(circ, aci_type) < 0) {
- log(LOG_ERR,"process_onion(): init_circuit() failed.");
- return -1;
- }
- /* check for replay */
- if(id_tracked_onion(circ->onion, circ->onionlen, tracked_onions)) {
- log(LOG_NOTICE,"process_onion(): I have just received a replayed onion. This could be a replay attack.");
- return -1;
- }
- /* track the new onion */
- if(!new_tracked_onion(circ->onion,circ->onionlen, &tracked_onions, &last_tracked_onion)) {
- log(LOG_DEBUG,"process_onion(): Onion tracking failed. Will ignore.");
- }
- return 0;
- }
- /* uses a weighted coin with weight cw to choose a route length */
- int chooselen(double cw)
- {
- int len = 2;
- int retval = 0;
- unsigned char coin;
-
- if ((cw < 0) || (cw >= 1)) /* invalid parameter */
- return -1;
-
- while(1)
- {
- retval = crypto_pseudo_rand(1, &coin);
- if (retval)
- return -1;
-
- if (coin > cw*255) /* don't extend */
- break;
- else
- len++;
- }
-
- return len;
- }
- /* returns an array of pointers to routent that define a new route through the OR network
- * int cw is the coin weight to use when choosing the route
- * order of routers is from last to first
- */
- unsigned int *new_route(double cw, routerinfo_t **rarray, size_t rarray_len, size_t *rlen)
- {
- int routelen = 0;
- int i = 0;
- int retval = 0;
- unsigned int *route = NULL;
- unsigned int oldchoice, choice;
-
- assert((cw >= 0) && (cw < 1) && (rarray) && (rlen) ); /* valid parameters */
- routelen = chooselen(cw);
- if (routelen == -1)
- {
- log(LOG_ERR,"Choosing route length failed.");
- return NULL;
- }
- log(LOG_DEBUG,"new_route(): Chosen route length %u.",routelen);
- /* FIXME need to figure out how many routers we can actually choose from.
- * We can get into an infinite loop if there are too few. */
-
- /* allocate memory for the new route */
- route = (unsigned int *)malloc(routelen * sizeof(unsigned int));
- if (!route)
- {
- log(LOG_ERR,"Memory allocation failed.");
- return NULL;
- }
-
- oldchoice = rarray_len;
- for(i=0;i<routelen;i++)
- {
- log(LOG_DEBUG,"new_route() : Choosing hop %u.",i);
- retval = crypto_pseudo_rand(sizeof(unsigned int),(unsigned char *)&choice);
- if (retval)
- {
- free((void *)route);
- return NULL;
- }
- choice = choice % (rarray_len);
- log(LOG_DEBUG,"new_route() : Chosen router %u.",choice);
- if (choice == oldchoice ||
- (oldchoice < rarray_len && !pkey_cmp(rarray[choice]->pkey, rarray[oldchoice]->pkey)) ||
- !connection_twin_get_by_addr_port(rarray[choice]->addr, rarray[choice]->or_port)) {
- /* Same router as last choice, or router twin,
- * or no routers with that key are connected to us.
- * Try again. */
- i--;
- continue;
- }
- oldchoice = choice;
- route[i] = choice;
- }
-
- *rlen = routelen;
- return route;
- }
- /* creates a new onion from route, stores it and its length into bufp and lenp respectively */
- unsigned char *create_onion(routerinfo_t **rarray, size_t rarray_len, unsigned int *route, size_t routelen, size_t *lenp, crypt_path_t **cpathp)
- {
- int i,j;
- int retval = 0;
- onion_layer_t *layer = NULL;
- crypt_path_t *hop = NULL;
- unsigned char *retbuf = NULL;
- unsigned char *bufp;
- routerinfo_t *router;
- unsigned char iv[16];
- assert(rarray && route && lenp && routelen);
- /* calculate the size of the onion */
- *lenp = routelen * 28 + 100; /* 28 bytes per layer + 100 bytes padding for the innermost layer */
- log(LOG_DEBUG,"create_onion() : Size of the onion is %u.",*lenp);
-
- /* allocate memory for the onion */
- bufp = (unsigned char *)malloc(*lenp);
- if (!bufp)
- {
- log(LOG_ERR,"Error allocating memory.");
- return NULL;
- }
- log(LOG_DEBUG,"create_onion() : Allocated memory for the onion.");
-
- for (retval=0; retval<routelen;retval++)
- {
- log(LOG_DEBUG,"create_onion() : %u : %s:%u, %u/%u",routelen-retval,inet_ntoa(*((struct in_addr *)&((rarray[route[retval]])->addr))),ntohs((rarray[route[retval]])->or_port),(rarray[route[retval]])->pkey,crypto_pk_keysize((rarray[route[retval]])->pkey));
- }
-
- layer = (onion_layer_t *)(bufp + *lenp - 128); /* pointer to innermost layer */
- /* create the onion layer by layer, starting with the innermost */
- for (i=0;i<routelen;i++)
- {
- router = rarray[route[i]];
-
- log(LOG_DEBUG,"create_onion() : %u",router);
- log(LOG_DEBUG,"create_onion() : This router is %s:%u",inet_ntoa(*((struct in_addr *)&router->addr)),ntohs(router->or_port));
- log(LOG_DEBUG,"create_onion() : Key pointer = %u.",router->pkey);
- log(LOG_DEBUG,"create_onion() : Key size = %u.",crypto_pk_keysize(router->pkey));
-
- /* 0 bit */
- layer->zero = 0;
- /* version */
- layer->version = VERSION;
- /* Back F + Forw F both use DES OFB*/
- layer->backf = ONION_DEFAULT_CIPHER;
- layer->forwf = ONION_DEFAULT_CIPHER;
- /* Dest Port */
- if (i) /* not last hop */
- layer->port = rarray[route[i-1]]->or_port;
- else
- layer->port = 0;
- /* Dest Addr */
- if (i) /* not last hop */
- layer->addr = rarray[route[i-1]]->addr;
- else
- layer->addr = 0;
- /* Expiration Time */
- layer->expire = time(NULL) + 3600; /* NOW + 1 hour */
- /* Key Seed Material */
- retval = crypto_rand(16, layer->keyseed);
- if (retval) /* error */
- {
- log(LOG_ERR,"Error generating random data.");
- free((void *)bufp);
- if (cpathp)
- {
- for (j=0;j<i;j++) {
- if (cpathp[i]->f_crypto)
- crypto_free_cipher_env(cpathp[i]->f_crypto);
- if (cpathp[i]->b_crypto)
- crypto_free_cipher_env(cpathp[i]->b_crypto);
-
- free((void *)cpathp[i]);
- }
- }
- return NULL;
- }
- log(LOG_DEBUG,"create_onion() : Onion layer %u built : %u, %u, %u, %s, %u.",i+1,layer->zero,layer->backf,layer->forwf,inet_ntoa(*((struct in_addr *)&layer->addr)),ntohs(layer->port));
-
- /* build up the crypt_path */
- if (cpathp)
- {
- cpathp[i] = (crypt_path_t *)malloc(sizeof(crypt_path_t));
- if (!cpathp[i])
- {
- log(LOG_ERR,"Error allocating memory.");
- free((void *)bufp);
- for (j=0;j<i;j++) {
- if (cpathp[i]->f_crypto)
- crypto_free_cipher_env(cpathp[i]->f_crypto);
- if (cpathp[i]->b_crypto)
- crypto_free_cipher_env(cpathp[i]->b_crypto);
-
- free((void *)cpathp[i]);
- }
- }
-
- log(LOG_DEBUG,"create_onion() : Building hop %u of crypt path.",i+1);
- hop = cpathp[i];
- /* set crypto functions */
- hop->backf = layer->backf;
- hop->forwf = layer->forwf;
-
- /* calculate keys */
- crypto_SHA_digest(layer->keyseed,16,hop->digest3);
- log(LOG_DEBUG,"create_onion() : First SHA pass performed.");
- crypto_SHA_digest(hop->digest3,20,hop->digest2);
- log(LOG_DEBUG,"create_onion() : Second SHA pass performed.");
- crypto_SHA_digest(hop->digest2,20,hop->digest3);
- log(LOG_DEBUG,"create_onion() : Third SHA pass performed.");
- log(LOG_DEBUG,"create_onion() : Keys generated.");
- /* set IV to zero */
- memset((void *)iv,0,16);
-
- /* initialize cipher engines */
- switch(layer->forwf)
- {
- case ONION_CIPHER_DES :
- hop->f_crypto = crypto_new_cipher_env(CRYPTO_CIPHER_DES);
- break;
- case ONION_CIPHER_RC4 :
- hop->f_crypto = crypto_new_cipher_env(CRYPTO_CIPHER_RC4);
- break;
- case ONION_CIPHER_IDENTITY :
- hop->f_crypto = crypto_new_cipher_env(CRYPTO_CIPHER_IDENTITY);
- break;
- }
- if (!hop->f_crypto) /* cipher initialization failed */
- {
- log(LOG_ERR,"Could not create a crypto environment.");
- free((void *)bufp);
- for (j=0;j<i;j++) {
- if (cpathp[i]->f_crypto)
- crypto_free_cipher_env(cpathp[i]->f_crypto);
- if (cpathp[i]->b_crypto)
- crypto_free_cipher_env(cpathp[i]->b_crypto);
- free((void *)cpathp[i]);
- }
- return NULL;
- }
- /* set the key and IV */
- if (crypto_cipher_set_key(hop->f_crypto, hop->digest3) ||
- crypto_cipher_set_iv(hop->f_crypto, iv)) {
- log(LOG_ERR,"Could not initialize the crypto engine.");
- free((void *)bufp);
- for (j=0;j<i;j++) {
- if (cpathp[i]->f_crypto)
- crypto_free_cipher_env(cpathp[i]->f_crypto);
- if (cpathp[i]->b_crypto)
- crypto_free_cipher_env(cpathp[i]->b_crypto);
- free((void *)cpathp[i]);
- }
- return NULL;
- }
-
- switch(layer->backf)
- {
- case ONION_CIPHER_DES :
- hop->b_crypto = crypto_new_cipher_env(CRYPTO_CIPHER_DES);
- break;
- case ONION_CIPHER_RC4 :
- hop->b_crypto = crypto_new_cipher_env(CRYPTO_CIPHER_RC4);
- break;
- case ONION_CIPHER_IDENTITY :
- hop->b_crypto = crypto_new_cipher_env(CRYPTO_CIPHER_IDENTITY);
- break;
- }
- if (!hop->b_crypto) /* cipher initialization failed */
- {
- log(LOG_ERR,"Could not create a crypto environment.");
- free((void *)bufp);
- for (j=0;j<i;j++) {
- if (cpathp[i]->f_crypto)
- crypto_free_cipher_env(cpathp[i]->f_crypto);
- if (cpathp[i]->b_crypto)
- crypto_free_cipher_env(cpathp[i]->b_crypto);
- free((void *)cpathp[i]);
- }
- return NULL;
- }
- /* set the key and IV */
- if (crypto_cipher_set_key(hop->b_crypto, hop->digest2) ||
- crypto_cipher_set_iv(hop->b_crypto, iv)) {
- log(LOG_ERR,"Could not initialize the crypto engine.");
- free((void *)bufp);
- for (j=0;j<i;j++) {
- if (cpathp[i]->f_crypto)
- crypto_free_cipher_env(cpathp[i]->f_crypto);
- if (cpathp[i]->b_crypto)
- crypto_free_cipher_env(cpathp[i]->b_crypto);
- free((void *)cpathp[i]);
- }
- return NULL;
- }
- /* initialize */
- if (crypto_cipher_encrypt_init_cipher(hop->f_crypto) || crypto_cipher_decrypt_init_cipher(hop->b_crypto)) {
- log(LOG_ERR,"Could not initialize the crypto engine.");
- free((void *)bufp);
- for (j=0;j<i;j++) {
- if (cpathp[i]->f_crypto)
- crypto_free_cipher_env(cpathp[i]->f_crypto);
- if (cpathp[i]->b_crypto)
- crypto_free_cipher_env(cpathp[i]->b_crypto);
- free((void *)cpathp[i]);
- }
- return NULL;
- }
-
- log(LOG_DEBUG,"create_onion() : Built corresponding crypt path hop.");
- }
-
- /* padding if this is the innermost layer */
- if (!i)
- {
- retval=crypto_pseudo_rand(100, (unsigned char *)layer + 28);
- if (retval) /* error */
- {
- log(LOG_ERR,"Error generating pseudo-random data.");
- free((void *)bufp);
- if (cpathp)
- {
- for (j=0;j<i;j++) {
- if (cpathp[i]->f_crypto)
- crypto_free_cipher_env(cpathp[i]->f_crypto);
- if (cpathp[i]->b_crypto)
- crypto_free_cipher_env(cpathp[i]->b_crypto);
- free((void *)cpathp[i]);
- }
- }
- return NULL;
- }
- log(LOG_DEBUG,"create_onion() : This is the innermost layer. Adding 100 bytes of padding.");
- }
-
- /* encrypt */
- retbuf = encrypt_onion(layer,128+(i*28),router->pkey);
- if (!retbuf)
- {
- log(LOG_ERR,"Error encrypting onion layer.");
- free((void *)bufp);
- if (cpathp)
- {
- for (j=0;j<i;j++) {
- if (cpathp[i]->f_crypto)
- crypto_free_cipher_env(cpathp[i]->f_crypto);
- if (cpathp[i]->b_crypto)
- crypto_free_cipher_env(cpathp[i]->b_crypto);
- free((void *)cpathp[i]);
- }
- }
- return NULL;
- }
- log(LOG_DEBUG,"create_onion() : Encrypted layer.");
-
- /* calculate pointer to next layer */
- layer = (onion_layer_t *)(bufp + (routelen-i-2)*sizeof(onion_layer_t));
- }
- return bufp;
- }
- /* encrypts 128 bytes of the onion with the specified public key, the rest with
- * DES OFB with the key as defined in the outter layer */
- unsigned char *encrypt_onion(onion_layer_t *onion, uint32_t onionlen, crypto_pk_env_t *pkey)
- {
- unsigned char *tmpbuf = NULL; /* temporary buffer for crypto operations */
- unsigned char digest[20]; /* stores SHA1 output - 160 bits */
- unsigned char iv[8];
- int retval = 0;
-
- crypto_cipher_env_t *crypt_env; /* crypto environment */
-
- if ( (onion) && (pkey) ) /* valid parameters */
- {
- memset((void *)iv,0,8);
-
- log(LOG_DEBUG,"Onion layer : %u, %u, %u, %s, %u.",onion->zero,onion->backf,onion->forwf,inet_ntoa(*((struct in_addr *)&onion->addr)),ntohs(onion->port));
- /* allocate space for tmpbuf */
- tmpbuf = (unsigned char *)malloc(onionlen);
- if (!tmpbuf)
- {
- log(LOG_ERR,"Could not allocate memory.");
- return NULL;
- }
- log(LOG_DEBUG,"encrypt_onion() : allocated %u bytes of memory for the encrypted onion (at %u).",onionlen,tmpbuf);
-
- /* get key1 = SHA1(KeySeed) */
- if (crypto_SHA_digest(((onion_layer_t *)onion)->keyseed,16,digest))
- {
- log(LOG_ERR,"Error computing SHA1 digest.");
- free((void *)tmpbuf);
- return NULL;
- }
- log(LOG_DEBUG,"encrypt_onion() : Computed DES key.");
-
- log(LOG_DEBUG,"encrypt_onion() : Trying to RSA encrypt.");
- /* encrypt 128 bytes with RSA *pkey */
- retval = crypto_pk_public_encrypt(pkey, (unsigned char *)onion, 128, tmpbuf, RSA_NO_PADDING);
- if (retval == -1)
- {
- log(LOG_ERR,"Error RSA-encrypting data :%s",crypto_perror());
- free((void *)tmpbuf);
- return NULL;
- }
-
- log(LOG_DEBUG,"encrypt_onion() : RSA encrypted first 128 bytes of the onion.");
-
- /* now encrypt the rest with DES OFB */
- crypt_env = crypto_new_cipher_env(CRYPTO_CIPHER_DES);
- if (!crypt_env)
- {
- log(LOG_ERR,"Error creating the crypto environment.");
- free((void *)tmpbuf);
- return NULL;
- }
- if (crypto_cipher_set_key(crypt_env, digest)) /* error */
- {
- log(LOG_ERR,"Error initializing DES engine:%s",crypto_perror());
- free((void *)tmpbuf);
- return NULL;
- }
- if (crypto_cipher_set_iv(crypt_env, iv))
- {
- log(LOG_ERR,"Error initializing DES engine:%s",crypto_perror());
- free((void *)tmpbuf);
- return NULL;
- }
- if (crypto_cipher_encrypt_init_cipher(crypt_env)) {
- log(LOG_ERR,"Error initializing DES engine:%s",crypto_perror());
- free((void *)tmpbuf);
- return NULL;
- }
-
- retval = crypto_cipher_encrypt(crypt_env,(unsigned char *)onion+128, onionlen-128, (unsigned char *)tmpbuf+128);
- if (retval) /* error */
- {
- log(LOG_ERR,"Error performing DES encryption:%s",crypto_perror());
- free((void *)tmpbuf);
- return NULL;
- }
- log(LOG_DEBUG,"encrypt_onion() : DES OFB encrypted the rest of the onion.");
-
- crypto_free_cipher_env(crypt_env);
-
- /* now copy tmpbuf to onion */
- memcpy((void *)onion,(void *)tmpbuf,onionlen);
- log(LOG_DEBUG,"encrypt_onion() : Copied cipher to original onion buffer.");
- free((void *)tmpbuf);
- return (unsigned char *)onion;
- } /* valid parameters */
- else
- return NULL;
- }
- /* decrypts the first 128 bytes using RSA and prkey, decrypts the rest with DES OFB with key1 */
- unsigned char *decrypt_onion(onion_layer_t *onion, uint32_t onionlen, crypto_pk_env_t *prkey)
- {
- void *tmpbuf = NULL; /* temporary buffer for crypto operations */
- unsigned char digest[20]; /* stores SHA1 output - 160 bits */
- unsigned char iv[8];
- int retval = 0;
-
- crypto_cipher_env_t *crypt_env; /* crypto environment */
-
- if ( (onion) && (prkey) ) /* valid parameters */
- {
- memset((void *)iv,0,8);
-
- /* allocate space for tmpbuf */
- tmpbuf = malloc(onionlen);
- if (!tmpbuf)
- {
- log(LOG_ERR,"Could not allocate memory.");
- return NULL;
- }
- log(LOG_DEBUG,"decrypt_onion() : Allocated memory for the temporary buffer.");
- /* decrypt 128 bytes with RSA *prkey */
- retval = crypto_pk_private_decrypt(prkey, (unsigned char*)onion, 128, (unsigned char *)tmpbuf, RSA_NO_PADDING);
- if (retval == -1)
- {
- log(LOG_ERR,"Error RSA-decrypting data :%s",crypto_perror());
- free((void *)tmpbuf);
- return NULL;
- }
- log(LOG_DEBUG,"decrypt_onion() : RSA decryption complete.");
-
- /* get key1 = SHA1(KeySeed) */
- retval = crypto_SHA_digest(((onion_layer_t *)tmpbuf)->keyseed,16,digest);
- if (retval)
- {
- log(LOG_ERR,"Error computing SHA1 digest.");
- free((void *)tmpbuf);
- return NULL;
- }
- log(LOG_DEBUG,"decrypt_onion() : Computed DES key.");
-
- /* now decrypt the rest with DES OFB */
- crypt_env = crypto_new_cipher_env(CRYPTO_CIPHER_DES);
- if (!crypt_env)
- {
- log(LOG_ERR,"Error creating the crypto environment.");
- free((void *)tmpbuf);
- return NULL;
- }
- if (crypto_cipher_set_key(crypt_env, digest)) /* error */
- {
- log(LOG_ERR,"Error initializing DES engine:%s",crypto_perror());
- free((void *)tmpbuf);
- return NULL;
- }
- if (crypto_cipher_set_iv(crypt_env, iv))
- {
- log(LOG_ERR,"Error initializing DES engine:%s",crypto_perror());
- free((void *)tmpbuf);
- return NULL;
- }
- if (crypto_cipher_decrypt_init_cipher(crypt_env)) {
- log(LOG_ERR,"Error initializing DES engine:%s",crypto_perror());
- free((void *)tmpbuf);
- return NULL;
- }
-
- retval = crypto_cipher_decrypt(crypt_env,(unsigned char *)onion+128, onionlen-128,(unsigned char *)tmpbuf+128);
- if (retval) /* error */
- {
- log(LOG_ERR,"Error performing DES decryption:%s",crypto_perror());
- free((void *)tmpbuf);
- return NULL;
- }
-
- crypto_free_cipher_env(crypt_env);
- log(LOG_DEBUG,"decrypt_onion() : DES decryption complete.");
-
- /* now copy tmpbuf to onion */
- memcpy((void *)onion,(void *)tmpbuf,onionlen);
- free((void *)tmpbuf);
- return (unsigned char *)onion;
- } /* valid parameters */
- else
- return NULL;
- }
- /* delete first n bytes of the onion and pads the end with n bytes of random data */
- void pad_onion(unsigned char *onion, uint32_t onionlen, size_t n)
- {
- if (onion) /* valid parameter */
- {
- memmove((void *)onion,(void *)(onion+n),onionlen-n);
- crypto_pseudo_rand(n, onion+onionlen-n);
- }
- }
- /* create a new tracked_onion entry */
- tracked_onion_t *new_tracked_onion(unsigned char *onion, uint32_t onionlen, tracked_onion_t **tracked_onions, tracked_onion_t **last_tracked_onion)
- {
- tracked_onion_t *to = NULL;
-
- if (!onion || !tracked_onions || !last_tracked_onion) /* invalid parameters */
- return NULL;
-
- to = (tracked_onion_t *)malloc(sizeof(tracked_onion_t));
- if (!to)
- return NULL;
-
- to->expire = ((onion_layer_t *)onion)->expire; /* set the expiration date */
- /* compute the SHA digest */
- if (crypto_SHA_digest(onion, onionlen, to->digest))
- {
- log(LOG_DEBUG,"new_tracked_onion() : Failed to compute a SHA1 digest of the onion.");
- free((void *)to);
- return NULL;
- }
-
- to->next = NULL;
-
- if (!*tracked_onions)
- {
- to->prev = NULL;
- *tracked_onions = to;
- }
- else
- {
- to->prev = (void *)*last_tracked_onion;
- (*last_tracked_onion)->next = (void *)to;
- }
- *last_tracked_onion = to;
-
- return to;
- }
- /* delete a tracked onion entry */
- void remove_tracked_onion(tracked_onion_t *to, tracked_onion_t **tracked_onions, tracked_onion_t **last_tracked_onion)
- {
- if (!*tracked_onions || !*last_tracked_onion || !to)
- return;
-
- if (to->prev)
- ((tracked_onion_t *)to->prev)->next = to->next;
- if (to->next)
- ((tracked_onion_t *)to->next)->prev = to->prev;
-
- if (to == *tracked_onions)
- *tracked_onions = (tracked_onion_t *)to->next;
-
- if (to == *last_tracked_onion)
- *last_tracked_onion = (tracked_onion_t *)to->prev;
-
- free((void *)to);
-
- return;
- }
- /* find a tracked onion in the linked list of tracked onions */
- tracked_onion_t *id_tracked_onion(unsigned char *onion, uint32_t onionlen, tracked_onion_t *tracked_onions)
- {
- tracked_onion_t *to = tracked_onions;
- unsigned char digest[20];
-
- /* compute the SHA digest of the onion */
- crypto_SHA_digest(onion,onionlen, digest);
-
- while(to)
- {
- if (!memcmp((void *)digest, (void *)to->digest, 20))
- return to;
- to = (tracked_onion_t *)to->next;
- }
-
- return NULL;
- }
|