1 21 22 27 28 package com.sun.mail.imap.protocol; 29 30 import java.io.*; 31 import java.util.*; 32 import javax.security.sasl.*; 33 import javax.security.auth.callback.*; 34 35 import com.sun.mail.iap.*; 36 import com.sun.mail.imap.*; 37 import com.sun.mail.util.*; 38 39 44 45 public class IMAPSaslAuthenticator implements SaslAuthenticator { 46 47 private IMAPProtocol pr; 48 private String name; 49 private Properties props; 50 private boolean debug; 51 private PrintStream out; 52 private String host; 53 54 public IMAPSaslAuthenticator(IMAPProtocol pr, String name, Properties props, 55 boolean debug, PrintStream out, String host) { 56 this.pr = pr; 57 this.name = name; 58 this.props = props; 59 this.debug = debug; 60 this.out = out; 61 this.host = host; 62 } 63 64 public boolean authenticate(String [] mechs, String realm, String authzid, 65 String u, String p) throws ProtocolException { 66 67 Vector v = new Vector(); 68 String tag = null; 69 Response r = null; 70 boolean done = false; 71 if (debug) { 72 out.print("IMAP SASL DEBUG: Mechanisms:"); 73 for (int i = 0; i < mechs.length; i++) 74 out.print(" " + mechs[i]); 75 out.println(); 76 } 77 78 SaslClient sc; 79 final String r0 = realm; 80 final String u0 = u; 81 final String p0 = p; 82 CallbackHandler cbh = new CallbackHandler() { 83 public void handle(Callback[] callbacks) { 84 if (debug) 85 out.println("IMAP SASL DEBUG: callback length: " + 86 callbacks.length); 87 for (int i = 0; i < callbacks.length; i++) { 88 if (debug) 89 out.println("IMAP SASL DEBUG: callback " + i + ": " + 90 callbacks[i]); 91 if (callbacks[i] instanceof NameCallback) { 92 NameCallback ncb = (NameCallback)callbacks[i]; 93 ncb.setName(u0); 94 } else if (callbacks[i] instanceof PasswordCallback) { 95 PasswordCallback pcb = (PasswordCallback)callbacks[i]; 96 pcb.setPassword(p0.toCharArray()); 97 } else if (callbacks[i] instanceof RealmCallback) { 98 RealmCallback rcb = (RealmCallback)callbacks[i]; 99 rcb.setText(r0 != null ? 100 r0 : rcb.getDefaultText()); 101 } else if (callbacks[i] instanceof RealmChoiceCallback) { 102 RealmChoiceCallback rcb = 103 (RealmChoiceCallback)callbacks[i]; 104 if (r0 == null) 105 rcb.setSelectedIndex(rcb.getDefaultChoice()); 106 else { 107 String [] choices = rcb.getChoices(); 109 for (int k = 0; k < choices.length; k++) { 110 if (choices[k].equals(r0)) { 111 rcb.setSelectedIndex(k); 112 break; 113 } 114 } 115 } 116 } 117 } 118 } 119 }; 120 121 try { 122 sc = Sasl.createSaslClient(mechs, authzid, name, host, 123 (Map)props, cbh); 124 } catch (SaslException sex) { 125 if (debug) 126 out.println("IMAP SASL DEBUG: Failed to create SASL client: " + 127 sex); 128 return false; 129 } 130 if (sc == null) { 131 if (debug) 132 out.println("IMAP SASL DEBUG: No SASL support"); 133 return false; 134 } 135 if (debug) 136 out.println("IMAP SASL DEBUG: SASL client " + 137 sc.getMechanismName()); 138 139 try { 140 tag = pr.writeCommand("AUTHENTICATE " + sc.getMechanismName(), 141 null); 142 } catch (Exception ex) { 143 if (debug) 144 out.println("IMAP SASL DEBUG: AUTHENTICATE Exception: " + ex); 145 return false; 146 } 147 148 OutputStream os = pr.getIMAPOutputStream(); 150 162 163 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 164 byte[] CRLF = { (byte)'\r', (byte)'\n'}; 165 166 while (!done) { try { 168 r = pr.readResponse(); 169 if (r.isContinuation()) { 170 byte[] ba = r.readByteArray().getNewBytes(); 171 if (ba.length > 0) 172 ba = BASE64DecoderStream.decode(ba); 173 if (debug) 174 out.println("IMAP SASL DEBUG: challenge: " + 175 ASCIIUtility.toString(ba, 0, ba.length) + " :"); 176 ba = sc.evaluateChallenge(ba); 177 done = sc.isComplete(); 179 if (ba == null) { 180 if (debug) 181 out.println("IMAP SASL DEBUG: no response"); 182 done = true; 183 os.write(CRLF); os.flush(); bos.reset(); } else { 187 if (debug) 188 out.println("IMAP SASL DEBUG: response: " + 189 ASCIIUtility.toString(ba, 0, ba.length) + " :"); 190 ba = BASE64EncoderStream.encode(ba); 191 bos.write(ba); 192 193 bos.write(CRLF); os.write(bos.toByteArray()); os.flush(); bos.reset(); } 198 } else if (r.isTagged() && r.getTag().equals(tag)) 199 done = true; 201 else if (r.isBYE()) done = true; 203 else v.addElement(r); 205 } catch (Exception ioex) { 206 if (debug) 207 ioex.printStackTrace(); 208 r = Response.byeResponse(ioex); 210 done = true; 211 } 213 } 214 215 if (sc.isComplete() ) { 216 String qop = (String )sc.getNegotiatedProperty(Sasl.QOP); 217 if (qop != null && (qop.equalsIgnoreCase("auth-int") || 218 qop.equalsIgnoreCase("auth-conf"))) { 219 if (debug) 221 out.println("IMAP SASL DEBUG: " + 222 "Mechanism requires integrity or confidentiality"); 223 return false; 224 } 225 } 226 227 233 Response[] responses = new Response[v.size()]; 234 v.copyInto(responses); 235 pr.notifyResponseHandlers(responses); 236 237 pr.handleResult(r); 239 return true; 240 } 241 } 242 | Popular Tags |