1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 20 package org.apache.geronimo.javamail.authentication; 21 22 import java.io.UnsupportedEncodingException; 23 24 import javax.mail.MessagingException; 25 26 public class LoginAuthenticator implements ClientAuthenticator { 27 28 // constants for the authentication stages 29 protected static final int USERNAME = 0; 30 31 protected static final int PASSWORD = 1; 32 33 protected static final int COMPLETE = 2; 34 35 // the user we're authenticating 36 protected String username; 37 38 // the user's password (the "shared secret") 39 protected String password; 40 41 // indicates whether we've gone through the entire challenge process. 42 protected int stage = USERNAME; 43 44 /** 45 * Main constructor. 46 * 47 * @param username 48 * The login user name. 49 * @param password 50 * The login password. 51 */ 52 public LoginAuthenticator(String username, String password) { 53 this.username = username; 54 this.password = password; 55 } 56 57 /** 58 * Respond to the hasInitialResponse query. This mechanism does not have an 59 * initial response. 60 * 61 * @return Always returns false; 62 */ 63 public boolean hasInitialResponse() { 64 return false; 65 } 66 67 /** 68 * Indicate whether the challenge/response process is complete. 69 * 70 * @return True if the last challenge has been processed, false otherwise. 71 */ 72 public boolean isComplete() { 73 return stage == COMPLETE; 74 } 75 76 /** 77 * Retrieve the authenticator mechanism name. 78 * 79 * @return Always returns the string "LOGIN" 80 */ 81 public String getMechanismName() { 82 return "LOGIN"; 83 } 84 85 /** 86 * Evaluate a PLAIN login challenge, returning the a result string that 87 * should satisfy the clallenge. 88 * 89 * @param challenge 90 * The decoded challenge data, as a byte array 91 * 92 * @return A formatted challege response, as an array of bytes. 93 * @exception MessagingException 94 */ 95 public byte[] evaluateChallenge(byte[] challenge) throws MessagingException { 96 97 // process the correct stage for the challenge 98 switch (stage) { 99 // should never happen 100 case COMPLETE: 101 throw new MessagingException("Invalid LOGIN challenge"); 102 103 case USERNAME: { 104 byte[] userBytes; 105 106 try { 107 // get the username and password in an UTF-8 encoding to create 108 // the token 109 userBytes = username.getBytes("UTF-8"); 110 } catch (UnsupportedEncodingException e) { 111 // got an error, fail this (this should never happen). 112 throw new MessagingException("Invalid encoding"); 113 } 114 115 // next time through we're looking for a password. 116 stage = PASSWORD; 117 // the user bytes are the entire challenge respose. 118 return userBytes; 119 } 120 121 case PASSWORD: { 122 byte[] passBytes; 123 124 try { 125 // get the username and password in an UTF-8 encoding to create 126 // the token 127 passBytes = password.getBytes("UTF-8"); 128 } catch (UnsupportedEncodingException e) { 129 // got an error, fail this (this should never happen). 130 throw new MessagingException("Invalid encoding"); 131 } 132 // we're finished 133 stage = COMPLETE; 134 return passBytes; 135 } 136 } 137 // should never get here. 138 throw new MessagingException("Invalid LOGIN challenge"); 139 } 140 }