X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=apps%2Fsilcd%2Fprotocol.c;h=a7a1b707d7d1a39000626dbf555ac8f20a52cd2d;hb=d47a87b03b846e2333ef57b2c0d81f1644992964;hp=07f3233d037378628bc5f7bd25f922734ec5c9de;hpb=08091374ff1050f22c4f1d8bf89288c0f347b441;p=silc.git diff --git a/apps/silcd/protocol.c b/apps/silcd/protocol.c index 07f3233d..a7a1b707 100644 --- a/apps/silcd/protocol.c +++ b/apps/silcd/protocol.c @@ -56,6 +56,13 @@ silc_verify_public_key_internal(SilcServer server, SilcSocketConnection sock, return TRUE; } + /* XXX For now, accept server keys without verification too. We are + currently always doing mutual authentication so the proof of posession + of the private key is verified, and if server is authenticated in + conn auth protocol with public key we MUST have the key already. */ + return TRUE; + /* Rest is unreachable code! */ + memset(filename, 0, sizeof(filename)); memset(file, 0, sizeof(file)); snprintf(file, sizeof(file) - 1, "serverkey_%s_%d.pub", sock->hostname, @@ -124,12 +131,11 @@ silc_verify_public_key_internal(SilcServer server, SilcSocketConnection sock, /* Save the key for future checking */ unlink(filename); - silc_pkcs_save_public_key_data(filename, pk, pk_len, - SILC_PKCS_FILE_PEM); + silc_pkcs_save_public_key_data(filename, pk, pk_len, SILC_PKCS_FILE_PEM); return TRUE; } - if (memcmp(encpk, pk, encpk_len)) { + if (memcmp(pk, encpk, encpk_len)) { SILC_LOG_WARNING(("%s (%s) port %d server public key does not match " "with local copy", sock->hostname, sock->ip, sock->port)); @@ -199,7 +205,8 @@ static void silc_server_protocol_ke_send_packet(SilcSKE ske, /* Sets the negotiated key material into use for particular connection. */ -int silc_server_protocol_ke_set_keys(SilcSKE ske, +int silc_server_protocol_ke_set_keys(SilcServer server, + SilcSKE ske, SilcSocketConnection sock, SilcSKEKeyMaterial *keymat, SilcCipher cipher, @@ -227,6 +234,23 @@ int silc_server_protocol_ke_set_keys(SilcSKE ske, return FALSE; } + if (!silc_hmac_alloc((char *)silc_hmac_get_name(hmac), NULL, + &idata->hmac_send)) { + silc_cipher_free(idata->send_key); + silc_cipher_free(idata->receive_key); + silc_free(conn_data); + return FALSE; + } + + if (!silc_hmac_alloc((char *)silc_hmac_get_name(hmac), NULL, + &idata->hmac_receive)) { + silc_cipher_free(idata->send_key); + silc_cipher_free(idata->receive_key); + silc_hmac_free(idata->hmac_send); + silc_free(conn_data); + return FALSE; + } + if (is_responder == TRUE) { silc_cipher_set_key(idata->send_key, keymat->receive_enc_key, keymat->enc_key_len); @@ -234,6 +258,10 @@ int silc_server_protocol_ke_set_keys(SilcSKE ske, silc_cipher_set_key(idata->receive_key, keymat->send_enc_key, keymat->enc_key_len); silc_cipher_set_iv(idata->receive_key, keymat->send_iv); + silc_hmac_set_key(idata->hmac_send, keymat->receive_hmac_key, + keymat->hmac_key_len); + silc_hmac_set_key(idata->hmac_receive, keymat->send_hmac_key, + keymat->hmac_key_len); } else { silc_cipher_set_key(idata->send_key, keymat->send_enc_key, keymat->enc_key_len); @@ -241,6 +269,10 @@ int silc_server_protocol_ke_set_keys(SilcSKE ske, silc_cipher_set_key(idata->receive_key, keymat->receive_enc_key, keymat->enc_key_len); silc_cipher_set_iv(idata->receive_key, keymat->receive_iv); + silc_hmac_set_key(idata->hmac_send, keymat->send_hmac_key, + keymat->hmac_key_len); + silc_hmac_set_key(idata->hmac_receive, keymat->receive_hmac_key, + keymat->hmac_key_len); } idata->rekey = silc_calloc(1, sizeof(*idata->rekey)); @@ -255,35 +287,29 @@ int silc_server_protocol_ke_set_keys(SilcSKE ske, idata->rekey->pfs = TRUE; idata->rekey->ske_group = silc_ske_group_get_number(group); - /* Save the remote host's public key */ - silc_pkcs_public_key_decode(ske->ke1_payload->pk_data, - ske->ke1_payload->pk_len, &idata->public_key); - /* Save the hash */ if (!silc_hash_alloc(hash->hash->name, &idata->hash)) { silc_cipher_free(idata->send_key); silc_cipher_free(idata->receive_key); + silc_hmac_free(idata->hmac_send); + silc_hmac_free(idata->hmac_receive); silc_free(conn_data); return FALSE; } - /* Save HMAC key to be used in the communication. */ - if (!silc_hmac_alloc(hmac->hmac->name, NULL, &idata->hmac_send)) { - silc_cipher_free(idata->send_key); - silc_cipher_free(idata->receive_key); - silc_hash_free(idata->hash); - silc_free(conn_data); - return FALSE; - } - silc_hmac_set_key(idata->hmac_send, keymat->hmac_key, keymat->hmac_key_len); - idata->hmac_receive = idata->hmac_send; + /* Save the remote host's public key */ + silc_pkcs_public_key_decode(ske->ke1_payload->pk_data, + ske->ke1_payload->pk_len, &idata->public_key); + if (ske->prop->flags & SILC_SKE_SP_FLAG_MUTUAL) + silc_hash_make(server->sha1hash, ske->ke1_payload->pk_data, + ske->ke1_payload->pk_len, idata->fingerprint); sock->user_data = (void *)conn_data; SILC_LOG_INFO(("%s (%s) security properties: %s %s %s", sock->hostname, sock->ip, idata->send_key->cipher->name, - idata->hmac_send->hmac->name, + (char *)silc_hmac_get_name(idata->hmac_send), idata->hash->hash->name)); return TRUE; @@ -341,8 +367,18 @@ SilcSKEStatus silc_ske_check_version(SilcSKE ske, unsigned char *version, if (maj != maj2) status = SILC_SKE_STATUS_BAD_VERSION; +#if 0 if (min > min2) status = SILC_SKE_STATUS_BAD_VERSION; +#endif + + /* XXX < 0.6 is not allowed */ + if (maj == 0 && min < 5) + status = SILC_SKE_STATUS_BAD_VERSION; + + /* XXX backward support for 0.6.1 */ + if (maj == 0 && min == 6 && build < 2) + ske->backward_version = 1; return status; } @@ -435,12 +471,12 @@ SILC_TASK_CALLBACK(silc_server_protocol_key_exchange) properties packet from initiator. */ status = silc_ske_responder_start(ske, ctx->rng, ctx->sock, silc_version_string, - ctx->packet->buffer, FALSE); + ctx->packet->buffer, TRUE); } else { SilcSKEStartPayload *start_payload; /* Assemble security properties. */ - silc_ske_assemble_security_properties(ske, SILC_SKE_SP_FLAG_NONE, + silc_ske_assemble_security_properties(ske, SILC_SKE_SP_FLAG_MUTUAL, silc_version_string, &start_payload); @@ -617,6 +653,11 @@ SILC_TASK_CALLBACK(silc_server_protocol_key_exchange) if (ctx->timeout_task) silc_schedule_task_del(server->schedule, ctx->timeout_task); + /* Assure that after calling final callback there cannot be pending + executions for this protocol anymore. This just unregisters any + timeout callbacks for this protocol. */ + silc_protocol_cancel(protocol, server->schedule); + /* Call the final callback */ if (protocol->final_callback) silc_protocol_execute_final(protocol, server->schedule); @@ -639,6 +680,11 @@ SILC_TASK_CALLBACK(silc_server_protocol_key_exchange) if (ctx->timeout_task) silc_schedule_task_del(server->schedule, ctx->timeout_task); + /* Assure that after calling final callback there cannot be pending + executions for this protocol anymore. This just unregisters any + timeout callbacks for this protocol. */ + silc_protocol_cancel(protocol, server->schedule); + /* On error the final callback is always called. */ if (protocol->final_callback) silc_protocol_execute_final(protocol, server->schedule); @@ -657,6 +703,11 @@ SILC_TASK_CALLBACK(silc_server_protocol_key_exchange) if (ctx->timeout_task) silc_schedule_task_del(server->schedule, ctx->timeout_task); + /* Assure that after calling final callback there cannot be pending + executions for this protocol anymore. This just unregisters any + timeout callbacks for this protocol. */ + silc_protocol_cancel(protocol, server->schedule); + /* On error the final callback is always called. */ if (protocol->final_callback) silc_protocol_execute_final(protocol, server->schedule); @@ -674,13 +725,13 @@ SILC_TASK_CALLBACK(silc_server_protocol_key_exchange) */ static int -silc_server_password_authentication(SilcServer server, char *auth1, - char *auth2) +silc_server_password_authentication(SilcServer server, char *remote_auth, + char *local_auth) { - if (!auth1 || !auth2) + if (!remote_auth || !local_auth) return FALSE; - if (!memcmp(auth1, auth2, strlen(auth1))) + if (!memcmp(remote_auth, local_auth, strlen(local_auth))) return TRUE; return FALSE; @@ -855,7 +906,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_connection_auth) /* Remote end is client */ if (conn_type == SILC_SOCKET_TYPE_CLIENT) { - SilcServerConfigSectionClientConnection *client = ctx->cconfig; + SilcServerConfigSectionClient *client = ctx->cconfig; if (client) { switch(client->auth_meth) { @@ -904,8 +955,8 @@ SILC_TASK_CALLBACK(silc_server_protocol_connection_auth) return; } } else { - SILC_LOG_DEBUG(("No configuration for remote connection")); - SILC_LOG_ERROR(("Remote connection not configured")); + SILC_LOG_DEBUG(("No configuration for remote client connection")); + SILC_LOG_ERROR(("Remote client connection not configured")); SILC_LOG_ERROR(("Authentication failed")); silc_free(auth_data); protocol->state = SILC_PROTOCOL_STATE_ERROR; @@ -917,7 +968,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_connection_auth) /* Remote end is server */ if (conn_type == SILC_SOCKET_TYPE_SERVER) { - SilcServerConfigSectionServerConnection *serv = ctx->sconfig; + SilcServerConfigSectionServer *serv = ctx->sconfig; if (serv) { switch(serv->auth_meth) { @@ -966,8 +1017,8 @@ SILC_TASK_CALLBACK(silc_server_protocol_connection_auth) return; } } else { - SILC_LOG_DEBUG(("No configuration for remote connection")); - SILC_LOG_ERROR(("Remote connection not configured")); + SILC_LOG_DEBUG(("No configuration for remote server connection")); + SILC_LOG_ERROR(("Remote server connection not configured")); SILC_LOG_ERROR(("Authentication failed")); protocol->state = SILC_PROTOCOL_STATE_ERROR; silc_protocol_execute(protocol, server->schedule, @@ -979,7 +1030,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_connection_auth) /* Remote end is router */ if (conn_type == SILC_SOCKET_TYPE_ROUTER) { - SilcServerConfigSectionServerConnection *serv = ctx->rconfig; + SilcServerConfigSectionRouter *serv = ctx->rconfig; if (serv) { switch(serv->auth_meth) { @@ -1028,8 +1079,8 @@ SILC_TASK_CALLBACK(silc_server_protocol_connection_auth) return; } } else { - SILC_LOG_DEBUG(("No configuration for remote connection")); - SILC_LOG_ERROR(("Remote connection not configured")); + SILC_LOG_DEBUG(("No configuration for remote router connection")); + SILC_LOG_ERROR(("Remote router connection not configured")); SILC_LOG_ERROR(("Authentication failed")); silc_free(auth_data); protocol->state = SILC_PROTOCOL_STATE_ERROR; @@ -1135,6 +1186,11 @@ SILC_TASK_CALLBACK(silc_server_protocol_connection_auth) if (ctx->timeout_task) silc_schedule_task_del(server->schedule, ctx->timeout_task); + /* Assure that after calling final callback there cannot be pending + executions for this protocol anymore. This just unregisters any + timeout callbacks for this protocol. */ + silc_protocol_cancel(protocol, server->schedule); + /* Protocol has ended, call the final callback */ if (protocol->final_callback) silc_protocol_execute_final(protocol, server->schedule); @@ -1161,6 +1217,11 @@ SILC_TASK_CALLBACK(silc_server_protocol_connection_auth) if (ctx->timeout_task) silc_schedule_task_del(server->schedule, ctx->timeout_task); + /* Assure that after calling final callback there cannot be pending + executions for this protocol anymore. This just unregisters any + timeout callbacks for this protocol. */ + silc_protocol_cancel(protocol, server->schedule); + /* On error the final callback is always called. */ if (protocol->final_callback) silc_protocol_execute_final(protocol, server->schedule); @@ -1180,6 +1241,11 @@ SILC_TASK_CALLBACK(silc_server_protocol_connection_auth) if (ctx->timeout_task) silc_schedule_task_del(server->schedule, ctx->timeout_task); + /* Assure that after calling final callback there cannot be pending + executions for this protocol anymore. This just unregisters any + timeout callbacks for this protocol. */ + silc_protocol_cancel(protocol, server->schedule); + /* On error the final callback is always called. */ if (protocol->final_callback) silc_protocol_execute_final(protocol, server->schedule); @@ -1210,32 +1276,31 @@ silc_server_protocol_rekey_validate(SilcServer server, silc_cipher_set_key(idata->send_key, keymat->receive_enc_key, keymat->enc_key_len); silc_cipher_set_iv(idata->send_key, keymat->receive_iv); + silc_hmac_set_key(idata->hmac_send, keymat->receive_hmac_key, + keymat->hmac_key_len); } else { silc_cipher_set_key(idata->receive_key, keymat->send_enc_key, keymat->enc_key_len); silc_cipher_set_iv(idata->receive_key, keymat->send_iv); + silc_hmac_set_key(idata->hmac_receive, keymat->send_hmac_key, + keymat->hmac_key_len); } } else { if (send) { silc_cipher_set_key(idata->send_key, keymat->send_enc_key, keymat->enc_key_len); silc_cipher_set_iv(idata->send_key, keymat->send_iv); + silc_hmac_set_key(idata->hmac_send, keymat->send_hmac_key, + keymat->hmac_key_len); } else { silc_cipher_set_key(idata->receive_key, keymat->receive_enc_key, keymat->enc_key_len); silc_cipher_set_iv(idata->receive_key, keymat->receive_iv); + silc_hmac_set_key(idata->hmac_receive, keymat->receive_hmac_key, + keymat->hmac_key_len); } } - if (send) { - silc_hmac_alloc(idata->hmac_send->hmac->name, NULL, &idata->hmac_send); - silc_hmac_set_key(idata->hmac_send, keymat->hmac_key, - keymat->hmac_key_len); - } else { - silc_hmac_free(idata->hmac_receive); - idata->hmac_receive = idata->hmac_send; - } - /* Save the current sending encryption key */ if (!send) { memset(idata->rekey->send_enc_key, 0, idata->rekey->enc_key_len); @@ -1376,7 +1441,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey) ctx->ske = silc_ske_alloc(); ctx->ske->rng = server->rng; ctx->ske->prop = silc_calloc(1, sizeof(*ctx->ske->prop)); - silc_ske_get_group_by_number(idata->rekey->ske_group, + silc_ske_group_get_by_number(idata->rekey->ske_group, &ctx->ske->prop->group); silc_ske_set_callbacks(ctx->ske, @@ -1432,7 +1497,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey) ctx->ske = silc_ske_alloc(); ctx->ske->rng = server->rng; ctx->ske->prop = silc_calloc(1, sizeof(*ctx->ske->prop)); - silc_ske_get_group_by_number(idata->rekey->ske_group, + silc_ske_group_get_by_number(idata->rekey->ske_group, &ctx->ske->prop->group); silc_ske_set_callbacks(ctx->ske, @@ -1550,6 +1615,11 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey) encrypted with the new key so set the decryption key to the new key */ silc_server_protocol_rekey_generate(server, ctx, FALSE); + /* Assure that after calling final callback there cannot be pending + executions for this protocol anymore. This just unregisters any + timeout callbacks for this protocol. */ + silc_protocol_cancel(protocol, server->schedule); + /* Protocol has ended, call the final callback */ if (protocol->final_callback) silc_protocol_execute_final(protocol, server->schedule); @@ -1567,6 +1637,11 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey) silc_ske_abort(ctx->ske, ctx->ske->status); } + /* Assure that after calling final callback there cannot be pending + executions for this protocol anymore. This just unregisters any + timeout callbacks for this protocol. */ + silc_protocol_cancel(protocol, server->schedule); + /* On error the final callback is always called. */ if (protocol->final_callback) silc_protocol_execute_final(protocol, server->schedule); @@ -1579,6 +1654,11 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey) * We have received failure from remote */ + /* Assure that after calling final callback there cannot be pending + executions for this protocol anymore. This just unregisters any + timeout callbacks for this protocol. */ + silc_protocol_cancel(protocol, server->schedule); + /* On error the final callback is always called. */ if (protocol->final_callback) silc_protocol_execute_final(protocol, server->schedule); @@ -1602,6 +1682,8 @@ void silc_server_protocols_register(void) silc_server_protocol_key_exchange); silc_protocol_register(SILC_PROTOCOL_SERVER_REKEY, silc_server_protocol_rekey); + silc_protocol_register(SILC_PROTOCOL_SERVER_BACKUP, + silc_server_protocol_backup); } /* Unregisters protocols */ @@ -1614,4 +1696,6 @@ void silc_server_protocols_unregister(void) silc_server_protocol_key_exchange); silc_protocol_unregister(SILC_PROTOCOL_SERVER_REKEY, silc_server_protocol_rekey); + silc_protocol_unregister(SILC_PROTOCOL_SERVER_BACKUP, + silc_server_protocol_backup); }