static int client1(int argc, char **argv) { /* client1 nodeID B -> msg state */ curve25519_public_key_t B; uint8_t node_id[DIGEST_LEN]; ntor_ntru_handshake_state_t *state = NULL; uint8_t msg[NTOR_NTRU_ONIONSKIN_LEN]; char buf[4096]; N_ARGS(4); BASE16(2, node_id, DIGEST_LEN); BASE16(3, B.public_key, CURVE25519_PUBKEY_LEN); if (onion_skin_ntor_ntru_create(node_id, &B, &state, msg)<0) { fprintf(stderr, "handshake failed"); return 2; } base16_encode(buf, sizeof(buf), (const char*)msg, sizeof(msg)); printf("%s\n", buf); base16_encode(buf, sizeof(buf), (void*)state, sizeof(*state)); printf("%s\n", buf); ntor_ntru_handshake_state_free(state); return 0; }
/** Constructor. Parses <b>status</b> for router status information. The given * string should match the router status entry format from Tor's dir-spec.txt. * The currently recognized lines are: * * "r" SP nickname SP identity SP digest SP publication SP IP SP ORPort * SP DirPort NL * "s" SP Flags NL * * Unrecognized lines are currently ignored. * * */ RouterStatus::RouterStatus(const QStringList &status) { bool ok; _valid = false; _flags = 0; _bandwidth = 0; foreach (QString line, status) { if (line.startsWith("r ")) { QStringList parts = line.split(" ", QString::SkipEmptyParts); if (parts.size() < 9) return; /* Nickname */ _name = parts.at(1); /* Identity key digest */ _id = base16_encode(QByteArray::fromBase64(parts.at(2).toAscii())); if (_id.isEmpty()) return; /* Most recent descriptor digest */ _digest = base16_encode(QByteArray::fromBase64(parts.at(3).toAscii())); if (_digest.isEmpty()) return; /* Most recent publication date */ _published = QDateTime::fromString(parts.at(4) + " " + parts.at(5), TIME_FORMAT); if (!_published.isValid()) return; /* IP address */ _ipAddress = QHostAddress(parts.at(6)); if (_ipAddress.isNull()) return; /* ORPort */ _orPort = parts.at(7).toUInt(&ok); if (!ok) return; /* DirPort */ _dirPort = parts.at(8).toUInt(&ok); if (!ok) return; _valid = true; } else if (line.startsWith("s ")) { /* Status flags */ QStringList flags = line.split(" ", QString::SkipEmptyParts); flags.removeFirst(); /* Remove the "s" */ foreach (QString flag, flags) { _flags |= flagValue(flag); } } else if (line.startsWith("w ")) {
static int client2(int argc, char **argv) { struct ntor_ntru_handshake_state_t state; uint8_t msg[NTOR_NTRU_REPLY_LEN]; int keybytes; uint8_t *keys; char *hexkeys; int result = 0; N_ARGS(5); BASE16(2, (&state), sizeof(state)); BASE16(3, msg, sizeof(msg)); INT(4, keybytes); keys = tor_malloc(keybytes); hexkeys = tor_malloc(keybytes*2+1); if (onion_skin_ntor_ntru_client_handshake(&state, msg, keys, keybytes)<0) { fprintf(stderr, "handshake failed"); result = 2; goto done; } base16_encode(hexkeys, keybytes*2+1, (const char*)keys, keybytes); printf("%s\n", hexkeys); done: tor_free(keys); tor_free(hexkeys); return result; }
/* ** mr_user ** parv[0] = sender prefix ** parv[1] = username (login name, account) ** parv[2] = client host name (used only from other servers) ** parv[3] = server host name (used only from other servers) ** parv[4] = users real name info */ static void mr_user(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { char *p; char *user; if (source_p->localClient->listener->flags & LISTENER_SERVER) { exit_client(source_p, &me, "Use a different port"); return; } if ((p = strchr(parv[1], '@')) != NULL) *p = '\0'; if (EmptyString(parv[4])) { sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, source_p->name[0] ? source_p->name : "*", "USER"); return; } if(!EmptyString(source_p->name)) { user = parv[1]; if(*user == '&') { user++; if(EmptyString(user)) user = parv[1]; else { if(!EmptyString(source_p->certfp)) { char buf[SHA_DIGEST_LENGTH*2+1]; base16_encode(buf, sizeof(buf), source_p->certfp, sizeof(source_p->certfp)); sendto_server(&me, NULL, NOCAPS, NOCAPS, ":%s AUTH 1 %s %s %s", me.name, user, source_p->name, buf); } else { sendto_server(&me, NULL, NOCAPS, NOCAPS, ":%s AUTH 0 %s %s %s", me.name, user, source_p->name, source_p->localClient->passwd); } strlcpy(source_p->info, parv[4], sizeof(source_p->info)); return; } } } do_local_user(parv[0], client_p, source_p, parv[1], /* username */ parv[2], /* host */ parv[3], /* server */ parv[4] /* users real name */ ); }
static chunk_t * b16_enc(const chunk_t *inp) { chunk_t *ch = chunk_new(inp->len * 2 + 1); base16_encode((char *)ch->buf, ch->len, (char*)inp->buf, inp->len); return ch; }
char * crypt_pass(char *password, int encode) { EVP_MD_CTX *mdctx; const EVP_MD *md; unsigned char md_value[EVP_MAX_MD_SIZE]; char buffer[2*DIGEST_LEN + 1]; char *ret; unsigned int md_len; md = EVP_get_digestbyname(DIGEST_FUNCTION); mdctx = EVP_MD_CTX_create(); EVP_MD_CTX_init(mdctx); EVP_DigestInit_ex(mdctx, md, NULL); EVP_DigestUpdate(mdctx, password, strlen(password)); EVP_DigestFinal_ex(mdctx, md_value, &md_len); EVP_MD_CTX_destroy(mdctx); if(encode) { base16_encode(buffer, sizeof(buffer), (char *)md_value, DIGEST_LEN); DupString(ret, buffer); } else { ret = MyMalloc(DIGEST_LEN); memcpy(ret, md_value, DIGEST_LEN); } return ret; }
static int server1(int argc, char **argv) { uint8_t msg_in[NTOR_ONIONSKIN_LEN]; curve25519_keypair_t kp; di_digest256_map_t *keymap=NULL; uint8_t node_id[DIGEST_LEN]; int keybytes; uint8_t msg_out[NTOR_REPLY_LEN]; uint8_t *keys = NULL; char *hexkeys = NULL; int result = 0; char buf[256]; /* server1: b nodeID msg N -> msg keys */ N_ARGS(6); BASE16(2, kp.seckey.secret_key, CURVE25519_SECKEY_LEN); BASE16(3, node_id, DIGEST_LEN); BASE16(4, msg_in, NTOR_ONIONSKIN_LEN); INT(5, keybytes); curve25519_public_key_generate(&kp.pubkey, &kp.seckey); dimap_add_entry(&keymap, kp.pubkey.public_key, &kp); keys = tor_malloc(keybytes); hexkeys = tor_malloc(keybytes*2+1); if (onion_skin_ntor_server_handshake( msg_in, keymap, NULL, node_id, msg_out, keys, (size_t)keybytes)<0) { fprintf(stderr, "handshake failed"); result = 2; goto done; } base16_encode(buf, sizeof(buf), (const char*)msg_out, sizeof(msg_out)); printf("%s\n", buf); base16_encode(hexkeys, keybytes*2+1, (const char*)keys, keybytes); printf("%s\n", hexkeys); done: tor_free(keys); tor_free(hexkeys); dimap_free(keymap, NULL); return result; }
/* replacement for torflow in Tor. for now just grab the bandwidth we configured * in the XML and use that as the measured bandwidth value. since our configured * bandwidth doesnt change over time, this could just be run once (by setting the * time far in the future so the file is not seen as outdated). but we need to * run it after all routers are loaded, so its best to re-run periodically. * * eventually we will want an option to run something similar to the actual * torflow scripts that download files over Tor and computes bandwidth values. * in that case it needs to run more often to keep monitoring the actual state * of the network. * * torflow writes a few things to the v3bwfile. all Tor currently uses is: * * 0123456789 * node_id=$0123456789ABCDEF0123456789ABCDEF01234567 bw=12345 * ... * * where 0123456789 is the time, 0123456789ABCDEF0123456789ABCDEF01234567 is * the relay's fingerprint, and 12345 is the measured bandwidth in ?. */ void scalliontor_init_v3bw(ScallionTor* stor) { /* open the bw file, clearing it if it exists */ FILE *v3bw = fopen(stor->v3bw_name, "w"); if(v3bw == NULL) { stor->shadowlibFuncs->log(SHADOW_LOG_LEVEL_MESSAGE, __FUNCTION__, "v3bandwidth file not updated: can not open file '%s'\n", stor->v3bw_name); return; } time_t maxtime = -1; /* print time part on first line */ if(fprintf(v3bw, "%lu\n", maxtime) < 0) { /* uhhhh... */ stor->shadowlibFuncs->log(SHADOW_LOG_LEVEL_MESSAGE, __FUNCTION__, "v3bandwidth file not updated: can write time '%u' to file '%s'\n", maxtime, stor->v3bw_name); return; } routerlist_t *rlist = router_get_routerlist(); routerinfo_t *rinfo; /* print an entry for each router */ for (int i=0; i < smartlist_len(rlist->routers); i++) { rinfo = smartlist_get(rlist->routers, i); /* get the fingerprint from its digest */ char node_id[HEX_DIGEST_LEN+1]; base16_encode(node_id, HEX_DIGEST_LEN+1, rinfo->cache_info.identity_digest, DIGEST_LEN); /* the network address */ in_addr_t netaddr = htonl(rinfo->addr); /* ask shadow for this node's configured bandwidth */ guint bwdown = 0, bwup = 0; stor->shadowlibFuncs->getBandwidth(netaddr, &bwdown, &bwup); /* XXX careful here! shadow bandwidth may be different than the consensus * right now i believe this v3bw file is not used to compute the consensus * "w Bandwidth" line, and * intercept_rep_hist_bandwidth_assess and * intercept_router_get_advertised_bandwidth_capped * takes care of things. so leave it for now. */ guint bw = MIN(bwup, bwdown); if(fprintf(v3bw, "node_id=$%s bw=%u\n", node_id, bw) < 0) { /* uhhhh... */ stor->shadowlibFuncs->log(SHADOW_LOG_LEVEL_MESSAGE, __FUNCTION__, "v3bandwidth file not updated: can write line 'node_id=$%s bw=%u\n' to file '%s'\n", node_id, bw, stor->v3bw_name); return; } } fclose(v3bw); /* reschedule */ stor->shadowlibFuncs->createCallback((ShadowPluginCallbackFunc)scalliontor_init_v3bw, (gpointer)stor, VTORFLOW_SCHED_PERIOD); }
/** * Finalise HTTP Digest * * @v ctx Digest context * @v out Buffer for digest output * @v len Buffer length */ static void http_digest_final ( struct md5_context *ctx, char *out, size_t len ) { uint8_t digest[MD5_DIGEST_SIZE]; /* Finalise and base16-encode MD5 digest */ digest_final ( &md5_algorithm, ctx, digest ); base16_encode ( digest, sizeof ( digest ), out, len ); }
/** Process an ESTABLISH_RENDEZVOUS cell by setting the circuit's purpose and * rendezvous cookie. */ int rend_mid_establish_rendezvous(or_circuit_t *circ, const uint8_t *request, size_t request_len) { char hexid[9]; int reason = END_CIRC_REASON_TORPROTOCOL; log_info(LD_REND, "Received an ESTABLISH_RENDEZVOUS request on circuit %u", (unsigned)circ->p_circ_id); if (circ->base_.purpose != CIRCUIT_PURPOSE_OR) { log_warn(LD_PROTOCOL, "Tried to establish rendezvous on non-OR circuit with purpose %s", circuit_purpose_to_string(circ->base_.purpose)); goto err; } if (circ->base_.n_chan) { log_warn(LD_PROTOCOL, "Tried to establish rendezvous on non-edge circuit"); goto err; } if (request_len != REND_COOKIE_LEN) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Invalid length on ESTABLISH_RENDEZVOUS."); goto err; } if (circuit_get_rendezvous(request)) { log_warn(LD_PROTOCOL, "Duplicate rendezvous cookie in ESTABLISH_RENDEZVOUS."); goto err; } /* Acknowledge the request. */ if (relay_send_command_from_edge(0,TO_CIRCUIT(circ), RELAY_COMMAND_RENDEZVOUS_ESTABLISHED, "", 0, NULL)<0) { log_warn(LD_PROTOCOL, "Couldn't send RENDEZVOUS_ESTABLISHED cell."); reason = END_CIRC_REASON_INTERNAL; goto err; } circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_REND_POINT_WAITING); circuit_set_rendezvous_cookie(circ, request); base16_encode(hexid,9,(char*)request,4); log_info(LD_REND, "Established rendezvous point on circuit %u for cookie %s", (unsigned)circ->p_circ_id, hexid); return 0; err: circuit_mark_for_close(TO_CIRCUIT(circ), reason); return -1; }
/* * ssl_handshake - let OpenSSL initialize the protocol. Register for * read/write events if necessary. */ static void ssl_handshake(int fd, struct Client *client_p) { int ret = SSL_accept(client_p->localClient->fd.ssl); X509 *cert; if ((cert = SSL_get_peer_certificate(client_p->localClient->fd.ssl)) != NULL) { int res = SSL_get_verify_result(client_p->localClient->fd.ssl); if (res == X509_V_OK || res == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN || res == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE || res == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) { /* The client sent a certificate which verified OK */ base16_encode(client_p->certfp, sizeof(client_p->certfp), (const char*)cert->sha1_hash, sizeof(cert->sha1_hash)); } else { ilog(L_WARN, "Client %s!%s@%s gave bad SSL client certificate: %d", client_p->name, client_p->username, client_p->host, res); } X509_free(cert); } if (ret <= 0) { if((CurrentTime - client_p->firsttime) > 30) { exit_client(client_p, client_p, "Timeout during SSL handshake"); return; } switch (SSL_get_error(client_p->localClient->fd.ssl, ret)) { case SSL_ERROR_WANT_WRITE: comm_setselect(&client_p->localClient->fd, COMM_SELECT_WRITE, (PF *) ssl_handshake, client_p, 30); return; case SSL_ERROR_WANT_READ: comm_setselect(&client_p->localClient->fd, COMM_SELECT_READ, (PF *) ssl_handshake, client_p, 30); return; default: exit_client(client_p, client_p, "Error during SSL handshake"); return; } } comm_settimeout(&client_p->localClient->fd, 0, NULL, NULL); execute_callback(auth_cb, client_p); }
/** Given a private or public key <b>pk</b>, put a hashed fingerprint of * the public key into <b>fp_out</b> (must have at least FINGERPRINT_LEN+1 * bytes of space). Return 0 on success, -1 on failure. * * Hashed fingerprints are computed as the SHA1 digest of the SHA1 digest * of the ASN.1 encoding of the public key, converted to hexadecimal, in * upper case. */ int crypto_pk_get_hashed_fingerprint(crypto_pk_t *pk, char *fp_out) { char digest[DIGEST_LEN], hashed_digest[DIGEST_LEN]; if (crypto_pk_get_digest(pk, digest)) { return -1; } if (crypto_digest(hashed_digest, digest, DIGEST_LEN)) { return -1; } base16_encode(fp_out, FINGERPRINT_LEN + 1, hashed_digest, DIGEST_LEN); return 0; }
static smartlist_t * cert_dl_status_sks_for_auth_id_mock(const char *digest) { smartlist_t *list = NULL; char sk[DIGEST_LEN]; char digest_str[HEX_DIGEST_LEN+1]; char *tmp; int len; tt_assert(digest != NULL); base16_encode(digest_str, HEX_DIGEST_LEN + 1, digest, DIGEST_LEN); digest_str[HEX_DIGEST_LEN] = '\0'; /* * Build a list of two hard-coded digests, depending on what we * were just passed. */ if (strcmp(digest_str, auth_id_digest_1_str) == 0) { list = smartlist_new(); len = base16_decode(sk, DIGEST_LEN, auth_1_sk_1_str, strlen(auth_1_sk_1_str)); tt_int_op(len, OP_EQ, DIGEST_LEN); tmp = tor_malloc(DIGEST_LEN); memcpy(tmp, sk, DIGEST_LEN); smartlist_add(list, tmp); len = base16_decode(sk, DIGEST_LEN, auth_1_sk_2_str, strlen(auth_1_sk_2_str)); tt_int_op(len, OP_EQ, DIGEST_LEN); tmp = tor_malloc(DIGEST_LEN); memcpy(tmp, sk, DIGEST_LEN); smartlist_add(list, tmp); } else if (strcmp(digest_str, auth_id_digest_2_str) == 0) { list = smartlist_new(); len = base16_decode(sk, DIGEST_LEN, auth_2_sk_1_str, strlen(auth_2_sk_1_str)); tt_int_op(len, OP_EQ, DIGEST_LEN); tmp = tor_malloc(DIGEST_LEN); memcpy(tmp, sk, DIGEST_LEN); smartlist_add(list, tmp); len = base16_decode(sk, DIGEST_LEN, auth_2_sk_2_str, strlen(auth_2_sk_2_str)); tt_int_op(len, OP_EQ, DIGEST_LEN); tmp = tor_malloc(DIGEST_LEN); memcpy(tmp, sk, DIGEST_LEN); smartlist_add(list, tmp); } done: return list; }
/** Process an ESTABLISH_RENDEZVOUS cell by setting the circuit's purpose and * rendezvous cookie. */ int rend_mid_establish_rendezvous(or_circuit_t *circ, const char *request, size_t request_len) { char hexid[9]; int reason = END_CIRC_REASON_TORPROTOCOL; log_info(LD_REND, "Received an ESTABLISH_RENDEZVOUS request on circuit %d", circ->p_circ_id); if (circ->_base.purpose != CIRCUIT_PURPOSE_OR || circ->_base.n_conn) { log_warn(LD_PROTOCOL, "Tried to establish rendezvous on non-OR or non-edge circuit."); goto err; } if (request_len != REND_COOKIE_LEN) { log_warn(LD_PROTOCOL, "Invalid length on ESTABLISH_RENDEZVOUS."); goto err; } if (circuit_get_rendezvous(request)) { log_warn(LD_PROTOCOL, "Duplicate rendezvous cookie in ESTABLISH_RENDEZVOUS."); goto err; } /* Acknowledge the request. */ if (relay_send_command_from_edge(0,TO_CIRCUIT(circ), RELAY_COMMAND_RENDEZVOUS_ESTABLISHED, "", 0, NULL)<0) { log_warn(LD_PROTOCOL, "Couldn't send RENDEZVOUS_ESTABLISHED cell."); reason = END_CIRC_REASON_INTERNAL; goto err; } circ->_base.purpose = CIRCUIT_PURPOSE_REND_POINT_WAITING; memcpy(circ->rend_token, request, REND_COOKIE_LEN); base16_encode(hexid,9,request,4); log_info(LD_REND, "Established rendezvous point on circuit %d for cookie %s", circ->p_circ_id, hexid); return 0; err: circuit_mark_for_close(TO_CIRCUIT(circ), reason); return -1; }
/* Allocate a new commit object and initializing it with <b>rsa_identity</b> * that MUST be provided. The digest algorithm is set to the default one * that is supported. The rest is uninitialized. This never returns NULL. */ static sr_commit_t * commit_new(const char *rsa_identity) { sr_commit_t *commit; tor_assert(rsa_identity); commit = tor_malloc_zero(sizeof(*commit)); commit->alg = SR_DIGEST_ALG; memcpy(commit->rsa_identity, rsa_identity, sizeof(commit->rsa_identity)); base16_encode(commit->rsa_identity_hex, sizeof(commit->rsa_identity_hex), commit->rsa_identity, sizeof(commit->rsa_identity)); return commit; }
static download_status_t * cert_dl_status_fp_sk_mock(const char *fp_digest, const char *sk_digest) { download_status_t *dl = NULL; char fp_digest_str[HEX_DIGEST_LEN+1], sk_digest_str[HEX_DIGEST_LEN+1]; /* * Unpack the digests so we can compare them and figure out which * dl status we want. */ tt_assert(fp_digest != NULL); base16_encode(fp_digest_str, HEX_DIGEST_LEN + 1, fp_digest, DIGEST_LEN); fp_digest_str[HEX_DIGEST_LEN] = '\0'; tt_assert(sk_digest != NULL); base16_encode(sk_digest_str, HEX_DIGEST_LEN + 1, sk_digest, DIGEST_LEN); sk_digest_str[HEX_DIGEST_LEN] = '\0'; if (strcmp(fp_digest_str, auth_id_digest_1_str) == 0) { if (strcmp(sk_digest_str, auth_1_sk_1_str) == 0) { dl = &auth_1_sk_1_dls; } else if (strcmp(sk_digest_str, auth_1_sk_2_str) == 0) { dl = &auth_1_sk_2_dls; } } else if (strcmp(fp_digest_str, auth_id_digest_2_str) == 0) { if (strcmp(sk_digest_str, auth_2_sk_1_str) == 0) { dl = &auth_2_sk_1_dls; } else if (strcmp(sk_digest_str, auth_2_sk_2_str) == 0) { dl = &auth_2_sk_2_dls; } } done: return dl; }
/** Given a private or public key <b>pk</b>, put a fingerprint of the * public key into <b>fp_out</b> (must have at least FINGERPRINT_LEN+1 bytes of * space). Return 0 on success, -1 on failure. * * Fingerprints are computed as the SHA1 digest of the ASN.1 encoding * of the public key, converted to hexadecimal, in upper case, with a * space after every four digits. * * If <b>add_space</b> is false, omit the spaces. */ int crypto_pk_get_fingerprint(crypto_pk_t *pk, char *fp_out, int add_space) { char digest[DIGEST_LEN]; char hexdigest[HEX_DIGEST_LEN+1]; if (crypto_pk_get_digest(pk, digest)) { return -1; } base16_encode(hexdigest,sizeof(hexdigest),digest,DIGEST_LEN); if (add_space) { crypto_add_spaces_to_fp(fp_out, FINGERPRINT_LEN+1, hexdigest); } else { sgx_strncpy(fp_out, hexdigest, HEX_DIGEST_LEN+1); } return 0; }
/** * Encrypts a string (str struct). * * @param src - the string that needs to be encrypted.Must NOT contain \0 * @returns - the encrypted string, allocated in this function. */ str thig_encrypt(str src) { int padding; str my_text={0,0},enc_text={0,0}; cipherInstance ci2 = ci; str encoded={0,0}; padding = (src.len%byteCnt)==0?0:byteCnt-(src.len%byteCnt); LOG(L_ERR,"DBG:"M_NAME":encrypt:String has length %d so needs padding %d\n",src.len,padding); my_text.len = src.len+padding; my_text.s = pkg_malloc(my_text.len); if (!my_text.s){ LOG(L_ERR,"ERR:"M_NAME":encrypt: error allocating %d bytes\n",my_text.len); goto error; } memcpy(my_text.s,src.s,src.len); memset(my_text.s+src.len,0,my_text.len-src.len); enc_text.s = pkg_malloc(my_text.len); if (!enc_text.s){ LOG(L_ERR,"ERR:"M_NAME":encrypt: error allocating %d bytes\n",my_text.len); goto error; } enc_text.len = my_text.len; printstr("String bef :",my_text); if (blockEncrypt(&ci2,&ki,(unsigned char*)my_text.s,my_text.len*8,(unsigned char*)enc_text.s) != my_text.len*8){ LOG(L_ERR,"DBG:"M_NAME":encrypt: Error in encryption phase\n"); goto error; } printstr("String aft :",enc_text); #ifdef USE_BASE64 encoded = base64_encode(enc_text); #else encoded = base16_encode(enc_text); #endif if (my_text.s) pkg_free(my_text.s); if (enc_text.s) pkg_free(enc_text.s); return encoded; error: if (my_text.s) pkg_free(my_text.s); if (enc_text.s) pkg_free(enc_text.s); enc_text.s = 0;enc_text.len=0; return enc_text; }
/** Note that we failed to fetch a microdescriptor from the relay with * <b>relay_digest</b> (of size DIGEST_LEN). */ void microdesc_note_outdated_dirserver(const char *relay_digest) { char relay_hexdigest[HEX_DIGEST_LEN+1]; /* If we have a reasonably live consensus, then most of our dirservers should * still be caching all the microdescriptors in it. Reasonably live * consensuses are up to a day old (or a day in the future). But * microdescriptors expire 7 days after the last consensus that referenced * them. */ if (!networkstatus_get_reasonably_live_consensus(approx_time(), FLAV_MICRODESC)) { return; } if (!outdated_dirserver_list) { outdated_dirserver_list = smartlist_new(); } tor_assert(outdated_dirserver_list); /* If the list grows too big, clean it up */ if (BUG(smartlist_len(outdated_dirserver_list) > TOO_MANY_OUTDATED_DIRSERVERS)) { microdesc_reset_outdated_dirservers_list(); } /* Turn the binary relay digest to a hex since smartlists have better support * for strings than digests. */ base16_encode(relay_hexdigest,sizeof(relay_hexdigest), relay_digest, DIGEST_LEN); /* Make sure we don't add a dirauth as an outdated dirserver */ if (router_get_trusteddirserver_by_digest(relay_digest)) { log_info(LD_GENERAL, "Auth %s gave us outdated dirinfo.", relay_hexdigest); return; } /* Don't double-add outdated dirservers */ if (smartlist_contains_string(outdated_dirserver_list, relay_hexdigest)) { return; } /* Add it to the list of outdated dirservers */ smartlist_add_strdup(outdated_dirserver_list, relay_hexdigest); log_info(LD_GENERAL, "Noted %s as outdated md dirserver", relay_hexdigest); }
int main(int argc, char **argv) { if (argc>1) { unsigned char pk[64]; unsigned char sk[32]; int n; if (((n=open(argv[1],0))<0)||(read(n,sk,32)<32)||(close(n)<0)) return 64; crypto_scalarmult_curve25519_base(pk,sk); memcpy(sk,pk,32); if (base16_encode(pk,sk,32)!=64) return 255; if (write(1,"pubkey: ",8)!=8) return 255; if (write(1,pk,64)!=64) return 255; if (write(1,"\n",1)-1) return 255; return 0; } write(2,USAGE,strlen(USAGE)); return 64; }
/** Encode data into a NULL-terminated hex string. A convenience wrapper around @base16_encode, this function will return a NULL-terminated string containing the hexadecimal (base-16) representation of the input buffer $src, which should be $len bytes long. On success, returns a pointer to the newly-allocated string. The caller is responsible from memory management from then on. On failure, returns NULL and sets errno appropriately: - **`EINVAL`** - $len is too small (0 or below). */ char* base16_encodestr(const void *src, size_t len) { assert(src); errno = EINVAL; if (len <= 0) return NULL; size_t dlen = len * 2; char *dst = vmalloc(sizeof(char) * (dlen + 1)); int rc = base16_encode(dst, dlen, src, len); if (rc < 0) { free(dst); return NULL; } dst[rc] = '\0'; return dst; }
/** * Display status of a certificate * * @v cert X.509 certificate */ void certstat ( struct x509_certificate *cert ) { struct digest_algorithm *digest = &sha1_algorithm; uint8_t fingerprint[ digest->digestsize ]; char buf[ base16_encoded_len ( sizeof ( fingerprint ) ) + 1 /* NUL */ ]; /* Generate fingerprint */ x509_fingerprint ( cert, digest, fingerprint ); base16_encode ( fingerprint, sizeof ( fingerprint ), buf, sizeof ( buf ) ); /* Print certificate status */ printf ( "%s : %s", x509_name ( cert ), buf ); if ( cert->flags & X509_FL_PERMANENT ) printf ( " [PERMANENT]" ); if ( cert->flags & X509_FL_EXPLICIT ) printf ( " [EXPLICIT]" ); if ( x509_is_valid ( cert ) ) printf ( " [VALIDATED]" ); printf ( "\n" ); }
static download_status_t * cert_dl_status_def_for_auth_mock(const char *digest) { download_status_t *dl = NULL; char digest_str[HEX_DIGEST_LEN+1]; tt_assert(digest != NULL); base16_encode(digest_str, HEX_DIGEST_LEN + 1, digest, DIGEST_LEN); digest_str[HEX_DIGEST_LEN] = '\0'; if (strcmp(digest_str, auth_id_digest_1_str) == 0) { dl = &auth_def_cert_download_status_1; } else if (strcmp(digest_str, auth_id_digest_2_str) == 0) { dl = &auth_def_cert_download_status_2; } done: return dl; }
/** Return True if the relay with <b>relay_digest</b> (size DIGEST_LEN) is an * outdated dirserver */ int microdesc_relay_is_outdated_dirserver(const char *relay_digest) { char relay_hexdigest[HEX_DIGEST_LEN+1]; if (!outdated_dirserver_list) { return 0; } /* Convert identity digest to hex digest */ base16_encode(relay_hexdigest, sizeof(relay_hexdigest), relay_digest, DIGEST_LEN); /* Last time we tried to fetch microdescs, was this directory mirror missing * any mds we asked for? */ if (smartlist_contains_string(outdated_dirserver_list, relay_hexdigest)) { return 1; } return 0; }
static download_status_t * descbr_get_dl_by_digest_mock(const char *digest) { download_status_t *dl = NULL; char digest_str[HEX_DIGEST_LEN+1]; if (!disable_descbr) { tt_assert(digest != NULL); base16_encode(digest_str, HEX_DIGEST_LEN + 1, digest, DIGEST_LEN); digest_str[HEX_DIGEST_LEN] = '\0'; if (strcmp(digest_str, descbr_digest_1_str) == 0) { dl = &descbr_digest_1_dl; } else if (strcmp(digest_str, descbr_digest_2_str) == 0) { dl = &descbr_digest_2_dl; } } done: return dl; }
int sdp_mpeg4_es(uint8_t *data, int bytes, int payload, int frequence, const void* extra, int extra_size) { static const char* pattern = "m=video 0 RTP/AVP %d\n" "a=rtpmap:%d MP4V-ES/90000\n" "a=fmtp:%d profile-level-id=1;config="; int r, n; uint8_t i; n = snprintf((char*)data, bytes, pattern, payload, payload, payload); if (n + extra_size * 2 + 1 > bytes) return -1; // // don't have enough memory // It is a hexadecimal representation of an octet string that // expresses the MPEG-4 Visual configuration information n += base16_encode(data + n, extra, extra_size); if (n < bytes) data[n++] = '\n'; return n; }
/** Process a RENDEZVOUS1 cell by looking up the correct rendezvous * circuit by its relaying the cell's body in a RENDEZVOUS2 cell, and * connecting the two circuits. */ int rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request, size_t request_len) { or_circuit_t *rend_circ; char hexid[9]; int reason = END_CIRC_REASON_INTERNAL; if (circ->base_.purpose != CIRCUIT_PURPOSE_OR || circ->base_.n_chan) { log_info(LD_REND, "Tried to complete rendezvous on non-OR or non-edge circuit %u.", (unsigned)circ->p_circ_id); reason = END_CIRC_REASON_TORPROTOCOL; goto err; } if (request_len != REND_COOKIE_LEN+DH_KEY_LEN+DIGEST_LEN) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Rejecting RENDEZVOUS1 cell with bad length (%d) on circuit %u.", (int)request_len, (unsigned)circ->p_circ_id); reason = END_CIRC_REASON_TORPROTOCOL; goto err; } base16_encode(hexid, sizeof(hexid), (const char*)request, 4); log_info(LD_REND, "Got request for rendezvous from circuit %u to cookie %s.", (unsigned)circ->p_circ_id, hexid); rend_circ = circuit_get_rendezvous(request); if (!rend_circ) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Rejecting RENDEZVOUS1 cell with unrecognized rendezvous cookie %s.", hexid); reason = END_CIRC_REASON_TORPROTOCOL; goto err; } /* Send the RENDEZVOUS2 cell to Alice. */ if (relay_send_command_from_edge(0, TO_CIRCUIT(rend_circ), RELAY_COMMAND_RENDEZVOUS2, (char*)(request+REND_COOKIE_LEN), request_len-REND_COOKIE_LEN, NULL)) { log_warn(LD_GENERAL, "Unable to send RENDEZVOUS2 cell to client on circuit %u.", (unsigned)rend_circ->p_circ_id); goto err; } /* Join the circuits. */ log_info(LD_REND, "Completing rendezvous: circuit %u joins circuit %u (cookie %s)", (unsigned)circ->p_circ_id, (unsigned)rend_circ->p_circ_id, hexid); circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_REND_ESTABLISHED); circuit_change_purpose(TO_CIRCUIT(rend_circ), CIRCUIT_PURPOSE_REND_ESTABLISHED); circuit_set_rendezvous_cookie(circ, NULL); rend_circ->rend_splice = circ; circ->rend_splice = rend_circ; return 0; err: circuit_mark_for_close(TO_CIRCUIT(circ), reason); return -1; }
/** Called when we get an AUTHCHALLENGE command. */ int handle_control_authchallenge(control_connection_t *conn, uint32_t len, const char *body) { const char *cp = body; char *client_nonce; size_t client_nonce_len; char server_hash[DIGEST256_LEN]; char server_hash_encoded[HEX_DIGEST256_LEN+1]; char server_nonce[SAFECOOKIE_SERVER_NONCE_LEN]; char server_nonce_encoded[(2*SAFECOOKIE_SERVER_NONCE_LEN) + 1]; cp += strspn(cp, " \t\n\r"); if (!strcasecmpstart(cp, "SAFECOOKIE")) { cp += strlen("SAFECOOKIE"); } else { connection_write_str_to_buf("513 AUTHCHALLENGE only supports SAFECOOKIE " "authentication\r\n", conn); connection_mark_for_close(TO_CONN(conn)); return -1; } if (!authentication_cookie_is_set) { connection_write_str_to_buf("515 Cookie authentication is disabled\r\n", conn); connection_mark_for_close(TO_CONN(conn)); return -1; } cp += strspn(cp, " \t\n\r"); if (*cp == '"') { const char *newcp = decode_escaped_string(cp, len - (cp - body), &client_nonce, &client_nonce_len); if (newcp == NULL) { connection_write_str_to_buf("513 Invalid quoted client nonce\r\n", conn); connection_mark_for_close(TO_CONN(conn)); return -1; } cp = newcp; } else { size_t client_nonce_encoded_len = strspn(cp, "0123456789ABCDEFabcdef"); client_nonce_len = client_nonce_encoded_len / 2; client_nonce = tor_malloc_zero(client_nonce_len); if (base16_decode(client_nonce, client_nonce_len, cp, client_nonce_encoded_len) != (int) client_nonce_len) { connection_write_str_to_buf("513 Invalid base16 client nonce\r\n", conn); connection_mark_for_close(TO_CONN(conn)); tor_free(client_nonce); return -1; } cp += client_nonce_encoded_len; } cp += strspn(cp, " \t\n\r"); if (*cp != '\0' || cp != body + len) { connection_write_str_to_buf("513 Junk at end of AUTHCHALLENGE command\r\n", conn); connection_mark_for_close(TO_CONN(conn)); tor_free(client_nonce); return -1; } crypto_rand(server_nonce, SAFECOOKIE_SERVER_NONCE_LEN); /* Now compute and send the server-to-controller response, and the * server's nonce. */ tor_assert(authentication_cookie != NULL); { size_t tmp_len = (AUTHENTICATION_COOKIE_LEN + client_nonce_len + SAFECOOKIE_SERVER_NONCE_LEN); char *tmp = tor_malloc_zero(tmp_len); char *client_hash = tor_malloc_zero(DIGEST256_LEN); memcpy(tmp, authentication_cookie, AUTHENTICATION_COOKIE_LEN); memcpy(tmp + AUTHENTICATION_COOKIE_LEN, client_nonce, client_nonce_len); memcpy(tmp + AUTHENTICATION_COOKIE_LEN + client_nonce_len, server_nonce, SAFECOOKIE_SERVER_NONCE_LEN); crypto_hmac_sha256(server_hash, SAFECOOKIE_SERVER_TO_CONTROLLER_CONSTANT, strlen(SAFECOOKIE_SERVER_TO_CONTROLLER_CONSTANT), tmp, tmp_len); crypto_hmac_sha256(client_hash, SAFECOOKIE_CONTROLLER_TO_SERVER_CONSTANT, strlen(SAFECOOKIE_CONTROLLER_TO_SERVER_CONSTANT), tmp, tmp_len); conn->safecookie_client_hash = client_hash; tor_free(tmp); } base16_encode(server_hash_encoded, sizeof(server_hash_encoded), server_hash, sizeof(server_hash)); base16_encode(server_nonce_encoded, sizeof(server_nonce_encoded), server_nonce, sizeof(server_nonce)); connection_printf_to_buf(conn, "250 AUTHCHALLENGE SERVERHASH=%s " "SERVERNONCE=%s\r\n", server_hash_encoded, server_nonce_encoded); tor_free(client_nonce); return 0; }
/** Run unit tests for misc crypto formatting functionality (base64, base32, * fingerprints, etc) */ static void test_crypto_formats(void) { char *data1 = NULL, *data2 = NULL, *data3 = NULL; int i, j, idx; data1 = tor_malloc(1024); data2 = tor_malloc(1024); data3 = tor_malloc(1024); test_assert(data1 && data2 && data3); /* Base64 tests */ memset(data1, 6, 1024); for (idx = 0; idx < 10; ++idx) { i = base64_encode(data2, 1024, data1, idx); test_assert(i >= 0); j = base64_decode(data3, 1024, data2, i); test_eq(j,idx); test_memeq(data3, data1, idx); } strlcpy(data1, "Test string that contains 35 chars.", 1024); strlcat(data1, " 2nd string that contains 35 chars.", 1024); i = base64_encode(data2, 1024, data1, 71); test_assert(i >= 0); j = base64_decode(data3, 1024, data2, i); test_eq(j, 71); test_streq(data3, data1); test_assert(data2[i] == '\0'); crypto_rand(data1, DIGEST_LEN); memset(data2, 100, 1024); digest_to_base64(data2, data1); test_eq(BASE64_DIGEST_LEN, strlen(data2)); test_eq(100, data2[BASE64_DIGEST_LEN+2]); memset(data3, 99, 1024); test_eq(digest_from_base64(data3, data2), 0); test_memeq(data1, data3, DIGEST_LEN); test_eq(99, data3[DIGEST_LEN+1]); test_assert(digest_from_base64(data3, "###") < 0); /* Encoding SHA256 */ crypto_rand(data2, DIGEST256_LEN); memset(data2, 100, 1024); digest256_to_base64(data2, data1); test_eq(BASE64_DIGEST256_LEN, strlen(data2)); test_eq(100, data2[BASE64_DIGEST256_LEN+2]); memset(data3, 99, 1024); test_eq(digest256_from_base64(data3, data2), 0); test_memeq(data1, data3, DIGEST256_LEN); test_eq(99, data3[DIGEST256_LEN+1]); /* Base32 tests */ strlcpy(data1, "5chrs", 1024); /* bit pattern is: [35 63 68 72 73] -> * [00110101 01100011 01101000 01110010 01110011] * By 5s: [00110 10101 10001 10110 10000 11100 10011 10011] */ base32_encode(data2, 9, data1, 5); test_streq(data2, "gvrwq4tt"); strlcpy(data1, "\xFF\xF5\x6D\x44\xAE\x0D\x5C\xC9\x62\xC4", 1024); base32_encode(data2, 30, data1, 10); test_streq(data2, "772w2rfobvomsywe"); /* Base16 tests */ strlcpy(data1, "6chrs\xff", 1024); base16_encode(data2, 13, data1, 6); test_streq(data2, "3663687273FF"); strlcpy(data1, "f0d678affc000100", 1024); i = base16_decode(data2, 8, data1, 16); test_eq(i,0); test_memeq(data2, "\xf0\xd6\x78\xaf\xfc\x00\x01\x00",8); /* now try some failing base16 decodes */ test_eq(-1, base16_decode(data2, 8, data1, 15)); /* odd input len */ test_eq(-1, base16_decode(data2, 7, data1, 16)); /* dest too short */ strlcpy(data1, "f0dz!8affc000100", 1024); test_eq(-1, base16_decode(data2, 8, data1, 16)); tor_free(data1); tor_free(data2); tor_free(data3); /* Add spaces to fingerprint */ { data1 = tor_strdup("ABCD1234ABCD56780000ABCD1234ABCD56780000"); test_eq(strlen(data1), 40); data2 = tor_malloc(FINGERPRINT_LEN+1); add_spaces_to_fp(data2, FINGERPRINT_LEN+1, data1); test_streq(data2, "ABCD 1234 ABCD 5678 0000 ABCD 1234 ABCD 5678 0000"); tor_free(data1); tor_free(data2); } done: tor_free(data1); tor_free(data2); tor_free(data3); }
/** Helper: write the router-status information in <b>rs</b> into a newly * allocated character buffer. Use the same format as in network-status * documents. If <b>version</b> is non-NULL, add a "v" line for the platform. * * consensus_method is the current consensus method when format is * NS_V3_CONSENSUS or NS_V3_CONSENSUS_MICRODESC. It is ignored for other * formats: pass ROUTERSTATUS_FORMAT_NO_CONSENSUS_METHOD. * * Return 0 on success, -1 on failure. * * The format argument has one of the following values: * NS_V2 - Output an entry suitable for a V2 NS opinion document * NS_V3_CONSENSUS - Output the first portion of a V3 NS consensus entry * for consensus_method. * NS_V3_CONSENSUS_MICRODESC - Output the first portion of a V3 microdesc * consensus entry for consensus_method. * NS_V3_VOTE - Output a complete V3 NS vote. If <b>vrs</b> is present, * it contains additional information for the vote. * NS_CONTROL_PORT - Output a NS document for the control port. */ char * routerstatus_format_entry(const routerstatus_t *rs, const char *version, const char *protocols, routerstatus_format_type_t format, int consensus_method, const vote_routerstatus_t *vrs) { char *summary; char *result = NULL; char published[ISO_TIME_LEN+1]; char identity64[BASE64_DIGEST_LEN+1]; char digest64[BASE64_DIGEST_LEN+1]; smartlist_t *chunks = smartlist_new(); format_iso_time(published, rs->published_on); digest_to_base64(identity64, rs->identity_digest); digest_to_base64(digest64, rs->descriptor_digest); smartlist_add_asprintf(chunks, "r %s %s %s%s%s %s %d %d\n", rs->nickname, identity64, (format==NS_V3_CONSENSUS_MICRODESC)?"":digest64, (format==NS_V3_CONSENSUS_MICRODESC)?"":" ", published, fmt_addr32(rs->addr), (int)rs->or_port, (int)rs->dir_port); /* TODO: Maybe we want to pass in what we need to build the rest of * this here, instead of in the caller. Then we could use the * networkstatus_type_t values, with an additional control port value * added -MP */ /* V3 microdesc consensuses only have "a" lines in later consensus methods */ if (format == NS_V3_CONSENSUS_MICRODESC && consensus_method < MIN_METHOD_FOR_A_LINES_IN_MICRODESC_CONSENSUS) goto done; /* Possible "a" line. At most one for now. */ if (!tor_addr_is_null(&rs->ipv6_addr)) { smartlist_add_asprintf(chunks, "a %s\n", fmt_addrport(&rs->ipv6_addr, rs->ipv6_orport)); } if (format == NS_V3_CONSENSUS || format == NS_V3_CONSENSUS_MICRODESC) goto done; smartlist_add_asprintf(chunks, "s%s%s%s%s%s%s%s%s%s%s%s\n", /* These must stay in alphabetical order. */ rs->is_authority?" Authority":"", rs->is_bad_exit?" BadExit":"", rs->is_exit?" Exit":"", rs->is_fast?" Fast":"", rs->is_possible_guard?" Guard":"", rs->is_hs_dir?" HSDir":"", rs->is_flagged_running?" Running":"", rs->is_stable?" Stable":"", rs->is_staledesc?" StaleDesc":"", rs->is_v2_dir?" V2Dir":"", rs->is_valid?" Valid":""); /* length of "opt v \n" */ #define V_LINE_OVERHEAD 7 if (version && strlen(version) < MAX_V_LINE_LEN - V_LINE_OVERHEAD) { smartlist_add_asprintf(chunks, "v %s\n", version); } if (protocols) { smartlist_add_asprintf(chunks, "pr %s\n", protocols); } if (format != NS_V2) { const routerinfo_t* desc = router_get_by_id_digest(rs->identity_digest); uint32_t bw_kb; if (format != NS_CONTROL_PORT) { /* Blow up more or less nicely if we didn't get anything or not the * thing we expected. */ if (!desc) { char id[HEX_DIGEST_LEN+1]; char dd[HEX_DIGEST_LEN+1]; base16_encode(id, sizeof(id), rs->identity_digest, DIGEST_LEN); base16_encode(dd, sizeof(dd), rs->descriptor_digest, DIGEST_LEN); log_warn(LD_BUG, "Cannot get any descriptor for %s " "(wanted descriptor %s).", id, dd); goto err; } /* This assert could fire for the control port, because * it can request NS documents before all descriptors * have been fetched. Therefore, we only do this test when * format != NS_CONTROL_PORT. */ if (tor_memneq(desc->cache_info.signed_descriptor_digest, rs->descriptor_digest, DIGEST_LEN)) { char rl_d[HEX_DIGEST_LEN+1]; char rs_d[HEX_DIGEST_LEN+1]; char id[HEX_DIGEST_LEN+1]; base16_encode(rl_d, sizeof(rl_d), desc->cache_info.signed_descriptor_digest, DIGEST_LEN); base16_encode(rs_d, sizeof(rs_d), rs->descriptor_digest, DIGEST_LEN); base16_encode(id, sizeof(id), rs->identity_digest, DIGEST_LEN); log_err(LD_BUG, "descriptor digest in routerlist does not match " "the one in routerstatus: %s vs %s " "(router %s)\n", rl_d, rs_d, id); tor_assert(tor_memeq(desc->cache_info.signed_descriptor_digest, rs->descriptor_digest, DIGEST_LEN)); } } if (format == NS_CONTROL_PORT && rs->has_bandwidth) { bw_kb = rs->bandwidth_kb; } else { tor_assert(desc); bw_kb = router_get_advertised_bandwidth_capped(desc) / 1000; } smartlist_add_asprintf(chunks, "w Bandwidth=%d", bw_kb); if (format == NS_V3_VOTE && vrs && vrs->has_measured_bw) { smartlist_add_asprintf(chunks, " Measured=%d", vrs->measured_bw_kb); } /* Write down guardfraction information if we have it. */ if (format == NS_V3_VOTE && vrs && vrs->status.has_guardfraction) { smartlist_add_asprintf(chunks, " GuardFraction=%d", vrs->status.guardfraction_percentage); } smartlist_add_strdup(chunks, "\n"); if (desc) { summary = policy_summarize(desc->exit_policy, AF_INET); smartlist_add_asprintf(chunks, "p %s\n", summary); tor_free(summary); } if (format == NS_V3_VOTE && vrs) { if (tor_mem_is_zero((char*)vrs->ed25519_id, ED25519_PUBKEY_LEN)) { smartlist_add_strdup(chunks, "id ed25519 none\n"); } else { char ed_b64[BASE64_DIGEST256_LEN+1]; digest256_to_base64(ed_b64, (const char*)vrs->ed25519_id); smartlist_add_asprintf(chunks, "id ed25519 %s\n", ed_b64); } } } done: result = smartlist_join_strings(chunks, "", 0, NULL); err: SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); smartlist_free(chunks); return result; }