bool id_h(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(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "ID", c->name, c->hostname); return false; } /* Check if this is a control connection */ if(name[0] == '^' && !strcmp(name + 1, controlcookie)) { c->status.control = true; c->allow_request = CONTROL; c->last_ping_time = now.tv_sec + 3600; free(c->name); c->name = xstrdup("<control>"); return send_request(c, "%d %d %d", ACK, TINC_CTL_VERSION_CURRENT, getpid()); } if(name[0] == '?') { if(!invitation_key) { logger(DEBUG_ALWAYS, LOG_ERR, "Got invitation from %s but we don't have an invitation key", c->hostname); return false; } c->ecdsa = ecdsa_set_base64_public_key(name + 1); if(!c->ecdsa) { logger(DEBUG_ALWAYS, LOG_ERR, "Got bad invitation from %s", c->hostname); return false; } c->status.invitation = true; char *mykey = ecdsa_get_base64_public_key(invitation_key); if(!mykey) return false; if(!send_request(c, "%d %s", ACK, mykey)) return false; free(mykey); c->protocol_minor = 2; return sptps_start(&c->sptps, c, false, false, invitation_key, c->ecdsa, "tinc invitation", 15, send_meta_sptps, receive_invitation_sptps); } /* Check if identity is a valid name */ if(!check_id(name)) { logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "ID", c->name, c->hostname, "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(DEBUG_ALWAYS, LOG_ERR, "Peer %s is %s instead of %s", c->hostname, name, c->name); return false; } } else { if(c->name) free(c->name); c->name = xstrdup(name); } /* Check if version matches */ if(c->protocol_major != myself->connection->protocol_major) { logger(DEBUG_ALWAYS, LOG_ERR, "Peer %s (%s) uses incompatible version %d.%d", c->name, c->hostname, c->protocol_major, c->protocol_minor); return false; } if(bypass_security) { if(!c->config_tree) init_configuration(&c->config_tree); c->allow_request = ACK; return send_ack(c); } if(!experimental) c->protocol_minor = 0; if(!c->config_tree) { init_configuration(&c->config_tree); if(!read_host_config(c->config_tree, c->name)) { logger(DEBUG_ALWAYS, LOG_ERR, "Peer %s had unknown identity (%s)", c->hostname, c->name); return false; } if(experimental) read_ecdsa_public_key(c); /* Ignore failures if no key known yet */ } if(c->protocol_minor && !ecdsa_active(c->ecdsa)) c->protocol_minor = 1; /* Forbid version rollback for nodes whose Ed25519 key we know */ if(ecdsa_active(c->ecdsa) && c->protocol_minor < 2) { logger(DEBUG_ALWAYS, LOG_ERR, "Peer %s (%s) tries to roll back protocol version to %d.%d", c->name, c->hostname, c->protocol_major, c->protocol_minor); return false; } c->allow_request = METAKEY; if(c->protocol_minor >= 2) { c->allow_request = ACK; char label[25 + strlen(myself->name) + strlen(c->name)]; if(c->outgoing) snprintf(label, sizeof label, "tinc TCP key expansion %s %s", myself->name, c->name); else snprintf(label, sizeof label, "tinc TCP key expansion %s %s", c->name, myself->name); return sptps_start(&c->sptps, c, c->outgoing, false, myself->connection->ecdsa, c->ecdsa, label, sizeof label, send_meta_sptps, receive_meta_sptps); } else { return send_metakey(c); } }
bool id_h(connection_t *c) { char name[MAX_STRING_SIZE]; if(sscanf(c->buffer, "%*d " MAX_STRING " %d", name, &c->protocol_version) != 2) { logger(LOG_ERR, "Got bad %s from %s (%s)", "ID", c->name, c->hostname); return false; } /* Check if identity is a valid name */ if(!check_id(name) || !strcmp(name, myself->name)) { logger(LOG_ERR, "Got bad %s from %s (%s): %s", "ID", c->name, c->hostname, "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(LOG_ERR, "Peer %s is %s instead of %s", c->hostname, name, c->name); return false; } } else { if(c->name) { free(c->name); } c->name = xstrdup(name); } /* Check if version matches */ if(c->protocol_version != myself->connection->protocol_version) { logger(LOG_ERR, "Peer %s (%s) uses incompatible version %d", c->name, c->hostname, c->protocol_version); return false; } if(bypass_security) { if(!c->config_tree) { init_configuration(&c->config_tree); } c->allow_request = ACK; if(!c->outgoing) { send_id(c); } return send_ack(c); } if(!c->config_tree) { init_configuration(&c->config_tree); if(!read_connection_config(c)) { logger(LOG_ERR, "Peer %s had unknown identity (%s)", c->hostname, c->name); return false; } } if(!read_rsa_public_key(c)) { return false; } c->allow_request = METAKEY; if(!c->outgoing) { send_id(c); } return send_metakey(c); }