src/java.security.sasl/share/classes/com/sun/security/sasl/digest/DigestMD5Server.java
author hb
Tue, 02 Jan 2018 15:03:52 +0530
branchjmx-rest-api
changeset 56005 90cff2ac77b8
parent 47216 71c04702a3d5
child 55040 0627b8ad33c1
permissions -rw-r--r--
REST base url gets complete complete domain name
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
14342
8435a30053c1 7197491: update copyright year to match last edit in jdk8 jdk repository
alanb
parents: 14340
diff changeset
     2
 * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
package com.sun.security.sasl.digest;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
import java.security.NoSuchAlgorithmException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
import java.io.ByteArrayOutputStream;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
import java.io.IOException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
import java.io.UnsupportedEncodingException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
import java.util.StringTokenizer;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
import java.util.ArrayList;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
import java.util.List;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
import java.util.Map;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
import java.util.Arrays;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
import java.util.logging.Level;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
import javax.security.sasl.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
import javax.security.auth.callback.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
  * An implementation of the DIGEST-MD5 server SASL mechanism.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
  * (<a href="http://www.ietf.org/rfc/rfc2831.txt">RFC 2831</a>)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
  * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
  * The DIGEST-MD5 SASL mechanism specifies two modes of authentication.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
  * <ul><li>Initial Authentication
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
  * <li>Subsequent Authentication - optional, (currently not supported)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
  * </ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
  *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
  * Required callbacks:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
  * - RealmCallback
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
  *      used as key by handler to fetch password
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
  * - NameCallback
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
  *      used as key by handler to fetch password
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
  * - PasswordCallback
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
  *      handler must enter password for username/realm supplied
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
  * - AuthorizeCallback
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
  *      handler must verify that authid/authzids are allowed and set
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
  *      authorized ID to be the canonicalized authzid (if applicable).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
  *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
  * Environment properties that affect the implementation:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
  * javax.security.sasl.qop:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
  *    specifies list of qops; default is "auth"; typically, caller should set
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
  *    this to "auth, auth-int, auth-conf".
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
  * javax.security.sasl.strength
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
  *    specifies low/medium/high strength of encryption; default is all available
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
  *    ciphers [high,medium,low]; high means des3 or rc4 (128); medium des or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
  *    rc4-56; low is rc4-40.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
  * javax.security.sasl.maxbuf
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
  *    specifies max receive buf size; default is 65536
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
  * javax.security.sasl.sendmaxbuffer
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
  *    specifies max send buf size; default is 65536 (min of this and client's max
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
  *    recv size)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
  *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
  * com.sun.security.sasl.digest.utf8:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
  *    "true" means to use UTF-8 charset; "false" to use ISO-8859-1 encoding;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
  *    default is "true".
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
  * com.sun.security.sasl.digest.realm:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
  *    space-separated list of realms; default is server name (fqdn parameter)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
  *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
  * @author Rosanna Lee
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
  */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
final class DigestMD5Server extends DigestMD5Base implements SaslServer {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
    private static final String MY_CLASS_NAME = DigestMD5Server.class.getName();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
    private static final String UTF8_DIRECTIVE = "charset=utf-8,";
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
    private static final String ALGORITHM_DIRECTIVE = "algorithm=md5-sess";
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
     * Always expect nonce count value to be 1 because we support only
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
     * initial authentication.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
    private static final int NONCE_COUNT_VALUE = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
    /* "true" means use UTF8; "false" ISO 8859-1; default is "true" */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
    private static final String UTF8_PROPERTY =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
        "com.sun.security.sasl.digest.utf8";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
    /* List of space-separated realms used for authentication */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
    private static final String REALM_PROPERTY =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
        "com.sun.security.sasl.digest.realm";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
    /* Directives encountered in responses sent by the client. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
    private static final String[] DIRECTIVE_KEY = {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
        "username",    // exactly once
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
        "realm",       // exactly once if sent by server
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
        "nonce",       // exactly once
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
        "cnonce",      // exactly once
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
        "nonce-count", // atmost once; default is 00000001
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
        "qop",         // atmost once; default is "auth"
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
        "digest-uri",  // atmost once; (default?)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
        "response",    // exactly once
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
        "maxbuf",      // atmost once; default is 65536
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
        "charset",     // atmost once; default is ISO-8859-1
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
        "cipher",      // exactly once if qop is "auth-conf"
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
        "authzid",     // atmost once; default is none
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
        "auth-param",  // >= 0 times (ignored)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
    };
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
    /* Indices into DIRECTIVE_KEY */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
    private static final int USERNAME = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
    private static final int REALM = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
    private static final int NONCE = 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
    private static final int CNONCE = 3;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
    private static final int NONCE_COUNT = 4;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
    private static final int QOP = 5;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
    private static final int DIGEST_URI = 6;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
    private static final int RESPONSE = 7;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
    private static final int MAXBUF = 8;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
    private static final int CHARSET = 9;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
    private static final int CIPHER = 10;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
    private static final int AUTHZID = 11;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
    private static final int AUTH_PARAM = 12;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
    /* Server-generated/supplied information */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
    private String specifiedQops;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
    private byte[] myCiphers;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
    private List<String> serverRealms;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
10336
0bb1999251f8 7064075: Security libraries don't build with javac -Xlint:all,-deprecation -Werror
jjg
parents: 5506
diff changeset
   143
    DigestMD5Server(String protocol, String serverName, Map<String, ?> props,
14340
e150cbaf584e 7110803: SASL service for multiple hostnames
weijun
parents: 10336
diff changeset
   144
            CallbackHandler cbh) throws SaslException {
e150cbaf584e 7110803: SASL service for multiple hostnames
weijun
parents: 10336
diff changeset
   145
        super(props, MY_CLASS_NAME, 1,
e150cbaf584e 7110803: SASL service for multiple hostnames
weijun
parents: 10336
diff changeset
   146
                protocol + "/" + (serverName==null?"*":serverName),
e150cbaf584e 7110803: SASL service for multiple hostnames
weijun
parents: 10336
diff changeset
   147
                cbh);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
        serverRealms = new ArrayList<String>();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
        useUTF8 = true;  // default
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
        if (props != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
            specifiedQops = (String) props.get(Sasl.QOP);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
            if ("false".equals((String) props.get(UTF8_PROPERTY))) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
                useUTF8 = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
                logger.log(Level.FINE, "DIGEST80:Server supports ISO-Latin-1");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
            String realms = (String) props.get(REALM_PROPERTY);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
            if (realms != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
                StringTokenizer parser = new StringTokenizer(realms, ", \t\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
                int tokenCount = parser.countTokens();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
                String token = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
                for (int i = 0; i < tokenCount; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
                    token = parser.nextToken();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
                    logger.log(Level.FINE, "DIGEST81:Server supports realm {0}",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
                        token);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
                    serverRealms.add(token);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
        encoding = (useUTF8 ? "UTF8" : "8859_1");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
        // By default, use server name as realm
10336
0bb1999251f8 7064075: Security libraries don't build with javac -Xlint:all,-deprecation -Werror
jjg
parents: 5506
diff changeset
   177
        if (serverRealms.isEmpty()) {
14340
e150cbaf584e 7110803: SASL service for multiple hostnames
weijun
parents: 10336
diff changeset
   178
            if (serverName == null) {
e150cbaf584e 7110803: SASL service for multiple hostnames
weijun
parents: 10336
diff changeset
   179
                throw new SaslException(
e150cbaf584e 7110803: SASL service for multiple hostnames
weijun
parents: 10336
diff changeset
   180
                        "A realm must be provided in props or serverName");
e150cbaf584e 7110803: SASL service for multiple hostnames
weijun
parents: 10336
diff changeset
   181
            } else {
e150cbaf584e 7110803: SASL service for multiple hostnames
weijun
parents: 10336
diff changeset
   182
                serverRealms.add(serverName);
e150cbaf584e 7110803: SASL service for multiple hostnames
weijun
parents: 10336
diff changeset
   183
            }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
    public  byte[] evaluateResponse(byte[] response) throws SaslException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
        if (response.length > MAX_RESPONSE_LENGTH) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
            throw new SaslException(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
                "DIGEST-MD5: Invalid digest response length. Got:  " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
                response.length + " Expected < " + MAX_RESPONSE_LENGTH);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
        byte[] challenge;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
        switch (step) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
        case 1:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
            if (response.length != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
                throw new SaslException(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
                    "DIGEST-MD5 must not have an initial response");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
            /* Generate first challenge */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
            String supportedCiphers = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
            if ((allQop&PRIVACY_PROTECTION) != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
                myCiphers = getPlatformCiphers();
24969
afa6934dd8e8 8041679: Replace uses of StringBuffer with StringBuilder within core library classes
psandoz
parents: 14342
diff changeset
   206
                StringBuilder sb = new StringBuilder();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
                // myCipher[i] is a byte that indicates whether CIPHER_TOKENS[i]
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
                // is supported
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
                for (int i = 0; i < CIPHER_TOKENS.length; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
                    if (myCiphers[i] != 0) {
24969
afa6934dd8e8 8041679: Replace uses of StringBuffer with StringBuilder within core library classes
psandoz
parents: 14342
diff changeset
   212
                        if (sb.length() > 0) {
afa6934dd8e8 8041679: Replace uses of StringBuffer with StringBuilder within core library classes
psandoz
parents: 14342
diff changeset
   213
                            sb.append(',');
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
                        }
24969
afa6934dd8e8 8041679: Replace uses of StringBuffer with StringBuilder within core library classes
psandoz
parents: 14342
diff changeset
   215
                        sb.append(CIPHER_TOKENS[i]);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
                }
24969
afa6934dd8e8 8041679: Replace uses of StringBuffer with StringBuilder within core library classes
psandoz
parents: 14342
diff changeset
   218
                supportedCiphers = sb.toString();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
                challenge = generateChallenge(serverRealms, specifiedQops,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
                    supportedCiphers);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
                step = 3;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
                return challenge;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
            } catch (UnsupportedEncodingException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
                throw new SaslException(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
                    "DIGEST-MD5: Error encoding challenge", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
            } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
                throw new SaslException(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
                    "DIGEST-MD5: Error generating challenge", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
            // Step 2 is performed by client
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
        case 3:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
            /* Validates client's response and generate challenge:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
             *    response-auth = "rspauth" "=" response-value
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
                byte[][] responseVal = parseDirectives(response, DIRECTIVE_KEY,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
                    null, REALM);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
                challenge = validateClientResponse(responseVal);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
            } catch (SaslException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
                throw e;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
            } catch (UnsupportedEncodingException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
                throw new SaslException(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
                    "DIGEST-MD5: Error validating client response", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
            } finally {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
                step = 0;  // Set to invalid state
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
            completed = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
            /* Initialize SecurityCtx implementation */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
            if (integrity && privacy) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
                secCtx = new DigestPrivacy(false /* not client */);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
            } else if (integrity) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
                secCtx = new DigestIntegrity(false /* not client */);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
            return challenge;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
        default:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
            // No other possible state
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
            throw new SaslException("DIGEST-MD5: Server at illegal state");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
     * Generates challenge to be sent to client.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
     *  digest-challenge  =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
     *    1#( realm | nonce | qop-options | stale | maxbuf | charset
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
     *               algorithm | cipher-opts | auth-param )
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
     *        realm             = "realm" "=" <"> realm-value <">
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
     *        realm-value       = qdstr-val
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
     *        nonce             = "nonce" "=" <"> nonce-value <">
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
     *        nonce-value       = qdstr-val
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
     *        qop-options       = "qop" "=" <"> qop-list <">
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
     *        qop-list          = 1#qop-value
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
     *        qop-value         = "auth" | "auth-int" | "auth-conf" |
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
     *                             token
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
     *        stale             = "stale" "=" "true"
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
     *        maxbuf            = "maxbuf" "=" maxbuf-value
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
     *        maxbuf-value      = 1*DIGIT
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
     *        charset           = "charset" "=" "utf-8"
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
     *        algorithm         = "algorithm" "=" "md5-sess"
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
     *        cipher-opts       = "cipher" "=" <"> 1#cipher-value <">
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
     *        cipher-value      = "3des" | "des" | "rc4-40" | "rc4" |
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
     *                            "rc4-56" | token
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
     *        auth-param        = token "=" ( token | quoted-string )
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
    private byte[] generateChallenge(List<String> realms, String qopStr,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
        String cipherStr) throws UnsupportedEncodingException, IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
        ByteArrayOutputStream out = new ByteArrayOutputStream();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
        // Realms (>= 0)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
        for (int i = 0; realms != null && i < realms.size(); i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
            out.write("realm=\"".getBytes(encoding));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
            writeQuotedStringValue(out, realms.get(i).getBytes(encoding));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
            out.write('"');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
            out.write(',');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
        // Nonce - required (1)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
        out.write(("nonce=\"").getBytes(encoding));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
        nonce = generateNonce();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
        writeQuotedStringValue(out, nonce);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
        out.write('"');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
        out.write(',');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
        // QOP - optional (1) [default: auth]
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
        // qop="auth,auth-conf,auth-int"
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
        if (qopStr != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
            out.write(("qop=\"").getBytes(encoding));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
            // Check for quotes in case of non-standard qop options
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
            writeQuotedStringValue(out, qopStr.getBytes(encoding));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
            out.write('"');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
            out.write(',');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
        // maxbuf - optional (1) [default: 65536]
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
        if (recvMaxBufSize != DEFAULT_MAXBUF) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
            out.write(("maxbuf=\"" + recvMaxBufSize + "\",").getBytes(encoding));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
        // charset - optional (1) [default: ISO 8859_1]
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
        if (useUTF8) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
            out.write(UTF8_DIRECTIVE.getBytes(encoding));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
        if (cipherStr != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
            out.write("cipher=\"".getBytes(encoding));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
            // Check for quotes in case of custom ciphers
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
            writeQuotedStringValue(out, cipherStr.getBytes(encoding));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
            out.write('"');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
            out.write(',');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
        // algorithm - required (1)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
        out.write(ALGORITHM_DIRECTIVE.getBytes(encoding));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
        return out.toByteArray();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
     * Validates client's response.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
     *   digest-response  = 1#( username | realm | nonce | cnonce |
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
     *                          nonce-count | qop | digest-uri | response |
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
     *                          maxbuf | charset | cipher | authzid |
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
     *                          auth-param )
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
     *       username         = "username" "=" <"> username-value <">
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
     *       username-value   = qdstr-val
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
     *       cnonce           = "cnonce" "=" <"> cnonce-value <">
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
     *       cnonce-value     = qdstr-val
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
     *       nonce-count      = "nc" "=" nc-value
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
     *       nc-value         = 8LHEX
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
     *       qop              = "qop" "=" qop-value
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
     *       digest-uri       = "digest-uri" "=" <"> digest-uri-value <">
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
     *       digest-uri-value  = serv-type "/" host [ "/" serv-name ]
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
     *       serv-type        = 1*ALPHA
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
     *       host             = 1*( ALPHA | DIGIT | "-" | "." )
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
     *       serv-name        = host
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
     *       response         = "response" "=" response-value
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
     *       response-value   = 32LHEX
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
     *       LHEX             = "0" | "1" | "2" | "3" |
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
     *                          "4" | "5" | "6" | "7" |
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
     *                          "8" | "9" | "a" | "b" |
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
     *                          "c" | "d" | "e" | "f"
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
     *       cipher           = "cipher" "=" cipher-value
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
     *       authzid          = "authzid" "=" <"> authzid-value <">
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
     *       authzid-value    = qdstr-val
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
     * sets:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
     *   negotiatedQop
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
     *   negotiatedCipher
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
     *   negotiatedRealm
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
     *   negotiatedStrength
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
     *   digestUri (checked and set to clients to account for case diffs)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
     *   sendMaxBufSize
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
     *   authzid (gotten from callback)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
     * @return response-value ('rspauth') for client to validate
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
    private byte[] validateClientResponse(byte[][] responseVal)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
        throws SaslException, UnsupportedEncodingException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
        /* CHARSET: optional atmost once */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
        if (responseVal[CHARSET] != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
            // The client should send this directive only if the server has
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
            // indicated it supports UTF-8.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
            if (!useUTF8 ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
                !"utf-8".equals(new String(responseVal[CHARSET], encoding))) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
                throw new SaslException("DIGEST-MD5: digest response format " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
                    "violation. Incompatible charset value: " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
                    new String(responseVal[CHARSET]));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
        // maxbuf: atmost once
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
        int clntMaxBufSize =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
            (responseVal[MAXBUF] == null) ? DEFAULT_MAXBUF
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
            : Integer.parseInt(new String(responseVal[MAXBUF], encoding));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
        // Max send buf size is min of client's max recv buf size and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
        // server's max send buf size
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
        sendMaxBufSize = ((sendMaxBufSize == 0) ? clntMaxBufSize :
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
            Math.min(sendMaxBufSize, clntMaxBufSize));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
        /* username: exactly once */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
        String username;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
        if (responseVal[USERNAME] != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
            username = new String(responseVal[USERNAME], encoding);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
            logger.log(Level.FINE, "DIGEST82:Username: {0}", username);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
            throw new SaslException("DIGEST-MD5: digest response format " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
                "violation. Missing username.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
        /* realm: exactly once if sent by server */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
        negotiatedRealm = ((responseVal[REALM] != null) ?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
            new String(responseVal[REALM], encoding) : "");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
        logger.log(Level.FINE, "DIGEST83:Client negotiated realm: {0}",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
            negotiatedRealm);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
        if (!serverRealms.contains(negotiatedRealm)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
            // Server had sent at least one realm
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
            // Check that response is one of these
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
            throw new SaslException("DIGEST-MD5: digest response format " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
                "violation. Nonexistent realm: " + negotiatedRealm);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
        // Else, client specified realm was one of server's or server had none
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
        /* nonce: exactly once */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
        if (responseVal[NONCE] == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
            throw new SaslException("DIGEST-MD5: digest response format " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
                "violation. Missing nonce.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
        byte[] nonceFromClient = responseVal[NONCE];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
        if (!Arrays.equals(nonceFromClient, nonce)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
            throw new SaslException("DIGEST-MD5: digest response format " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
                "violation. Mismatched nonce.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
        /* cnonce: exactly once */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
        if (responseVal[CNONCE] == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
            throw new SaslException("DIGEST-MD5: digest response format " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
                "violation. Missing cnonce.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
        byte[] cnonce = responseVal[CNONCE];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
        /* nonce-count: atmost once */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
        if (responseVal[NONCE_COUNT] != null &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
            NONCE_COUNT_VALUE != Integer.parseInt(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
                new String(responseVal[NONCE_COUNT], encoding), 16)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
            throw new SaslException("DIGEST-MD5: digest response format " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
                "violation. Nonce count does not match: " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
                new String(responseVal[NONCE_COUNT]));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
        /* qop: atmost once; default is "auth" */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
        negotiatedQop = ((responseVal[QOP] != null) ?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
            new String(responseVal[QOP], encoding) : "auth");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
        logger.log(Level.FINE, "DIGEST84:Client negotiated qop: {0}",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
            negotiatedQop);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
        // Check that QOP is one sent by server
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
        byte cQop;
10336
0bb1999251f8 7064075: Security libraries don't build with javac -Xlint:all,-deprecation -Werror
jjg
parents: 5506
diff changeset
   471
        switch (negotiatedQop) {
0bb1999251f8 7064075: Security libraries don't build with javac -Xlint:all,-deprecation -Werror
jjg
parents: 5506
diff changeset
   472
            case "auth":
0bb1999251f8 7064075: Security libraries don't build with javac -Xlint:all,-deprecation -Werror
jjg
parents: 5506
diff changeset
   473
                cQop = NO_PROTECTION;
0bb1999251f8 7064075: Security libraries don't build with javac -Xlint:all,-deprecation -Werror
jjg
parents: 5506
diff changeset
   474
                break;
0bb1999251f8 7064075: Security libraries don't build with javac -Xlint:all,-deprecation -Werror
jjg
parents: 5506
diff changeset
   475
            case "auth-int":
0bb1999251f8 7064075: Security libraries don't build with javac -Xlint:all,-deprecation -Werror
jjg
parents: 5506
diff changeset
   476
                cQop = INTEGRITY_ONLY_PROTECTION;
0bb1999251f8 7064075: Security libraries don't build with javac -Xlint:all,-deprecation -Werror
jjg
parents: 5506
diff changeset
   477
                integrity = true;
0bb1999251f8 7064075: Security libraries don't build with javac -Xlint:all,-deprecation -Werror
jjg
parents: 5506
diff changeset
   478
                rawSendSize = sendMaxBufSize - 16;
0bb1999251f8 7064075: Security libraries don't build with javac -Xlint:all,-deprecation -Werror
jjg
parents: 5506
diff changeset
   479
                break;
0bb1999251f8 7064075: Security libraries don't build with javac -Xlint:all,-deprecation -Werror
jjg
parents: 5506
diff changeset
   480
            case "auth-conf":
0bb1999251f8 7064075: Security libraries don't build with javac -Xlint:all,-deprecation -Werror
jjg
parents: 5506
diff changeset
   481
                cQop = PRIVACY_PROTECTION;
0bb1999251f8 7064075: Security libraries don't build with javac -Xlint:all,-deprecation -Werror
jjg
parents: 5506
diff changeset
   482
                integrity = privacy = true;
0bb1999251f8 7064075: Security libraries don't build with javac -Xlint:all,-deprecation -Werror
jjg
parents: 5506
diff changeset
   483
                rawSendSize = sendMaxBufSize - 26;
0bb1999251f8 7064075: Security libraries don't build with javac -Xlint:all,-deprecation -Werror
jjg
parents: 5506
diff changeset
   484
                break;
0bb1999251f8 7064075: Security libraries don't build with javac -Xlint:all,-deprecation -Werror
jjg
parents: 5506
diff changeset
   485
            default:
0bb1999251f8 7064075: Security libraries don't build with javac -Xlint:all,-deprecation -Werror
jjg
parents: 5506
diff changeset
   486
                throw new SaslException("DIGEST-MD5: digest response format " +
0bb1999251f8 7064075: Security libraries don't build with javac -Xlint:all,-deprecation -Werror
jjg
parents: 5506
diff changeset
   487
                    "violation. Invalid QOP: " + negotiatedQop);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
        if ((cQop&allQop) == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
            throw new SaslException("DIGEST-MD5: server does not support " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
                " qop: " + negotiatedQop);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
        if (privacy) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
            negotiatedCipher = ((responseVal[CIPHER] != null) ?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
                new String(responseVal[CIPHER], encoding) : null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
            if (negotiatedCipher == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
                throw new SaslException("DIGEST-MD5: digest response format " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
                    "violation. No cipher specified.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
            int foundCipher = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
            logger.log(Level.FINE, "DIGEST85:Client negotiated cipher: {0}",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
                negotiatedCipher);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
            // Check that cipher is one that we offered
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
            for (int j = 0; j < CIPHER_TOKENS.length; j++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
                if (negotiatedCipher.equals(CIPHER_TOKENS[j]) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
                    myCiphers[j] != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
                    foundCipher = j;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
            if (foundCipher == -1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
                throw new SaslException("DIGEST-MD5: server does not " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
                    "support cipher: " + negotiatedCipher);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
            // Set negotiatedStrength
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
            if ((CIPHER_MASKS[foundCipher]&HIGH_STRENGTH) != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
                negotiatedStrength = "high";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
            } else if ((CIPHER_MASKS[foundCipher]&MEDIUM_STRENGTH) != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
                negotiatedStrength = "medium";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
                // assume default low
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
                negotiatedStrength = "low";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
            logger.log(Level.FINE, "DIGEST86:Negotiated strength: {0}",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
                negotiatedStrength);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
        // atmost once
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
        String digestUriFromResponse = ((responseVal[DIGEST_URI]) != null ?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
            new String(responseVal[DIGEST_URI], encoding) : null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
90ce3da70b43 Initial load
duke
parents:
diff changeset
   536
        if (digestUriFromResponse != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
            logger.log(Level.FINE, "DIGEST87:digest URI: {0}",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   538
                digestUriFromResponse);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   540
90ce3da70b43 Initial load
duke
parents:
diff changeset
   541
        // serv-type "/" host [ "/" serv-name ]
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
        // e.g.: smtp/mail3.example.com/example.com
90ce3da70b43 Initial load
duke
parents:
diff changeset
   543
        // e.g.: ftp/ftp.example.com
90ce3da70b43 Initial load
duke
parents:
diff changeset
   544
        // e.g.: ldap/ldapserver.example.com
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
        // host should match one of service's configured service names
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
        // Check against digest URI that mech was created with
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
14340
e150cbaf584e 7110803: SASL service for multiple hostnames
weijun
parents: 10336
diff changeset
   549
        if (uriMatches(digestUri, digestUriFromResponse)) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
            digestUri = digestUriFromResponse; // account for case-sensitive diffs
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
            throw new SaslException("DIGEST-MD5: digest response format " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
                "violation. Mismatched URI: " + digestUriFromResponse +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
                "; expecting: " + digestUri);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
        // response: exactly once
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
        byte[] responseFromClient = responseVal[RESPONSE];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
        if (responseFromClient == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   560
            throw new SaslException("DIGEST-MD5: digest response format " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   561
                " violation. Missing response.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   562
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   563
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
        // authzid: atmost once
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
        byte[] authzidBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
        String authzidFromClient = ((authzidBytes=responseVal[AUTHZID]) != null?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   567
            new String(authzidBytes, encoding) : username);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   568
90ce3da70b43 Initial load
duke
parents:
diff changeset
   569
        if (authzidBytes != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
            logger.log(Level.FINE, "DIGEST88:Authzid: {0}",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
                new String(authzidBytes));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
        // Ignore auth-param
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
        // Get password need to generate verifying response
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
        char[] passwd;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
            // Realm and Name callbacks are used to provide info
90ce3da70b43 Initial load
duke
parents:
diff changeset
   580
            RealmCallback rcb = new RealmCallback("DIGEST-MD5 realm: ",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
                negotiatedRealm);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
            NameCallback ncb = new NameCallback("DIGEST-MD5 authentication ID: ",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
                username);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
            // PasswordCallback is used to collect info
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
            PasswordCallback pcb =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
                new PasswordCallback("DIGEST-MD5 password: ", false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
            cbh.handle(new Callback[] {rcb, ncb, pcb});
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
            passwd = pcb.getPassword();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
            pcb.clearPassword();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
        } catch (UnsupportedCallbackException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
            throw new SaslException(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   595
                "DIGEST-MD5: Cannot perform callback to acquire password", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   596
90ce3da70b43 Initial load
duke
parents:
diff changeset
   597
        } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   598
            throw new SaslException(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
                "DIGEST-MD5: IO error acquiring password", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   600
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
90ce3da70b43 Initial load
duke
parents:
diff changeset
   602
        if (passwd == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
            throw new SaslException(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
                "DIGEST-MD5: cannot acquire password for " + username +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
                " in realm : " + negotiatedRealm);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   606
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   607
90ce3da70b43 Initial load
duke
parents:
diff changeset
   608
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   609
            // Validate response value sent by client
90ce3da70b43 Initial load
duke
parents:
diff changeset
   610
            byte[] expectedResponse;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   611
90ce3da70b43 Initial load
duke
parents:
diff changeset
   612
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
                expectedResponse = generateResponseValue("AUTHENTICATE",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   614
                    digestUri, negotiatedQop, username, negotiatedRealm,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   615
                    passwd, nonce /* use own nonce */,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
                    cnonce, NONCE_COUNT_VALUE, authzidBytes);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   617
90ce3da70b43 Initial load
duke
parents:
diff changeset
   618
            } catch (NoSuchAlgorithmException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   619
                throw new SaslException(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
                    "DIGEST-MD5: problem duplicating client response", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   621
            } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
                throw new SaslException(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   623
                    "DIGEST-MD5: problem duplicating client response", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   624
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   625
90ce3da70b43 Initial load
duke
parents:
diff changeset
   626
            if (!Arrays.equals(responseFromClient, expectedResponse)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   627
                throw new SaslException("DIGEST-MD5: digest response format " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   628
                    "violation. Mismatched response.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   629
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   630
90ce3da70b43 Initial load
duke
parents:
diff changeset
   631
            // Ensure that authzid mapping is OK
90ce3da70b43 Initial load
duke
parents:
diff changeset
   632
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   633
                AuthorizeCallback acb =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   634
                    new AuthorizeCallback(username, authzidFromClient);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   635
                cbh.handle(new Callback[]{acb});
90ce3da70b43 Initial load
duke
parents:
diff changeset
   636
90ce3da70b43 Initial load
duke
parents:
diff changeset
   637
                if (acb.isAuthorized()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   638
                    authzid = acb.getAuthorizedID();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   639
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   640
                    throw new SaslException("DIGEST-MD5: " + username +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   641
                        " is not authorized to act as " + authzidFromClient);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   642
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   643
            } catch (SaslException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   644
                throw e;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   645
            } catch (UnsupportedCallbackException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   646
                throw new SaslException(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   647
                    "DIGEST-MD5: Cannot perform callback to check authzid", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   648
            } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   649
                throw new SaslException(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   650
                    "DIGEST-MD5: IO error checking authzid", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   651
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   652
90ce3da70b43 Initial load
duke
parents:
diff changeset
   653
            return generateResponseAuth(username, passwd, cnonce,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   654
                NONCE_COUNT_VALUE, authzidBytes);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   655
        } finally {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   656
            // Clear password
90ce3da70b43 Initial load
duke
parents:
diff changeset
   657
            for (int i = 0; i < passwd.length; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   658
                passwd[i] = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   659
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   660
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   661
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   662
14340
e150cbaf584e 7110803: SASL service for multiple hostnames
weijun
parents: 10336
diff changeset
   663
    private static boolean uriMatches(String thisUri, String incomingUri) {
e150cbaf584e 7110803: SASL service for multiple hostnames
weijun
parents: 10336
diff changeset
   664
        // Full match
e150cbaf584e 7110803: SASL service for multiple hostnames
weijun
parents: 10336
diff changeset
   665
        if (thisUri.equalsIgnoreCase(incomingUri)) {
e150cbaf584e 7110803: SASL service for multiple hostnames
weijun
parents: 10336
diff changeset
   666
            return true;
e150cbaf584e 7110803: SASL service for multiple hostnames
weijun
parents: 10336
diff changeset
   667
        }
e150cbaf584e 7110803: SASL service for multiple hostnames
weijun
parents: 10336
diff changeset
   668
        // Unbound match
e150cbaf584e 7110803: SASL service for multiple hostnames
weijun
parents: 10336
diff changeset
   669
        if (thisUri.endsWith("/*")) {
e150cbaf584e 7110803: SASL service for multiple hostnames
weijun
parents: 10336
diff changeset
   670
            int protoAndSlash = thisUri.length() - 1;
e150cbaf584e 7110803: SASL service for multiple hostnames
weijun
parents: 10336
diff changeset
   671
            String thisProtoAndSlash = thisUri.substring(0, protoAndSlash);
e150cbaf584e 7110803: SASL service for multiple hostnames
weijun
parents: 10336
diff changeset
   672
            String incomingProtoAndSlash = incomingUri.substring(0, protoAndSlash);
e150cbaf584e 7110803: SASL service for multiple hostnames
weijun
parents: 10336
diff changeset
   673
            return thisProtoAndSlash.equalsIgnoreCase(incomingProtoAndSlash);
e150cbaf584e 7110803: SASL service for multiple hostnames
weijun
parents: 10336
diff changeset
   674
        }
e150cbaf584e 7110803: SASL service for multiple hostnames
weijun
parents: 10336
diff changeset
   675
        return false;
e150cbaf584e 7110803: SASL service for multiple hostnames
weijun
parents: 10336
diff changeset
   676
    }
e150cbaf584e 7110803: SASL service for multiple hostnames
weijun
parents: 10336
diff changeset
   677
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   678
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   679
     * Server sends a message formatted as follows:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   680
     *    response-auth = "rspauth" "=" response-value
90ce3da70b43 Initial load
duke
parents:
diff changeset
   681
     *   where response-value is calculated as above, using the values sent in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   682
     *   step two, except that if qop is "auth", then A2 is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   683
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   684
     *       A2 = { ":", digest-uri-value }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   685
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   686
     *   And if qop is "auth-int" or "auth-conf" then A2 is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   687
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   688
     *       A2 = { ":", digest-uri-value, ":00000000000000000000000000000000" }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   689
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   690
     * Clears password afterwards.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   691
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   692
    private byte[] generateResponseAuth(String username, char[] passwd,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   693
        byte[] cnonce, int nonceCount, byte[] authzidBytes) throws SaslException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   694
90ce3da70b43 Initial load
duke
parents:
diff changeset
   695
        // Construct response value
90ce3da70b43 Initial load
duke
parents:
diff changeset
   696
90ce3da70b43 Initial load
duke
parents:
diff changeset
   697
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   698
            byte[] responseValue = generateResponseValue("",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   699
                digestUri, negotiatedQop, username, negotiatedRealm,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   700
                passwd, nonce, cnonce, nonceCount, authzidBytes);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   701
90ce3da70b43 Initial load
duke
parents:
diff changeset
   702
            byte[] challenge = new byte[responseValue.length + 8];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   703
            System.arraycopy("rspauth=".getBytes(encoding), 0, challenge, 0, 8);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   704
            System.arraycopy(responseValue, 0, challenge, 8,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   705
                responseValue.length );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   706
90ce3da70b43 Initial load
duke
parents:
diff changeset
   707
            return challenge;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   708
90ce3da70b43 Initial load
duke
parents:
diff changeset
   709
        } catch (NoSuchAlgorithmException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   710
            throw new SaslException("DIGEST-MD5: problem generating response", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   711
        } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   712
            throw new SaslException("DIGEST-MD5: problem generating response", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   713
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   714
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   715
90ce3da70b43 Initial load
duke
parents:
diff changeset
   716
    public String getAuthorizationID() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   717
        if (completed) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   718
            return authzid;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   719
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   720
            throw new IllegalStateException(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   721
                "DIGEST-MD5 server negotiation not complete");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   722
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   723
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   724
}