Package org.subethamail.smtp.auth

Source Code of org.subethamail.smtp.auth.PlainAuthenticationHandlerFactory$Handler

package org.subethamail.smtp.auth;

import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import org.subethamail.smtp.AuthenticationHandler;
import org.subethamail.smtp.AuthenticationHandlerFactory;
import org.subethamail.smtp.RejectException;
import org.subethamail.smtp.util.Base64;

/**
* Implements the SMTP AUTH PLAIN mechanism.<br>
* You are only required to plug your UsernamePasswordValidator implementation
* for username and password validation to take effect.
*
* @author Marco Trevisan <mrctrevisan@yahoo.it>
* @author Jeff Schnitzer
* @author Ian White <ibwhite@gmail.com>
*/
public class PlainAuthenticationHandlerFactory implements AuthenticationHandlerFactory
{
  static List<String> MECHANISMS = new ArrayList<String>(1);
  static {
    MECHANISMS.add("PLAIN");
  }

  private UsernamePasswordValidator helper;

  /** */
  public PlainAuthenticationHandlerFactory(UsernamePasswordValidator helper)
  {
    this.helper = helper;
  }

  /** */
  public List<String> getAuthenticationMechanisms()
  {
    return MECHANISMS;
  }

  /** */
  public AuthenticationHandler create()
  {
    return new Handler();
  }

  /**
   */
  class Handler implements AuthenticationHandler
  {
    private String username;
    private String password;

    /* */
    public String auth(String clientInput) throws RejectException
    {
      StringTokenizer stk = new StringTokenizer(clientInput);
      String secret = stk.nextToken();
      if (secret.trim().equalsIgnoreCase("AUTH"))
      {
        // Let's read the RFC2554 "initial-response" parameter
        // The line could be in the form of "AUTH PLAIN <base64Secret>"
        if (!stk.nextToken().trim().equalsIgnoreCase("PLAIN"))
        {
          // Mechanism mismatch
          throw new RejectException(504, "AUTH mechanism mismatch");
        }

        if (stk.hasMoreTokens())
        {
          // the client submitted an initial response
          secret = stk.nextToken();
        }
        else
        {
          // the client did not submit an initial response, we'll get it in the next pass
          return "334 Ok";
        }
      }

      byte[] decodedSecret = Base64.decode(secret);
      if (decodedSecret == null)
        throw new RejectException();

      /*
       * RFC4616: The client presents the authorization identity (identity
       * to act as), followed by a NUL (U+0000) character, followed by the
       * authentication identity (identity whose password will be used),
       * followed by a NUL (U+0000) character, followed by the clear-text
       * password.
       */

      int i, j;
      for (i = 0; i < decodedSecret.length && decodedSecret[i] != 0; i++)
        ;
      if (i >= decodedSecret.length)
      {
        throw new RejectException();
      }

      for (j = i + 1; j < decodedSecret.length && decodedSecret[j] != 0; j++)
        ;
      if (j >= decodedSecret.length)
      {
        throw new RejectException();
      }

      @SuppressWarnings("unused")
      String authorizationId = new String(decodedSecret, 0, i);
      String authenticationId = new String(decodedSecret, i + 1, j - i - 1);
      String passwd = new String(decodedSecret, j + 1, decodedSecret.length - j - 1);

      // might be nice to do something with authorizationId, but for
      // purposes of the UsernamePasswordValidator, we just want to use
      // authenticationId

      this.username = authenticationId;
      this.password = passwd;
      try
      {
        PlainAuthenticationHandlerFactory.this.helper.login(this.username.toString(), this.password);
      }
      catch (LoginFailedException lfe)
      {
        throw new RejectException();
      }

      return null;
    }

    /* */
    public Object getIdentity()
    {
      return this.username;
    }
  }
}
TOP

Related Classes of org.subethamail.smtp.auth.PlainAuthenticationHandlerFactory$Handler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.