X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=apps%2Fsilcd%2Fprotocol.c;h=794a20880279462c6b473c8896443a1c971969e2;hb=386c883d8774999c6e74d7c6c37e52e4163a4cb1;hp=8bf9e5b96e9dcee1d401cc6283a933e747dc00cc;hpb=0d83f43ff41af4950a7cda27a59fce6f8973311e;p=silc.git diff --git a/apps/silcd/protocol.c b/apps/silcd/protocol.c index 8bf9e5b9..794a2088 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,45 +269,46 @@ 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)); - idata->rekey->send_enc_key = - silc_calloc(keymat->enc_key_len / 8, - sizeof(*idata->rekey->send_enc_key)); - memcpy(idata->rekey->send_enc_key, - keymat->send_enc_key, keymat->enc_key_len / 8); + idata->rekey->send_enc_key = silc_memdup(keymat->send_enc_key, + keymat->enc_key_len / 8); idata->rekey->enc_key_len = keymat->enc_key_len / 8; - if (ske->start_payload->flags & SILC_SKE_SP_FLAG_PFS) + if (ske->prop->flags & SILC_SKE_SP_FLAG_PFS) 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, + (char *)silc_hmac_get_name(idata->hmac_send), + idata->hash->hash->name)); + return TRUE; } @@ -335,8 +364,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; } @@ -359,10 +398,10 @@ static void silc_server_protocol_ke_continue(SilcSKE ske, void *context) SILC_LOG_DEBUG(("Start")); if (ske->status != SILC_SKE_STATUS_OK) { - SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol", - ske->status)); - SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol", - ske->status)); + SILC_LOG_WARNING(("Error (%s) during Key Exchange protocol", + silc_ske_map_status(ske->status))); + SILC_LOG_DEBUG(("Error (%s) during Key Exchange protocol", + silc_ske_map_status(ske->status))); protocol->state = SILC_PROTOCOL_STATE_ERROR; silc_protocol_execute(protocol, server->schedule, 0, 300000); @@ -415,9 +454,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_key_exchange) SilcSKE ske; /* Allocate Key Exchange object */ - ske = silc_ske_alloc(); - ctx->ske = ske; - ske->rng = server->rng; + ctx->ske = ske = silc_ske_alloc(server->rng, server); silc_ske_set_callbacks(ske, silc_server_protocol_ke_send_packet, NULL, silc_server_protocol_ke_verify_key, @@ -429,12 +466,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, ctx->flags); } else { SilcSKEStartPayload *start_payload; /* Assemble security properties. */ - silc_ske_assemble_security_properties(ske, SILC_SKE_SP_FLAG_NONE, + silc_ske_assemble_security_properties(ske, ctx->flags, silc_version_string, &start_payload); @@ -449,10 +486,10 @@ SILC_TASK_CALLBACK(silc_server_protocol_key_exchange) return; if (status != SILC_SKE_STATUS_OK) { - SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol", - status)); - SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol", - status)); + SILC_LOG_WARNING(("Error (%s) during Key Exchange protocol", + silc_ske_map_status(status))); + SILC_LOG_DEBUG(("Error (%s) during Key Exchange protocol", + silc_ske_map_status(status))); protocol->state = SILC_PROTOCOL_STATE_ERROR; silc_protocol_execute(protocol, server->schedule, 0, 300000); @@ -472,8 +509,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_key_exchange) */ if (ctx->responder == TRUE) { /* Sends the selected security properties to the initiator. */ - status = silc_ske_responder_phase_1(ctx->ske, - ctx->ske->start_payload); + status = silc_ske_responder_phase_1(ctx->ske); } else { /* Call Phase-1 function. This processes the Key Exchange Start paylaod reply we just got from the responder. The callback @@ -487,10 +523,10 @@ SILC_TASK_CALLBACK(silc_server_protocol_key_exchange) return; if (status != SILC_SKE_STATUS_OK) { - SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol", - status)); - SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol", - status)); + SILC_LOG_WARNING(("Error (%s) during Key Exchange protocol", + silc_ske_map_status(status))); + SILC_LOG_DEBUG(("Error (%s) during Key Exchange protocol", + silc_ske_map_status(status))); protocol->state = SILC_PROTOCOL_STATE_ERROR; silc_protocol_execute(protocol, server->schedule, 0, 300000); @@ -520,7 +556,8 @@ SILC_TASK_CALLBACK(silc_server_protocol_key_exchange) Key Exhange 1 Payload to the responder. */ status = silc_ske_initiator_phase_2(ctx->ske, server->public_key, - server->private_key); + server->private_key, + SILC_SKE_PK_TYPE_SILC); protocol->state++; } @@ -529,10 +566,10 @@ SILC_TASK_CALLBACK(silc_server_protocol_key_exchange) return; if (status != SILC_SKE_STATUS_OK) { - SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol", - status)); - SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol", - status)); + SILC_LOG_WARNING(("Error (%s) during Key Exchange protocol", + silc_ske_map_status(status))); + SILC_LOG_DEBUG(("Error (%s) during Key Exchange protocol", + silc_ske_map_status(status))); protocol->state = SILC_PROTOCOL_STATE_ERROR; silc_protocol_execute(protocol, server->schedule, 0, 300000); @@ -567,10 +604,10 @@ SILC_TASK_CALLBACK(silc_server_protocol_key_exchange) return; if (status != SILC_SKE_STATUS_OK) { - SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol", - status)); - SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol", - status)); + SILC_LOG_WARNING(("Error (%s) during Key Exchange protocol", + silc_ske_map_status(status))); + SILC_LOG_DEBUG(("Error (%s) during Key Exchange protocol", + silc_ske_map_status(status))); protocol->state = SILC_PROTOCOL_STATE_ERROR; silc_protocol_execute(protocol, server->schedule, 0, 300000); @@ -611,6 +648,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); @@ -633,6 +675,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); @@ -651,6 +698,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); @@ -668,13 +720,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; @@ -712,7 +764,8 @@ silc_server_public_key_authentication(SilcServer server, SILC_STR_END); /* Verify signature */ - if (silc_pkcs_verify(pkcs, sign, sign_len, auth->data, auth->len)) { + if (silc_pkcs_verify_with_hash(pkcs, ske->prop->hash, sign, sign_len, + auth->data, auth->len)) { silc_pkcs_free(pkcs); silc_buffer_free(auth); return TRUE; @@ -725,8 +778,7 @@ silc_server_public_key_authentication(SilcServer server, static int silc_server_get_public_key_auth(SilcServer server, - SilcPublicKey pub_key, - unsigned char *auth_data, + unsigned char **auth_data, uint32 *auth_data_len, SilcSKE ske) { @@ -734,14 +786,7 @@ silc_server_get_public_key_auth(SilcServer server, SilcPKCS pkcs; SilcBuffer auth; - if (!pub_key) - return FALSE; - - silc_pkcs_alloc(pub_key->name, &pkcs); - if (!silc_pkcs_public_key_set(pkcs, pub_key)) { - silc_pkcs_free(pkcs); - return FALSE; - } + pkcs = server->pkcs; /* Make the authentication data. Protocol says it is HASH plus KE Start Payload. */ @@ -754,17 +799,63 @@ silc_server_get_public_key_auth(SilcServer server, ske->start_payload_copy->len), SILC_STR_END); - if (silc_pkcs_sign(pkcs, auth->data, auth->len, auth_data, auth_data_len)) { - silc_pkcs_free(pkcs); + *auth_data = silc_calloc(silc_pkcs_get_key_len(pkcs), sizeof(**auth_data)); + if (silc_pkcs_sign_with_hash(pkcs, ske->prop->hash, auth->data, + auth->len, *auth_data, auth_data_len)) { silc_buffer_free(auth); return TRUE; } - silc_pkcs_free(pkcs); + silc_free(*auth_data); silc_buffer_free(auth); return FALSE; } +/* Function that actually performs the authentication to the remote. This + supports both passphrase and public key authentication. */ + +static bool +silc_server_get_authentication(SilcServerConnAuthInternalContext *ctx, + char *local_passphrase, + void *local_publickey, + unsigned char *remote_auth, + uint32 remote_auth_len) +{ + SilcServer server = (SilcServer)ctx->server; + SilcSKE ske = ctx->ske; + bool result = FALSE; + + /* If we don't have authentication data set at all we do not require + authentication at all */ + if (!local_passphrase && !local_publickey) { + SILC_LOG_DEBUG(("No authentication required")); + return TRUE; + } + + /* If both passphrase and public key is provided then we'll try both of + them and see which one of them authenticates. If only one of them is + set, then try only that. */ + + /* Try first passphrase (as it is faster to check) */ + if (local_passphrase) { + SILC_LOG_DEBUG(("Password authentication")); + result = silc_server_password_authentication(server, local_passphrase, + remote_auth); + } + + /* Try public key authenetication */ + if (!result && local_publickey) { + SILC_LOG_DEBUG(("Public key authentication")); + result = silc_server_public_key_authentication(server, + local_publickey, + remote_auth, + remote_auth_len, + ske); + } + + return result; +} + /* Performs connection authentication protocol. If responder, we authenticate the remote data received. If initiator, we will send authentication data to the remote end. */ @@ -857,57 +948,24 @@ SILC_TASK_CALLBACK(silc_server_protocol_connection_auth) /* Remote end is client */ if (conn_type == SILC_SOCKET_TYPE_CLIENT) { - SilcServerConfigSectionClientConnection *client = ctx->cconfig; + SilcServerConfigClient *client = ctx->cconfig; if (client) { - switch(client->auth_meth) { - case SILC_AUTH_NONE: - /* No authentication required */ - SILC_LOG_DEBUG(("No authentication required")); - break; - - case SILC_AUTH_PASSWORD: - /* Password authentication */ - SILC_LOG_DEBUG(("Password authentication")); - ret = silc_server_password_authentication(server, auth_data, - client->auth_data); - - if (ret) - break; - + ret = silc_server_get_authentication(ctx, client->passphrase, + client->publickey, + auth_data, payload_len); + if (!ret) { /* Authentication failed */ SILC_LOG_ERROR(("Authentication failed")); SILC_LOG_DEBUG(("Authentication failed")); silc_free(auth_data); protocol->state = SILC_PROTOCOL_STATE_ERROR; - silc_protocol_execute(protocol, server->schedule, - 0, 300000); - return; - break; - - case SILC_AUTH_PUBLIC_KEY: - /* Public key authentication */ - SILC_LOG_DEBUG(("Public key authentication")); - ret = silc_server_public_key_authentication(server, - client->auth_data, - auth_data, - payload_len, - ctx->ske); - - if (ret) - break; - - SILC_LOG_ERROR(("Authentication failed")); - SILC_LOG_DEBUG(("Authentication failed")); - silc_free(auth_data); - protocol->state = SILC_PROTOCOL_STATE_ERROR; - silc_protocol_execute(protocol, server->schedule, - 0, 300000); + silc_protocol_execute(protocol, server->schedule, 0, 300000); 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; @@ -919,57 +977,24 @@ SILC_TASK_CALLBACK(silc_server_protocol_connection_auth) /* Remote end is server */ if (conn_type == SILC_SOCKET_TYPE_SERVER) { - SilcServerConfigSectionServerConnection *serv = ctx->sconfig; + SilcServerConfigServer *serv = ctx->sconfig; if (serv) { - switch(serv->auth_meth) { - case SILC_AUTH_NONE: - /* No authentication required */ - SILC_LOG_DEBUG(("No authentication required")); - break; - - case SILC_AUTH_PASSWORD: - /* Password authentication */ - SILC_LOG_DEBUG(("Password authentication")); - ret = silc_server_password_authentication(server, auth_data, - serv->auth_data); - - if (ret) - break; - + ret = silc_server_get_authentication(ctx, serv->passphrase, + serv->publickey, + auth_data, payload_len); + if (!ret) { /* Authentication failed */ SILC_LOG_ERROR(("Authentication failed")); SILC_LOG_DEBUG(("Authentication failed")); silc_free(auth_data); protocol->state = SILC_PROTOCOL_STATE_ERROR; - silc_protocol_execute(protocol, server->schedule, - 0, 300000); - return; - break; - - case SILC_AUTH_PUBLIC_KEY: - /* Public key authentication */ - SILC_LOG_DEBUG(("Public key authentication")); - ret = silc_server_public_key_authentication(server, - serv->auth_data, - auth_data, - payload_len, - ctx->ske); - - if (ret) - break; - - SILC_LOG_ERROR(("Authentication failed")); - SILC_LOG_DEBUG(("Authentication failed")); - silc_free(auth_data); - protocol->state = SILC_PROTOCOL_STATE_ERROR; - silc_protocol_execute(protocol, server->schedule, - 0, 300000); + silc_protocol_execute(protocol, server->schedule, 0, 300000); 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, @@ -981,57 +1006,24 @@ SILC_TASK_CALLBACK(silc_server_protocol_connection_auth) /* Remote end is router */ if (conn_type == SILC_SOCKET_TYPE_ROUTER) { - SilcServerConfigSectionServerConnection *serv = ctx->rconfig; + SilcServerConfigRouter *serv = ctx->rconfig; if (serv) { - switch(serv->auth_meth) { - case SILC_AUTH_NONE: - /* No authentication required */ - SILC_LOG_DEBUG(("No authentication required")); - break; - - case SILC_AUTH_PASSWORD: - /* Password authentication */ - SILC_LOG_DEBUG(("Password authentication")); - ret = silc_server_password_authentication(server, auth_data, - serv->auth_data); - - if (ret) - break; - + ret = silc_server_get_authentication(ctx, serv->passphrase, + serv->publickey, + auth_data, payload_len); + if (!ret) { /* Authentication failed */ SILC_LOG_ERROR(("Authentication failed")); SILC_LOG_DEBUG(("Authentication failed")); silc_free(auth_data); protocol->state = SILC_PROTOCOL_STATE_ERROR; - silc_protocol_execute(protocol, server->schedule, - 0, 300000); - return; - break; - - case SILC_AUTH_PUBLIC_KEY: - /* Public key authentication */ - SILC_LOG_DEBUG(("Public key authentication")); - ret = silc_server_public_key_authentication(server, - serv->auth_data, - auth_data, - payload_len, - ctx->ske); - - if (ret) - break; - - SILC_LOG_ERROR(("Authentication failed")); - SILC_LOG_DEBUG(("Authentication failed")); - silc_free(auth_data); - protocol->state = SILC_PROTOCOL_STATE_ERROR; - silc_protocol_execute(protocol, server->schedule, - 0, 300000); + silc_protocol_execute(protocol, server->schedule, 0, 300000); 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; @@ -1078,14 +1070,9 @@ SILC_TASK_CALLBACK(silc_server_protocol_connection_auth) case SILC_AUTH_PUBLIC_KEY: { - unsigned char sign[1024]; - /* Public key authentication */ - silc_server_get_public_key_auth(server, ctx->auth_data, - sign, &auth_data_len, + silc_server_get_public_key_auth(server, &auth_data, &auth_data_len, ctx->ske); - auth_data = silc_calloc(auth_data_len, sizeof(*auth_data)); - memcpy(auth_data, sign, auth_data_len); break; } } @@ -1138,6 +1125,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); @@ -1164,6 +1156,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); @@ -1183,6 +1180,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); @@ -1213,41 +1215,37 @@ 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); silc_free(idata->rekey->send_enc_key); - idata->rekey->send_enc_key = - silc_calloc(keymat->enc_key_len / 8, - sizeof(*idata->rekey->send_enc_key)); - memcpy(idata->rekey->send_enc_key, keymat->send_enc_key, - keymat->enc_key_len / 8); + idata->rekey->send_enc_key = silc_memdup(keymat->send_enc_key, + keymat->enc_key_len / 8); idata->rekey->enc_key_len = keymat->enc_key_len / 8; } } @@ -1373,12 +1371,12 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey) /* Error in protocol */ protocol->state = SILC_PROTOCOL_STATE_ERROR; silc_protocol_execute(protocol, server->schedule, 0, 300000); + return; } - ctx->ske = silc_ske_alloc(); - ctx->ske->rng = server->rng; + ctx->ske = silc_ske_alloc(server->rng, server); 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, @@ -1388,8 +1386,8 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey) status = silc_ske_responder_phase_2(ctx->ske, ctx->packet->buffer); if (status != SILC_SKE_STATUS_OK) { - SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)", - status)); + SILC_LOG_WARNING(("Error (%s) during Re-key (PFS)", + silc_ske_map_status(status))); protocol->state = SILC_PROTOCOL_STATE_ERROR; silc_protocol_execute(protocol, server->schedule, 0, 300000); @@ -1431,10 +1429,9 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey) * Use Perfect Forward Secrecy, ie. negotiate the key material * using the SKE protocol. */ - ctx->ske = silc_ske_alloc(); - ctx->ske->rng = server->rng; + ctx->ske = silc_ske_alloc(server->rng, server); 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, @@ -1442,10 +1439,10 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey) NULL, NULL, NULL, silc_ske_check_version, context); - status = silc_ske_initiator_phase_2(ctx->ske, NULL, NULL); + status = silc_ske_initiator_phase_2(ctx->ske, NULL, NULL, 0); if (status != SILC_SKE_STATUS_OK) { - SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)", - status)); + SILC_LOG_WARNING(("Error (%s) during Re-key (PFS)", + silc_ske_map_status(status))); protocol->state = SILC_PROTOCOL_STATE_ERROR; silc_protocol_execute(protocol, server->schedule, 0, 300000); @@ -1489,8 +1486,8 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey) status = silc_ske_responder_finish(ctx->ske, NULL, NULL, SILC_SKE_PK_TYPE_SILC); if (status != SILC_SKE_STATUS_OK) { - SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)", - status)); + SILC_LOG_WARNING(("Error (%s) during Re-key (PFS)", + silc_ske_map_status(status))); protocol->state = SILC_PROTOCOL_STATE_ERROR; silc_protocol_execute(protocol, server->schedule, 0, 300000); @@ -1507,12 +1504,13 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey) /* Error in protocol */ protocol->state = SILC_PROTOCOL_STATE_ERROR; silc_protocol_execute(protocol, server->schedule, 0, 300000); + return; } status = silc_ske_initiator_finish(ctx->ske, ctx->packet->buffer); if (status != SILC_SKE_STATUS_OK) { - SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)", - status)); + SILC_LOG_WARNING(("Error (%s) during Re-key (PFS)", + silc_ske_map_status(status))); protocol->state = SILC_PROTOCOL_STATE_ERROR; silc_protocol_execute(protocol, server->schedule, 0, 300000); @@ -1543,13 +1541,19 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey) if (ctx->packet->type != SILC_PACKET_REKEY_DONE) { /* Error in protocol */ protocol->state = SILC_PROTOCOL_STATE_ERROR; - silc_protocol_execute(protocol, server->schedule, 0, 0); + silc_protocol_execute(protocol, server->schedule, 0, 300000); + return; } /* We received the REKEY_DONE packet and all packets after this is 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 +1571,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 +1588,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 +1616,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 +1630,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); }