/*

  sshauthmethodc.c

  Authors:
        Tatu Ylonen <ylo@ssh.com>
        Markku-Juhani Saarinen <mjos@ssh.com>
        Timo J. Rinne <tri@ssh.com>
        Sami Lehtinen <sjl@ssh.com>

  Copyright (C) 1997-2000 SSH Communications Security Corp, Helsinki, Finland
  All rights reserved.

  SSH2 authentication methods for the client.

*/

#include "ssh2includes.h"
#include "sshencode.h"
#include "sshauth.h"
#include "readpass.h"
#include "authc-pubkey.h"
#include "authc-passwd.h"
#include "authc-hostbased.h"
#include "sshdllist.h"

#define SSH_DEBUG_MODULE "SshAuthMethodClient"

/* table of the supported authentication methods */

SshAuthClientMethod client_methods[] =
{
#ifndef SSH_WIN_CLIENT
  /* XXX test hostbased and pubkey auth on Windows later */
  { SSH_AUTH_HOSTBASED, ssh_client_auth_hostbased },
  { SSH_AUTH_PUBKEY, ssh_client_auth_pubkey },
#endif /* SSH_WIN_CLIENT */
#ifdef WITH_PAM
  { SSH_AUTH_PAM, ssh_client_auth_pam },
#endif /* WITH_PAM */
  { SSH_AUTH_PASSWD, ssh_client_auth_passwd },
  { NULL, NULL }
};

/* Initializes the authentication methods array for the client. */

SshAuthClientMethod *ssh_client_authentication_initialize(SshDlList conf_methods)
{
  SshAuthClientMethod *methods;
  SshDlList new_list;
  int i = 0, j = 0;
  char *cur_method = NULL, *existing = NULL;
  
  SSH_PRECOND(conf_methods);
  
  methods = ssh_xcalloc(sizeof(client_methods)/sizeof(*client_methods),
                        sizeof(*client_methods));

  /* Delete duplicate methods. */
  new_list = ssh_dllist_allocate();
  ssh_dllist_rewind(conf_methods);
  cur_method = ssh_dllist_current(conf_methods);

  for (;cur_method; ssh_dllist_fw(conf_methods, 1))
    {
      for (ssh_dllist_rewind(new_list);
           (existing = ssh_dllist_current(new_list)) != NULL;
           ssh_dllist_fw(new_list, 1))
        {
          SSH_ASSERT(existing);
          if (strcmp(existing, cur_method) == 0)
            break;
        }

      if (!existing)
        {
          ssh_dllist_add_item(new_list, cur_method, SSH_DLLIST_END);
          SSH_DEBUG(4, ("Added method \"%s\" to candidates.", cur_method));
        }
      
      cur_method = ssh_dllist_current(conf_methods);
    }


  /* Add the methods to the array in the order they are presented in
     the config. */
  ssh_dllist_rewind(new_list);
  cur_method = ssh_dllist_current(new_list);

  for (;cur_method; ssh_dllist_fw(new_list, 1),
         cur_method = ssh_dllist_current(new_list))
    {
      for (i = 0; client_methods[i].name != NULL; i++)
        {
          if (strcmp(client_methods[i].name, cur_method) == 0)
            {
              methods[j++] = client_methods[i];
              SSH_DEBUG(2, ("Added \"%s\" to usable methods.",
                            client_methods[i].name));
            }
        }
    }

  ssh_dllist_free(new_list);
  return methods;
}

/* Frees the returned authentication method array. */

void ssh_client_authentication_uninitialize(SshAuthClientMethod *methods)
{
  memset(methods, 'F', sizeof(client_methods));
  ssh_xfree(methods);
}
