silc_hmac_set_key(conn->hmac, keymat->hmac_key, keymat->hmac_key_len);
}
+/* Checks the version string of the server. */
+
+SilcSKEStatus silc_ske_check_version(SilcSKE ske, unsigned char *version,
+ unsigned int len)
+{
+ SilcSocketConnection conn = (SilcSocketConnection)ske->sock->user_data;
+ SilcClient client = (SilcClient)ske->user_data;
+ SilcSKEStatus status = SILC_SKE_STATUS_OK;
+
+ /* Check for initial version string */
+ if (!strstr(version, "SILC-1.0-"))
+ status = SILC_SKE_STATUS_BAD_VERSION;
+
+ /* Check software version */
+
+ if (len < strlen(silc_version_string))
+ status = SILC_SKE_STATUS_BAD_VERSION;
+
+ /* XXX for now there is no other tests due to the abnormal version
+ string that is used */
+
+ if (status != SILC_SKE_STATUS_OK)
+ client->ops->say(client, conn,
+ "We don't support server version `%s'", version);
+
+ return status;
+}
+
/* Performs key exchange protocol. This is used for both initiator
and responder key exchange. This may be called recursively. */
/* Allocate Key Exchange object */
ske = silc_ske_alloc();
ctx->ske = ske;
+ ske->rng = client->rng;
+ ske->user_data = (void *)client;
if (ctx->responder == TRUE) {
#if 0
SilcSKEStartPayload *start_payload;
/* Assemble security properties. */
- silc_ske_assemble_security_properties(ske, silc_version_string,
+ silc_ske_assemble_security_properties(ske, SILC_SKE_SP_FLAG_NONE,
+ silc_version_string,
&start_payload);
/* Start the key exchange by sending our security properties
paylaod reply we just got from the responder. The callback
function will receive the processed payload where we will
save it. */
- status = silc_ske_initiator_phase_1(ctx->ske, ctx->packet, NULL, NULL);
+ status = silc_ske_initiator_phase_1(ctx->ske, ctx->packet->buffer,
+ NULL, NULL);
}
if (status != SILC_SKE_STATUS_OK) {
} else {
/* Finish the protocol. This verifies the Key Exchange 2 payload
sent by responder. */
- status = silc_ske_initiator_finish(ctx->ske, ctx->packet,
+ status = silc_ske_initiator_finish(ctx->ske, ctx->packet->buffer,
silc_client_protocol_ke_verify_key,
context, NULL, NULL);
}
protocol->state = SILC_PROTOCOL_STATE_END;
}
break;
+
case SILC_PROTOCOL_STATE_END:
{
/*
silc_protocol_free(protocol);
}
break;
+
case SILC_PROTOCOL_STATE_ERROR:
+ /*
+ * Error during protocol
+ */
+ /* Send abort notification */
+ silc_ske_abort(ctx->ske, ctx->ske->status,
+ silc_client_protocol_ke_send_packet,
+ context);
+
+ /* On error the final callback is always called. */
+ if (protocol->final_callback)
+ protocol->execute_final(client->timeout_queue, 0, protocol, fd);
+ else
+ silc_protocol_free(protocol);
+ break;
+
+ case SILC_PROTOCOL_STATE_FAILURE:
+ /*
+ * Received failure from remote.
+ */
+
/* On error the final callback is always called. */
if (protocol->final_callback)
protocol->execute_final(client->timeout_queue, 0, protocol, fd);
case SILC_PROTOCOL_STATE_ERROR:
{
/*
- * Error
+ * Error. Send notify to remote.
*/
+ unsigned char error[4];
+
+ SILC_PUT32_MSB(SILC_CONN_AUTH_FAILED, error);
/* Error in protocol. Send FAILURE packet. Although I don't think
this could ever happen on client side. */
silc_client_packet_send(client, ctx->sock, SILC_PACKET_FAILURE,
- NULL, 0, NULL, NULL, NULL, 0, TRUE);
+ NULL, 0, NULL, NULL, error, 4, TRUE);
/* On error the final callback is always called. */
if (protocol->final_callback)
else
silc_protocol_free(protocol);
}
+
+ case SILC_PROTOCOL_STATE_FAILURE:
+ /*
+ * Received failure from remote.
+ */
+
+ /* On error the final callback is always called. */
+ if (protocol->final_callback)
+ protocol->execute_final(client->timeout_queue, 0, protocol, fd);
+ else
+ silc_protocol_free(protocol);
break;
+
case SILC_PROTOCOL_STATE_UNKNOWN:
break;
}