/**
 * Licensed to Jasig under one or more contributor license
 * agreements. See the NOTICE file distributed with this work
 * for additional information regarding copyright ownership.
 * Jasig licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a
 * copy of the License at:
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.jasig.portlet.calendar.adapter.exchange;

import java.io.IOException;

import jcifs.ntlmssp.NtlmFlags;
import jcifs.ntlmssp.Type1Message;
import jcifs.ntlmssp.Type2Message;
import jcifs.ntlmssp.Type3Message;
import jcifs.util.Base64;

import org.apache.http.impl.auth.NTLMEngine;
import org.apache.http.impl.auth.NTLMEngineException;

public final class JCIFSEngine implements NTLMEngine {

    private static final int TYPE_1_FLAGS = 
            NtlmFlags.NTLMSSP_NEGOTIATE_56 | 
            NtlmFlags.NTLMSSP_NEGOTIATE_128 | 
            NtlmFlags.NTLMSSP_NEGOTIATE_NTLM2 | 
            NtlmFlags.NTLMSSP_NEGOTIATE_ALWAYS_SIGN | 
            NtlmFlags.NTLMSSP_REQUEST_TARGET;

    public String generateType1Msg(final String domain, final String workstation)
            throws NTLMEngineException {
        final Type1Message type1Message = new Type1Message(TYPE_1_FLAGS, domain, workstation);
        return Base64.encode(type1Message.toByteArray());
    }

    public String generateType3Msg(final String username, final String password,
            final String domain, final String workstation, final String challenge)
            throws NTLMEngineException {
        Type2Message type2Message;
        try {
            type2Message = new Type2Message(Base64.decode(challenge));
        } catch (final IOException exception) {
            throw new NTLMEngineException("Invalid NTLM type 2 message", exception);
        }
        final int type2Flags = type2Message.getFlags();
        final int type3Flags = type2Flags
                & (0xffffffff ^ (NtlmFlags.NTLMSSP_TARGET_TYPE_DOMAIN | NtlmFlags.NTLMSSP_TARGET_TYPE_SERVER));
        final Type3Message type3Message = new Type3Message(type2Message, password, domain,
                username, workstation, type3Flags);
        return Base64.encode(type3Message.toByteArray());
    }

}

@@ -1012,16 +1012,101 @@
 ase64;%0A%0A
+import org.apache.commons.logging.Log;%0Aimport org.apache.commons.logging.LogFactory;%0A
 import o
@@ -1542,16 +1542,81 @@
 ARGET;%0A%0A
+    private final Log log = LogFactory.getLog(this.getClass());%0A%0A
     publ
@@ -1688,28 +1688,16 @@
 station)
-%0A           
  throws 
@@ -1710,32 +1710,242 @@
 gineException %7B%0A
+        %0A        if (log.isDebugEnabled()) %7B%0A            log.debug(%22Generating NTLM Type 1 message;  domain=%22 + domain %0A                                    + %22, workstation=%22 + workstation);%0A        %7D%0A        %0A
         final Ty
@@ -2284,32 +2284,359 @@
 ngineException %7B
+%0A%0A        if (log.isDebugEnabled()) %7B%0A            log.debug(%22Generating NTLM Type 3 message;  username=%22 + username %0A                    + %22, password.length=%22 + password.length() + %22, domain=%22 %0A                    + domain + %22, workstation=%22 + workstation %0A                    + %22, challenge=%22 + challenge);%0A        %7D%0A        
 %0A        Type2Me

Add some log messages that should be helpful in occasionally troubleshooting NTLM (or other) authentication with Exchange WS