changeset 5606:6176777d2b97

7200720: crash in net.dll during NTLM authentication Reviewed-by: chegar, weijun
author michaelm
date Wed, 21 Nov 2012 21:20:39 +0000
parents a91ac65b5e2f
children ff3d02c43a1c
files make/java/net/Makefile src/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthSequence.java src/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java src/windows/native/sun/net/www/protocol/http/ntlm/NTLMAuthSequence.c
diffstat 4 files changed, 49 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/make/java/net/Makefile	Wed Jul 13 12:24:56 2011 +0100
+++ b/make/java/net/Makefile	Wed Nov 21 21:20:39 2012 +0000
@@ -74,6 +74,7 @@
     FILES_export += java/net/DualStackPlainSocketImpl.java
     FILES_export += java/net/TwoStacksPlainDatagramSocketImpl.java
     FILES_export += java/net/DualStackPlainDatagramSocketImpl.java
+    FILES_export += sun/net/www/protocol/http/ntlm/NTLMAuthSequence.java
 else
     FILES_export += java/net/PlainDatagramSocketImpl.java
 endif
--- a/src/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthSequence.java	Wed Jul 13 12:24:56 2011 +0100
+++ b/src/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthSequence.java	Wed Nov 21 21:20:39 2012 +0000
@@ -45,15 +45,25 @@
     private long ctxHandle;
 
     static {
-        initFirst();
+        initFirst(Status.class);
     }
 
+    // Used by native code to indicate when a particular protocol sequence is completed
+    // and must not be re-used.
+
+    class Status {
+        boolean sequenceComplete;
+    }
+
+    Status status;
+
     NTLMAuthSequence (String username, String password, String ntdomain)
     throws IOException
     {
         this.username = username;
         this.password = password;
         this.ntdomain = ntdomain;
+        this.status = new Status();
         state = 0;
         crdHandle = getCredentialsHandle (username, ntdomain, password);
         if (crdHandle == 0) {
@@ -63,19 +73,26 @@
 
     public String getAuthHeader (String token) throws IOException {
         byte[] input = null;
+
+        assert !status.sequenceComplete;
+
         if (token != null)
             input = (new BASE64Decoder()).decodeBuffer(token);
-        byte[] b = getNextToken (crdHandle, input);
+        byte[] b = getNextToken (crdHandle, input, status);
         if (b == null)
             throw new IOException ("Internal authentication error");
         return (new B64Encoder()).encode (b);
     }
 
-    private native static void initFirst ();
+    public boolean isComplete() {
+        return status.sequenceComplete;
+    }
+
+    private native static void initFirst (Class<NTLMAuthSequence.Status> clazz);
 
     private native long getCredentialsHandle (String user, String domain, String password);
 
-    private native byte[] getNextToken (long crdHandle, byte[] lastToken);
+    private native byte[] getNextToken (long crdHandle, byte[] lastToken, Status returned);
 }
 
 class B64Encoder extends BASE64Encoder {
--- a/src/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java	Wed Jul 13 12:24:56 2011 +0100
+++ b/src/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java	Wed Nov 21 21:20:39 2012 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -186,6 +186,7 @@
     public synchronized boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) {
 
         try {
+
             NTLMAuthSequence seq = (NTLMAuthSequence)conn.authObj();
             if (seq == null) {
                 seq = new NTLMAuthSequence (username, password, ntdomain);
@@ -193,8 +194,12 @@
             }
             String response = "NTLM " + seq.getAuthHeader (raw.length()>6?raw.substring(5):null);
             conn.setAuthenticationProperty(getHeaderName(), response);
+            if (seq.isComplete()) { // 7200720
+                conn.authObj(null);
+            }
             return true;
         } catch (IOException e) {
+            conn.authObj(null); // MMM 7200720 ??
             return false;
         }
     }
--- a/src/windows/native/sun/net/www/protocol/http/ntlm/NTLMAuthSequence.c	Wed Jul 13 12:24:56 2011 +0100
+++ b/src/windows/native/sun/net/www/protocol/http/ntlm/NTLMAuthSequence.c	Wed Nov 21 21:20:39 2012 +0000
@@ -41,18 +41,20 @@
 #define SECURITY_WIN32
 #include "sspi.h"
 
-static void endSequence (PCredHandle credHand, PCtxtHandle ctxHandle);
+static void endSequence (PCredHandle credHand, PCtxtHandle ctxHandle, JNIEnv *env, jobject status);
 
 static jfieldID ntlm_ctxHandleID;
 static jfieldID ntlm_crdHandleID;
+static jfieldID status_seqCompleteID;
 
 static HINSTANCE lib = NULL;
 
 JNIEXPORT void JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthSequence_initFirst
-(JNIEnv *env, jclass clazz)
+(JNIEnv *env, jclass authseq_clazz, jclass status_clazz)
 {
-    ntlm_ctxHandleID = (*env)->GetFieldID(env, clazz, "ctxHandle", "J");
-    ntlm_crdHandleID = (*env)->GetFieldID(env, clazz, "crdHandle", "J");
+    ntlm_ctxHandleID = (*env)->GetFieldID(env, authseq_clazz, "ctxHandle", "J");
+    ntlm_crdHandleID = (*env)->GetFieldID(env, authseq_clazz, "crdHandle", "J");
+    status_seqCompleteID = (*env)->GetFieldID(env, status_clazz, "sequenceComplete", "Z");
 }
 
 /*
@@ -145,8 +147,14 @@
     }
 }
 
+
+/*
+ * Class:     sun_net_www_protocol_http_ntlm_NTLMAuthSequence
+ * Method:    getNextToken
+ * Signature: (J[BLsun/net/www/protocol/http/ntlm/NTLMAuthSequence/Status;)[B
+ */
 JNIEXPORT jbyteArray JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthSequence_getNextToken
-(JNIEnv *env, jobject this, jlong crdHandle, jbyteArray lastToken)
+(JNIEnv *env, jobject this, jlong crdHandle, jbyteArray lastToken, jobject status)
 {
 
     VOID        *pInput = 0;
@@ -217,7 +225,7 @@
     }
 
     if (ss < 0) {
-        endSequence (pCred, pCtx);
+        endSequence (pCred, pCtx, env, status);
         return 0;
     }
 
@@ -225,7 +233,7 @@
         ss = CompleteAuthToken( pCtx, &OutBuffDesc );
 
         if (ss < 0) {
-            endSequence (pCred, pCtx);
+            endSequence (pCred, pCtx, env, status);
             return 0;
         }
     }
@@ -235,18 +243,18 @@
         (*env)->SetByteArrayRegion(env, ret, 0, OutSecBuff.cbBuffer,
                 OutSecBuff.pvBuffer);
         if (lastToken != 0) // 2nd stage
-            endSequence (pCred, pCtx);
+            endSequence (pCred, pCtx, env, status);
         result = ret;
     }
 
     if ((ss != SEC_I_CONTINUE_NEEDED) && (ss == SEC_I_COMPLETE_AND_CONTINUE)) {
-        endSequence (pCred, pCtx);
+        endSequence (pCred, pCtx, env, status);
     }
 
     return result;
 }
 
-static void endSequence (PCredHandle credHand, PCtxtHandle ctxHandle) {
+static void endSequence (PCredHandle credHand, PCtxtHandle ctxHandle, JNIEnv *env, jobject status) {
     if (credHand != 0) {
         FreeCredentialsHandle(credHand);
         free(credHand);
@@ -256,4 +264,7 @@
         DeleteSecurityContext(ctxHandle);
         free(ctxHandle);
     }
+
+    /* Sequence is complete so set flag */
+    (*env)->SetBooleanField(env, status, status_seqCompleteID, JNI_TRUE);
 }