-int chal_reply_h(connection_t *c)
-{
- char hishash[MAX_STRING_SIZE];
- char myhash[SHA_DIGEST_LENGTH];
-cp
- if(sscanf(c->buffer, "%*d "MAX_STRING, hishash) != 1)
- {
- syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "CHAL_REPLY", c->name, c->hostname);
- return -1;
- }
-
- /* Check if the length of the hash is all right */
-
- if(strlen(hishash) != SHA_DIGEST_LENGTH*2)
- {
- syslog(LOG_ERR, _("Possible intruder %s (%s): %s"), c->name, c->hostname, _("wrong challenge reply length"));
- return -1;
- }
-
- /* Convert the hash to binary format */
-
- hex2bin(hishash, hishash, SHA_DIGEST_LENGTH);
-
- /* Calculate the hash from the challenge we sent */
-
- SHA1(c->hischallenge, RSA_size(c->rsa_key), myhash);
-
- /* Verify the incoming hash with the calculated hash */
-
- if(memcmp(hishash, myhash, SHA_DIGEST_LENGTH))
- {
- syslog(LOG_ERR, _("Possible intruder %s (%s): %s"), c->name, c->hostname, _("wrong challenge reply"));
- if(debug_lvl >= DEBUG_SCARY_THINGS)
- {
- bin2hex(myhash, hishash, SHA_DIGEST_LENGTH);
- hishash[SHA_DIGEST_LENGTH*2] = '\0';
- syslog(LOG_DEBUG, _("Expected challenge reply: %s"), hishash);
- }
- return -1;
- }
-
- /* Identity has now been positively verified.
- Send an acknowledgement with the rest of the information needed.
- */
-
- c->allow_request = ACK;
-cp
- return send_ack(c);
+bool challenge_h(connection_t *c, const char *request) {
+ if(!myself->connection->rsa) {
+ return false;
+ }
+
+ char buffer[MAX_STRING_SIZE];
+ const size_t len = rsa_size(myself->connection->rsa);
+
+ if(sscanf(request, "%*d " MAX_STRING, buffer) != 1) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "CHALLENGE", c->name, c->hostname);
+ return false;
+ }
+
+ /* Check if the length of the challenge is all right */
+
+ if(strlen(buffer) != (size_t)len * 2) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Possible intruder %s (%s): %s", c->name, c->hostname, "wrong challenge length");
+ return false;
+ }
+
+ c->mychallenge = xrealloc(c->mychallenge, len);
+
+ /* Convert the challenge from hexadecimal back to binary */
+
+ hex2bin(buffer, c->mychallenge, len);
+
+ /* The rest is done by send_chal_reply() */
+
+ c->allow_request = CHAL_REPLY;
+
+ if(c->outgoing) {
+ return send_chal_reply(c);
+ } else {
+ return true;
+ }
+}
+
+bool send_chal_reply(connection_t *c) {
+ const size_t len = rsa_size(myself->connection->rsa);
+ size_t digestlen = digest_length(&c->indigest);
+ char digest[digestlen * 2 + 1];
+
+ /* Calculate the hash from the challenge we received */
+
+ if(!digest_create(&c->indigest, c->mychallenge, len, digest)) {
+ return false;
+ }
+
+ free(c->mychallenge);
+ c->mychallenge = NULL;
+
+ /* Convert the hash to a hexadecimal formatted string */
+
+ bin2hex(digest, digest, digestlen);
+
+ /* Send the reply */
+
+ return send_request(c, "%d %s", CHAL_REPLY, digest);
+}
+
+bool chal_reply_h(connection_t *c, const char *request) {
+ char hishash[MAX_STRING_SIZE];
+
+ if(sscanf(request, "%*d " MAX_STRING, hishash) != 1) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "CHAL_REPLY", c->name,
+ c->hostname);
+ return false;
+ }
+
+ /* Convert the hash to binary format */
+
+ size_t inlen = hex2bin(hishash, hishash, sizeof(hishash));
+
+ /* Check if the length of the hash is all right */
+
+ if(inlen != digest_length(&c->outdigest)) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Possible intruder %s (%s): %s", c->name, c->hostname, "wrong challenge reply length");
+ return false;
+ }
+
+
+ /* Verify the hash */
+
+ if(!digest_verify(&c->outdigest, c->hischallenge, rsa_size(c->rsa), hishash)) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Possible intruder %s (%s): %s", c->name, c->hostname, "wrong challenge reply");
+ return false;
+ }
+
+ /* Identity has now been positively verified.
+ Send an acknowledgement with the rest of the information needed.
+ */
+
+ free(c->hischallenge);
+ c->hischallenge = NULL;
+ c->allow_request = ACK;
+
+ if(!c->outgoing) {
+ send_chal_reply(c);
+ }
+
+ return send_ack(c);
+}
+
+static bool send_upgrade(connection_t *c) {
+ /* Special case when protocol_minor is 1: the other end is Ed25519 capable,
+ * but doesn't know our key yet. So send it now. */
+
+ char *pubkey = ecdsa_get_base64_public_key(myself->connection->ecdsa);
+
+ if(!pubkey) {
+ return false;
+ }
+
+ bool result = send_request(c, "%d %s", ACK, pubkey);
+ free(pubkey);
+ return result;
+}
+#else
+bool send_metakey(connection_t *c) {
+ (void)c;
+ return false;
+}
+
+bool metakey_h(connection_t *c, const char *request) {
+ (void)c;
+ (void)request;
+ return false;
+}
+
+bool send_challenge(connection_t *c) {
+ (void)c;
+ return false;
+}
+
+bool challenge_h(connection_t *c, const char *request) {
+ (void)c;
+ (void)request;
+ return false;
+}
+
+bool send_chal_reply(connection_t *c) {
+ (void)c;
+ return false;
+}
+
+bool chal_reply_h(connection_t *c, const char *request) {
+ (void)c;
+ (void)request;
+ return false;
+}
+
+static bool send_upgrade(connection_t *c) {
+ (void)c;
+ return false;
+}
+#endif
+
+bool send_ack(connection_t *c) {
+ if(c->protocol_minor == 1) {
+ return send_upgrade(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 = (int)((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_TCPONLY)) {
+ 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;
+ }
+
+ if(!get_config_int(lookup_config(c->config_tree, "Weight"), &c->estimated_weight)) {
+ get_config_int(lookup_config(&config_tree, "Weight"), &c->estimated_weight);
+ }
+
+ return send_request(c, "%d %s %d %x", ACK, myport, c->estimated_weight, (c->options & 0xffffff) | (experimental ? (PROT_MINOR << 24) : 0));