001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019
020 package org.apache.geronimo.javamail.authentication;
021
022 import java.io.UnsupportedEncodingException;
023
024 import javax.mail.MessagingException;
025
026 public class PlainAuthenticator implements ClientAuthenticator {
027
028 // the user we're authenticating
029 protected String username;
030
031 // the user's password (the "shared secret")
032 protected String password;
033
034 // indicates whether we've gone through the entire challenge process.
035 protected boolean complete = false;
036
037 /**
038 * Main constructor.
039 *
040 * @param username
041 * The login user name.
042 * @param password
043 * The login password.
044 */
045 public PlainAuthenticator(String username, String password) {
046 this.username = username;
047 this.password = password;
048 }
049
050 /**
051 * Respond to the hasInitialResponse query. This mechanism does have an
052 * initial response, which is the entire challenge sequence.
053 *
054 * @return Always returns true.
055 */
056 public boolean hasInitialResponse() {
057 return true;
058 }
059
060 /**
061 * Indicate whether the challenge/response process is complete.
062 *
063 * @return True if the last challenge has been processed, false otherwise.
064 */
065 public boolean isComplete() {
066 return complete;
067 }
068
069 /**
070 * Retrieve the authenticator mechanism name.
071 *
072 * @return Always returns the string "PLAIN"
073 */
074 public String getMechanismName() {
075 return "PLAIN";
076 }
077
078 /**
079 * Evaluate a PLAIN login challenge, returning the a result string that
080 * should satisfy the clallenge.
081 *
082 * @param challenge
083 * The decoded challenge data, as byte array.
084 *
085 * @return A formatted challege response, as an array of bytes.
086 * @exception MessagingException
087 */
088 public byte[] evaluateChallenge(byte[] challenge) throws MessagingException {
089 try {
090 // get the username and password in an UTF-8 encoding to create the
091 // token
092 byte[] userBytes = username.getBytes("UTF-8");
093 byte[] passBytes = password.getBytes("UTF-8");
094
095 // our token has two copies of the username, one copy of the
096 // password, and nulls
097 // between
098 byte[] tokenBytes = new byte[(userBytes.length * 2) + passBytes.length + 2];
099
100 System.arraycopy(userBytes, 0, tokenBytes, 0, userBytes.length);
101 System.arraycopy(userBytes, 0, tokenBytes, userBytes.length + 1, userBytes.length);
102 System.arraycopy(passBytes, 0, tokenBytes, (userBytes.length * 2) + 2, passBytes.length);
103
104 complete = true;
105 return tokenBytes;
106
107 } catch (UnsupportedEncodingException e) {
108 // got an error, fail this
109 throw new MessagingException("Invalid encoding");
110 }
111 }
112 }