View Javadoc

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 }