src/java.security.sasl/share/classes/com/sun/security/sasl/digest/DigestMD5Server.java
changeset 59024 b046ba510bbc
parent 55040 0627b8ad33c1
equal deleted inserted replaced
59023:f0dca628176c 59024:b046ba510bbc
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
    25 
    26 package com.sun.security.sasl.digest;
    26 package com.sun.security.sasl.digest;
    27 
    27 
    28 import java.security.NoSuchAlgorithmException;
       
    29 import java.io.ByteArrayOutputStream;
    28 import java.io.ByteArrayOutputStream;
    30 import java.io.IOException;
    29 import java.io.IOException;
    31 import java.io.UnsupportedEncodingException;
    30 import java.security.NoSuchAlgorithmException;
    32 import java.util.StringTokenizer;
    31 import java.util.StringTokenizer;
    33 import java.util.ArrayList;
    32 import java.util.ArrayList;
    34 import java.util.List;
    33 import java.util.List;
    35 import java.util.Map;
    34 import java.util.Map;
    36 import java.util.Arrays;
    35 import java.util.Arrays;
    37 
    36 
    38 import java.util.logging.Level;
    37 import java.util.logging.Level;
    39 
    38 
    40 import javax.security.sasl.*;
    39 import javax.security.sasl.*;
    41 import javax.security.auth.callback.*;
    40 import javax.security.auth.callback.*;
       
    41 
       
    42 import static java.nio.charset.StandardCharsets.*;
    42 
    43 
    43 /**
    44 /**
    44   * An implementation of the DIGEST-MD5 server SASL mechanism.
    45   * An implementation of the DIGEST-MD5 server SASL mechanism.
    45   * (<a href="http://www.ietf.org/rfc/rfc2831.txt">RFC 2831</a>)
    46   * (<a href="http://www.ietf.org/rfc/rfc2831.txt">RFC 2831</a>)
    46   * <p>
    47   * <p>
   169                     serverRealms.add(token);
   170                     serverRealms.add(token);
   170                 }
   171                 }
   171             }
   172             }
   172         }
   173         }
   173 
   174 
   174         encoding = (useUTF8 ? "UTF8" : "8859_1");
   175         encoding = (useUTF8 ? UTF_8 : ISO_8859_1);
   175 
   176 
   176         // By default, use server name as realm
   177         // By default, use server name as realm
   177         if (serverRealms.isEmpty()) {
   178         if (serverRealms.isEmpty()) {
   178             if (serverName == null) {
   179             if (serverName == null) {
   179                 throw new SaslException(
   180                 throw new SaslException(
   227                 challenge = generateChallenge(serverRealms, specifiedQops,
   228                 challenge = generateChallenge(serverRealms, specifiedQops,
   228                     supportedCiphers);
   229                     supportedCiphers);
   229 
   230 
   230                 step = 3;
   231                 step = 3;
   231                 return challenge;
   232                 return challenge;
   232             } catch (UnsupportedEncodingException e) {
       
   233                 throw new SaslException(
       
   234                     "DIGEST-MD5: Error encoding challenge", e);
       
   235             } catch (IOException e) {
   233             } catch (IOException e) {
   236                 throw new SaslException(
   234                 throw new SaslException(
   237                     "DIGEST-MD5: Error generating challenge", e);
   235                     "DIGEST-MD5: Error generating challenge", e);
   238             }
   236             }
   239 
   237 
   245              */
   243              */
   246             try {
   244             try {
   247                 byte[][] responseVal = parseDirectives(response, DIRECTIVE_KEY,
   245                 byte[][] responseVal = parseDirectives(response, DIRECTIVE_KEY,
   248                     null, REALM);
   246                     null, REALM);
   249                 challenge = validateClientResponse(responseVal);
   247                 challenge = validateClientResponse(responseVal);
   250             } catch (SaslException e) {
       
   251                 throw e;
       
   252             } catch (UnsupportedEncodingException e) {
       
   253                 throw new SaslException(
       
   254                     "DIGEST-MD5: Error validating client response", e);
       
   255             } finally {
   248             } finally {
   256                 step = 0;  // Set to invalid state
   249                 step = 0;  // Set to invalid state
   257             }
   250             }
   258 
   251 
   259             completed = true;
   252             completed = true;
   296      *        cipher-value      = "3des" | "des" | "rc4-40" | "rc4" |
   289      *        cipher-value      = "3des" | "des" | "rc4-40" | "rc4" |
   297      *                            "rc4-56" | token
   290      *                            "rc4-56" | token
   298      *        auth-param        = token "=" ( token | quoted-string )
   291      *        auth-param        = token "=" ( token | quoted-string )
   299      */
   292      */
   300     private byte[] generateChallenge(List<String> realms, String qopStr,
   293     private byte[] generateChallenge(List<String> realms, String qopStr,
   301         String cipherStr) throws UnsupportedEncodingException, IOException {
   294         String cipherStr) throws IOException {
   302         ByteArrayOutputStream out = new ByteArrayOutputStream();
   295         ByteArrayOutputStream out = new ByteArrayOutputStream();
   303 
   296 
   304         // Realms (>= 0)
   297         // Realms (>= 0)
   305         for (int i = 0; realms != null && i < realms.size(); i++) {
   298         for (int i = 0; realms != null && i < realms.size(); i++) {
   306             out.write("realm=\"".getBytes(encoding));
   299             out.write("realm=\"".getBytes(encoding));
   387      *   sendMaxBufSize
   380      *   sendMaxBufSize
   388      *   authzid (gotten from callback)
   381      *   authzid (gotten from callback)
   389      * @return response-value ('rspauth') for client to validate
   382      * @return response-value ('rspauth') for client to validate
   390      */
   383      */
   391     private byte[] validateClientResponse(byte[][] responseVal)
   384     private byte[] validateClientResponse(byte[][] responseVal)
   392         throws SaslException, UnsupportedEncodingException {
   385         throws SaslException {
   393 
   386 
   394         /* CHARSET: optional atmost once */
   387         /* CHARSET: optional atmost once */
   395         if (responseVal[CHARSET] != null) {
   388         if (responseVal[CHARSET] != null) {
   396             // The client should send this directive only if the server has
   389             // The client should send this directive only if the server has
   397             // indicated it supports UTF-8.
   390             // indicated it supports UTF-8.