+bool chal_reply_h(connection_t *c) {
+ char hishash[MAX_STRING_SIZE];
+ char myhash[EVP_MAX_MD_SIZE];
+ EVP_MD_CTX *ctx;
+
+ if(sscanf(c->buffer, "%*d " MAX_STRING, hishash) != 1) {
+ logger(LOG_ERR, "Got bad %s from %s (%s)", "CHAL_REPLY", c->name,
+ c->hostname);
+ return false;
+ }
+
+ /* Check if the length of the hash is all right */
+
+ if(strlen(hishash) != EVP_MD_size(c->outdigest) * 2) {
+ logger(LOG_ERR, "Possible intruder %s (%s): %s", c->name,
+ c->hostname, "wrong challenge reply length");
+ return false;
+ }
+
+ /* Convert the hash to binary format */
+
+ if(!hex2bin(hishash, hishash, EVP_MD_size(c->outdigest))) {
+ logger(LOG_ERR, "Got bad %s from %s(%s): %s", "CHAL_REPLY", c->name, c->hostname, "invalid hash");
+ return false;
+ }
+
+ /* Calculate the hash from the challenge we sent */
+
+ ctx = EVP_MD_CTX_create();
+ if(!ctx)
+ abort();
+
+ if(!EVP_DigestInit(ctx, c->outdigest)
+ || !EVP_DigestUpdate(ctx, c->hischallenge, RSA_size(c->rsa_key))
+ || !EVP_DigestFinal(ctx, (unsigned char *)myhash, NULL)) {
+ EVP_MD_CTX_destroy(ctx);
+ logger(LOG_ERR, "Error during calculation of response from %s (%s): %s",
+ c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL));
+ return false;
+ }
+
+ EVP_MD_CTX_destroy(ctx);
+
+ /* Verify the incoming hash with the calculated hash */
+
+ if(memcmp(hishash, myhash, EVP_MD_size(c->outdigest))) {
+ logger(LOG_ERR, "Possible intruder %s (%s): %s", c->name,
+ c->hostname, "wrong challenge reply");
+
+ ifdebug(SCARY_THINGS) {
+ bin2hex(myhash, hishash, SHA_DIGEST_LENGTH);
+ hishash[SHA_DIGEST_LENGTH * 2] = '\0';
+ logger(LOG_DEBUG, "Expected challenge reply: %s", hishash);
+ }
+
+ return false;
+ }
+
+ /* Identity has now been positively verified.
+ Send an acknowledgement with the rest of the information needed.
+ */
+
+ c->allow_request = ACK;
+
+ return send_ack(c);
+}
+
+bool send_ack(connection_t *c) {
+ /* ACK message contains rest of the information the other end needs
+ to create node_t and edge_t structures. */
+
+ struct timeval now;
+ bool choice;
+
+ /* Estimate weight */
+
+ gettimeofday(&now, NULL);
+ c->estimated_weight = (now.tv_sec - c->start.tv_sec) * 1000 + (now.tv_usec - c->start.tv_usec) / 1000;
+
+ /* Check some options */
+
+ if((get_config_bool(lookup_config(c->config_tree, "IndirectData"), &choice) && choice) || myself->options & OPTION_INDIRECT)
+ c->options |= OPTION_INDIRECT;
+
+ if((get_config_bool(lookup_config(c->config_tree, "TCPOnly"), &choice) && choice) || myself->options & OPTION_TCPONLY)
+ c->options |= OPTION_TCPONLY | OPTION_INDIRECT;
+
+ if(myself->options & OPTION_PMTU_DISCOVERY)
+ c->options |= OPTION_PMTU_DISCOVERY;
+
+ choice = myself->options & OPTION_CLAMP_MSS;
+ get_config_bool(lookup_config(c->config_tree, "ClampMSS"), &choice);
+ if(choice)
+ c->options |= OPTION_CLAMP_MSS;
+
+ get_config_int(lookup_config(c->config_tree, "Weight"), &c->estimated_weight);
+
+ return send_request(c, "%d %s %d %x", ACK, myport, c->estimated_weight, c->options);