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 }