/**
   * @param authentication
   * @param msg
   * @return
   * @throws IOException
   */
  public int authenticate(AuthenticationProtocolServer authentication, SshMsgUserAuthRequest msg)
      throws IOException {
    NativeAuthenticationProvider authImpl = NativeAuthenticationProvider.getInstance();

    if (authImpl == null) {
      log.error("Cannot perfrom authentication witout native authentication provider");

      return AuthenticationProtocolState.FAILED;
    }

    ByteArrayReader bar = new ByteArrayReader(msg.getRequestData());
    boolean changepwd = ((bar.read() == 0) ? false : true);
    String password = bar.readString();
    String newpassword = null;

    if (changepwd) {
      newpassword = bar.readString();

      try {
        if (!authImpl.changePassword(msg.getUsername(), password, newpassword)) {
          return AuthenticationProtocolState.FAILED;
        }

        if (authImpl.logonUser(msg.getUsername(), newpassword)) {
          return AuthenticationProtocolState.COMPLETE;
        } else {
          return AuthenticationProtocolState.FAILED;
        }
      } catch (PasswordChangeException ex1) {
        return AuthenticationProtocolState.FAILED;
      }
    } else {
      try {
        if (authImpl.logonUser(msg.getUsername(), password)) {
          log.info(msg.getUsername() + " has passed password authentication");

          return AuthenticationProtocolState.COMPLETE;
        } else {
          log.info(msg.getUsername() + " has failed password authentication");

          return AuthenticationProtocolState.FAILED;
        }
      } catch (PasswordChangeException ex) {
        SshMsgUserAuthPwdChangeReq reply =
            new SshMsgUserAuthPwdChangeReq(
                msg.getUsername() + " is required to change password", "");
        authentication.sendMessage(reply);

        return AuthenticationProtocolState.READY;
      }
    }
  }
  private SshPublicKey getAuthorizedKey(String username, String algorithm, byte[] encoded)
      throws IOException {
    NativeAuthenticationProvider provider = NativeAuthenticationProvider.getInstance();

    String userHome = provider.getHomeDirectory(username); // , nativeSettings);

    if (userHome == null) {
      log.warn("There is no home directory for " + username + " is available");
    }

    // Replace '\' with '/' because when we use it in String.replaceAll
    // for some reason it removes them?
    if (userHome != null) {
      userHome = userHome.replace('\\', '/');
    }

    ServerConfiguration config =
        (ServerConfiguration) ConfigurationLoader.getConfiguration(ServerConfiguration.class);
    String authorizationFile;
    String userConfigDir = config.getUserConfigDirectory();

    // First replace any '\' with '/' (Becasue replaceAll removes them!)
    userConfigDir = userConfigDir.replace('\\', '/');

    // Replace any home directory tokens
    if ((userConfigDir.indexOf("%D") > -1) && (userHome == null)) {
      throw new IOException(
          "<UserConfigDirectory> requires home directory, but none available for " + username);
    }

    int idx = 0;

    while ((idx = userConfigDir.indexOf("%D", idx + 1)) > -1) {
      StringBuffer buf = new StringBuffer(userConfigDir);
      buf = buf.replace(idx, idx + 1, userHome);
      userConfigDir = buf.toString();
    }

    idx = 0;

    while ((idx = userConfigDir.indexOf("%U", idx + 1)) > -1) {
      StringBuffer buf = new StringBuffer(userConfigDir);
      buf = buf.replace(idx, idx + 1, username);
      userConfigDir = buf.toString();
    }

    // Replace the '/' with File.seperator and trim
    userConfigDir = userConfigDir.replace('/', File.separatorChar).trim();

    if (!userConfigDir.endsWith(File.separator)) {
      userConfigDir += File.separator;
    }

    authorizationFile = userConfigDir + config.getAuthorizationFile();

    // Load the authorization file
    File file = new File(authorizationFile);

    if (!file.exists()) {
      log.info("authorizationFile: " + authorizationFile + " does not exist.");
      throw new IOException("authorizationFile: " + authorizationFile + " does not exist.");
    }

    FileInputStream in = new FileInputStream(file);
    Authorization keys;

    try {
      keys = new Authorization(in);
    } catch (Exception e) {
      throw new AuthenticationProtocolException(
          "Failed to load authorized keys file " + authorizationFile);
    }

    //      SshPublicKey key = SshPublicKeyFile.parse(encoded);
    Iterator it = keys.getAuthorizedKeys().iterator();

    SshKeyPair pair = SshKeyPairFactory.newInstance(algorithm);
    SshPublicKey authorizedKey = null;
    SshPublicKey key = pair.decodePublicKey(encoded);
    boolean valid = false;
    String keyfile;

    while (it.hasNext()) {
      keyfile = (String) it.next();

      // Look for the file in the user config dir first
      file = new File(userConfigDir + keyfile);

      // If it does not exist then look absolute
      if (!file.exists()) {
        file = new File(keyfile);
      }

      if (file.exists()) {
        // Try to open the public key in the default file format
        // otherwise attempt the supported key formats
        SshPublicKeyFile pkf = SshPublicKeyFile.parse(file);
        authorizedKey = pkf.toPublicKey();

        if (authorizedKey.equals(key)) {
          return authorizedKey;
        }
      } else {
        log.info("Failed attempt to load key file " + keyfile);
      }
    }

    throw new IOException("");
  }