+/* 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,
+ SilcHashTable local_publickeys,
+ unsigned char *remote_auth,
+ SilcUInt32 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_publickeys ||
+ !silc_hash_table_count(local_publickeys))) {
+ 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_publickeys) {
+ SilcPublicKey cached_key;
+ SilcPublicKey remote_key =
+ ((SilcIDListData)ctx->sock->user_data)->public_key;
+
+ SILC_LOG_DEBUG(("Public key authentication"));
+
+ /* Find the public key to be used in authentication */
+ cached_key = silc_server_find_public_key(server, local_publickeys,
+ remote_key);
+ if (!cached_key)
+ return FALSE;
+
+ result = silc_server_public_key_authentication(server, cached_key,
+ remote_auth,
+ remote_auth_len, ske);
+ }
+
+ SILC_LOG_DEBUG(("Authentication %s", result ? "successful" : "failed"));
+
+ return result;
+}
+
+/* Performs connection authentication protocol. If responder, we