-int chal_reply_h(connection_t *c)
-{
- char hishash[MAX_STRING_SIZE];
- char myhash[EVP_MAX_MD_SIZE];
- EVP_MD_CTX ctx;
-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) != c->outdigest->md_size*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, c->outdigest->md_size);
-
- /* Calculate the hash from the challenge we sent */
-
- EVP_DigestInit(&ctx, c->outdigest);
- EVP_DigestUpdate(&ctx, c->hischallenge, RSA_size(c->rsa_key));
- EVP_DigestFinal(&ctx, myhash, NULL);
-
- /* Verify the incoming hash with the calculated hash */
-
- if(memcmp(hishash, myhash, c->outdigest->md_size))
- {
- 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 id_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
+ char name[MAX_STRING_SIZE];
+
+ if(sscanf(request, "%*d " MAX_STRING " %d.%d", name, &c->protocol_major, &c->protocol_minor) < 2) {
+ logger(mesh, MESHLINK_ERROR, "Got bad %s from %s", "ID", c->name);
+ return false;
+ }
+
+ /* Check if this is an invitation */
+
+ if(name[0] == '?') {
+ if(!mesh->invitation_key) {
+ logger(mesh, MESHLINK_ERROR, "Got invitation from %s but we don't have an invitation key", c->name);
+ return false;
+ }
+
+ c->ecdsa = ecdsa_set_base64_public_key(name + 1);
+
+ if(!c->ecdsa) {
+ logger(mesh, MESHLINK_ERROR, "Got bad invitation from %s", c->name);
+ return false;
+ }
+
+ c->status.invitation = true;
+ char *mykey = ecdsa_get_base64_public_key(mesh->invitation_key);
+
+ if(!mykey) {
+ return false;
+ }
+
+ if(!send_request(mesh, c, "%d %s", ACK, mykey)) {
+ return false;
+ }
+
+ free(mykey);
+
+ c->protocol_minor = PROT_MINOR;
+ c->allow_request = LAST;
+
+ return sptps_start(&c->sptps, c, false, false, mesh->invitation_key, c->ecdsa, meshlink_invitation_label, sizeof(meshlink_invitation_label), send_meta_sptps, receive_invitation_sptps);
+ }
+
+ /* Check if identity is a valid name */
+
+ if(!check_id(name)) {
+ logger(mesh, MESHLINK_ERROR, "Got bad %s from %s: %s", "ID", c->name, "invalid name");
+ return false;
+ }
+
+ /* If this is an outgoing connection, make sure we are connected to the right host */
+
+ if(c->outgoing) {
+ if(strcmp(c->name, name)) {
+ logger(mesh, MESHLINK_ERROR, "Peer is %s instead of %s", name, c->name);
+ return false;
+ }
+ } else {
+ if(c->name) {
+ free(c->name);
+ }
+
+ c->name = xstrdup(name);
+ }
+
+ /* Check if version matches */
+
+ if(c->protocol_major != mesh->self->connection->protocol_major) {
+ logger(mesh, MESHLINK_ERROR, "Peer %s uses incompatible version %d.%d",
+ c->name, c->protocol_major, c->protocol_minor);
+ return false;
+ }
+
+ if(!c->config_tree) {
+ init_configuration(&c->config_tree);
+
+ if(!read_host_config(mesh, c->config_tree, c->name)) {
+ logger(mesh, MESHLINK_ERROR, "Peer %s has unknown identity", c->name);
+ return false;
+ }
+ }
+
+ bool blacklisted = false;
+ get_config_bool(lookup_config(c->config_tree, "blacklisted"), &blacklisted);
+
+ if(blacklisted) {
+ logger(mesh, MESHLINK_EPEER, "Peer %s is blacklisted", c->name);
+ return false;
+ }
+
+ read_ecdsa_public_key(mesh, c);
+
+ if(!ecdsa_active(c->ecdsa)) {
+ logger(mesh, MESHLINK_ERROR, "No key known for peer %s", c->name);
+
+ node_t *n = lookup_node(mesh, c->name);
+
+ if(n && !n->status.waitingforkey) {
+ logger(mesh, MESHLINK_INFO, "Requesting key from peer %s", c->name);
+ send_req_key(mesh, n);
+ }
+
+ return false;
+ }
+
+ c->allow_request = ACK;
+ char label[sizeof(meshlink_tcp_label) + strlen(mesh->self->name) + strlen(c->name) + 2];
+
+ if(c->outgoing) {
+ snprintf(label, sizeof(label), "%s %s %s", meshlink_tcp_label, mesh->self->name, c->name);
+ } else {
+ snprintf(label, sizeof(label), "%s %s %s", meshlink_tcp_label, c->name, mesh->self->name);
+ }
+
+ return sptps_start(&c->sptps, c, c->outgoing, false, mesh->self->connection->ecdsa, c->ecdsa, label, sizeof(label) - 1, send_meta_sptps, receive_meta_sptps);