All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.kerb4j.server.SpnegoTokenFixer Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF 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 com.kerb4j.server;

import java.util.LinkedHashMap;

/**
 * This class implements a hack around an incompatibility between the
 * SPNEGO implementation in Windows and the SPNEGO implementation in Java 8
 * update 40 onwards. It was introduced by the change to fix this bug:
 * https://bugs.openjdk.java.net/browse/JDK-8048194
 * (note: the change applied is not the one suggested in the bug report)
 * 

* It is not clear to me if Windows, Java or Tomcat is at fault here. I * think it is Java but I could be wrong. *

* This hack works by re-ordering the list of mechTypes in the NegTokenInit * token. */ public class SpnegoTokenFixer { public static void fix(byte[] token) { SpnegoTokenFixer fixer = new SpnegoTokenFixer(token); fixer.fix(); } private final byte[] token; private int pos = 0; private SpnegoTokenFixer(byte[] token) { this.token = token; } // Fixes the token in-place private void fix() { /* * Useful references: * http://tools.ietf.org/html/rfc4121#page-5 * http://tools.ietf.org/html/rfc2743#page-81 * https://msdn.microsoft.com/en-us/library/ms995330.aspx */ // Scan until we find the mech types list. If we find anything // unexpected, abort the fix process. if (!tag(0x60)) return; if (!length()) return; if (!oid("1.3.6.1.5.5.2")) return; if (!tag(0xa0)) return; if (!length()) return; if (!tag(0x30)) return; if (!length()) return; if (!tag(0xa0)) return; lengthAsInt(); if (!tag(0x30)) return; // Now at the start of the mechType list. // Read the mechTypes into an ordered set int mechTypesLen = lengthAsInt(); int mechTypesStart = pos; LinkedHashMap mechTypeEntries = new LinkedHashMap<>(); while (pos < mechTypesStart + mechTypesLen) { int[] value = new int[2]; value[0] = pos; String key = oidAsString(); value[1] = pos - value[0]; mechTypeEntries.put(key, value); } // Now construct the re-ordered mechType list byte[] replacement = new byte[mechTypesLen]; int replacementPos = 0; int[] first = mechTypeEntries.remove("1.2.840.113554.1.2.2"); if (first != null) { System.arraycopy(token, first[0], replacement, replacementPos, first[1]); replacementPos += first[1]; } for (int[] markers : mechTypeEntries.values()) { System.arraycopy(token, markers[0], replacement, replacementPos, markers[1]); replacementPos += markers[1]; } // Finally, replace the original mechType list with the re-ordered // one. System.arraycopy(replacement, 0, token, mechTypesStart, mechTypesLen); } private boolean tag(int expected) { return (token[pos++] & 0xFF) == expected; } private boolean length() { // No need to retain the length - just need to consume it and make // sure it is valid. int len = lengthAsInt(); return pos + len == token.length; } private int lengthAsInt() { int len = token[pos++] & 0xFF; if (len > 127) { int bytes = len - 128; len = 0; for (int i = 0; i < bytes; i++) { len = len << 8; len = len + (token[pos++] & 0xff); } } return len; } private boolean oid(String expected) { return expected.equals(oidAsString()); } private String oidAsString() { if (!tag(0x06)) return null; StringBuilder result = new StringBuilder(); int len = lengthAsInt(); // First byte is special case int v = token[pos++] & 0xFF; int c2 = v % 40; int c1 = (v - c2) / 40; result.append(c1); result.append('.'); result.append(c2); int c = 0; boolean write = false; for (int i = 1; i < len; i++) { int b = token[pos++] & 0xFF; if (b > 127) { b -= 128; } else { write = true; } c = c << 7; c += b; if (write) { result.append('.'); result.append(c); c = 0; write = false; } } return result.toString(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy