History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/com/sun/security/ntlm/Server.java (1 of 18352 files). Show all

Unified · Split

java/pkg/com/sun/security/ntlm/Server.java+205−0
@@ -0,0 +1,205 @@
1+/*
2+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package com.sun.security.ntlm;
27+
28+import java.util.Arrays;
29+import java.util.Locale;
30+
31+/**
32+ * The NTLM server, not multi-thread enabled.<p>
33+ * Example:
34+ * <pre>
35+ * Server server = new Server(null, "REALM") {
36+ * public char[] getPassword(String ntdomain, String username) {
37+ * switch (username) {
38+ * case "dummy": return "t0pSeCr3t".toCharArray();
39+ * case "guest": return "".toCharArray();
40+ * default: return null;
41+ * }
42+ * }
43+ * };
44+ * // Receive client request as type1
45+ * byte[] type2 = server.type2(type1, nonce);
46+ * // Send type2 to client and receive type3
47+ * verify(type3, nonce);
48+ * </pre>
49+ */
50+public abstract class Server extends NTLM {
51+ final private String domain;
52+ final private boolean allVersion;
53+ /**
54+ * Creates a Server instance.
55+ * @param version the NTLM version to use, which can be:
56+ * <ul>
57+ * <li>NTLM: Original NTLM v1
58+ * <li>NTLM2: NTLM v1 with Client Challenge
59+ * <li>NTLMv2: NTLM v2
60+ * </ul>
61+ * If null, all versions will be supported. Please note that unless NTLM2
62+ * is selected, authentication succeeds if one of LM (or LMv2) or
63+ * NTLM (or NTLMv2) is verified.
64+ * @param domain the domain, must not be null
65+ * @throws NullPointerException if {@code domain} is null.
66+ */
67+ public Server(String version, String domain) throws NTLMException {
68+ super(version);
69+ if (domain == null) {
70+ throw new NullPointerException("domain cannot be null");
71+ }
72+ this.allVersion = (version == null);
73+ this.domain = domain;
74+ debug("NTLM Server: (t,version) = (%s,%s)\n", domain, version);
75+ }
76+
77+ /**
78+ * Generates the Type 2 message
79+ * @param type1 the Type1 message received, must not be null
80+ * @param nonce the random 8-byte array to be used in message generation,
81+ * must not be null
82+ * @return the message generated
83+ * @throws NullPointerException if type1 or nonce is null
84+ * @throws NTLMException if the incoming message is invalid
85+ */
86+ public byte[] type2(byte[] type1, byte[] nonce) {
87+ if (nonce == null) {
88+ throw new NullPointerException("nonce cannot be null");
89+ }
90+ debug("NTLM Server: Type 1 received\n");
91+ if (type1 != null) debug(type1);
92+ Writer p = new Writer(2, 32);
93+ int flags = 0x80205;
94+ p.writeSecurityBuffer(12, domain, true);
95+ p.writeInt(20, flags);
96+ p.writeBytes(24, nonce);
97+ debug("NTLM Server: Type 2 created\n");
98+ debug(p.getBytes());
99+ return p.getBytes();
100+ }
101+
102+ /**
103+ * Verifies the Type3 message received from client and returns
104+ * various negotiated information.
105+ * @param type3 the incoming Type3 message from client, must not be null
106+ * @param nonce the same nonce provided in {@link #type2}, must not be null
107+ * @return username and hostname of the client in a byte array
108+ * @throws NullPointerException if {@code type3} or {@code nonce} is null
109+ * @throws NTLMException if the incoming message is invalid
110+ */
111+ public String[] verify(byte[] type3, byte[] nonce)
112+ throws NTLMException {
113+ if (type3 == null || nonce == null) {
114+ throw new NullPointerException("type1 or nonce cannot be null");
115+ }
116+ debug("NTLM Server: Type 3 received\n");
117+ if (type3 != null) debug(type3);
118+ Reader r = new Reader(type3);
119+ String username = r.readSecurityBuffer(36, true);
120+ String hostname = r.readSecurityBuffer(44, true);
121+ String incomingDomain = r.readSecurityBuffer(28, true);
122+ /*if (incomingDomain != null && !incomingDomain.equals(domain)) {
123+ throw new NTLMException(NTLMException.DOMAIN_UNMATCH,
124+ "Wrong domain: " + incomingDomain +
125+ " vs " + domain); // Needed?
126+ }*/
127+ boolean verified = false;
128+ char[] password = getPassword(domain, username);
129+ if (password == null) {
130+ throw new NTLMException(NTLMException.USER_UNKNOWN,
131+ "Unknown user");
132+ }
133+ byte[] incomingLM = r.readSecurityBuffer(12);
134+ byte[] incomingNTLM = r.readSecurityBuffer(20);
135+
136+ if (!verified && (allVersion || v == Version.NTLM)) {
137+ if (incomingLM.length > 0) {
138+ byte[] pw1 = getP1(password);
139+ byte[] lmhash = calcLMHash(pw1);
140+ byte[] lmresponse = calcResponse (lmhash, nonce);
141+ if (Arrays.equals(lmresponse, incomingLM)) {
142+ verified = true;
143+ }
144+ }
145+ if (incomingNTLM.length > 0) {
146+ byte[] pw2 = getP2(password);
147+ byte[] nthash = calcNTHash(pw2);
148+ byte[] ntresponse = calcResponse (nthash, nonce);
149+ if (Arrays.equals(ntresponse, incomingNTLM)) {
150+ verified = true;
151+ }
152+ }
153+ debug("NTLM Server: verify using NTLM: " + verified + "\n");
154+ }
155+ if (!verified && (allVersion || v == Version.NTLM2)) {
156+ byte[] pw2 = getP2(password);
157+ byte[] nthash = calcNTHash(pw2);
158+ byte[] clientNonce = Arrays.copyOf(incomingLM, 8);
159+ byte[] ntlmresponse = ntlm2NTLM(nthash, clientNonce, nonce);
160+ if (Arrays.equals(incomingNTLM, ntlmresponse)) {
161+ verified = true;
162+ }
163+ debug("NTLM Server: verify using NTLM2: " + verified + "\n");
164+ }
165+ if (!verified && (allVersion || v == Version.NTLMv2)) {
166+ byte[] pw2 = getP2(password);
167+ byte[] nthash = calcNTHash(pw2);
168+ if (incomingLM.length > 0) {
169+ byte[] clientNonce = Arrays.copyOfRange(
170+ incomingLM, 16, incomingLM.length);
171+ byte[] lmresponse = calcV2(nthash,
172+ username.toUpperCase(Locale.US)+incomingDomain,
173+ clientNonce, nonce);
174+ if (Arrays.equals(lmresponse, incomingLM)) {
175+ verified = true;
176+ }
177+ }
178+ if (incomingNTLM.length > 0) {
179+ byte[] clientBlob = Arrays.copyOfRange(
180+ incomingNTLM, 16, incomingNTLM.length);
181+ byte[] ntlmresponse = calcV2(nthash,
182+ username.toUpperCase(Locale.US)+incomingDomain,
183+ clientBlob, nonce);
184+ if (Arrays.equals(ntlmresponse, incomingNTLM)) {
185+ verified = true;
186+ }
187+ }
188+ debug("NTLM Server: verify using NTLMv2: " + verified + "\n");
189+ }
190+ if (!verified) {
191+ throw new NTLMException(NTLMException.AUTH_FAILED,
192+ "None of LM and NTLM verified");
193+ }
194+ return new String[] {username, hostname};
195+ }
196+
197+ /**
198+ * Retrieves the password for a given user. This method should be
199+ * overridden in a concrete class.
200+ * @param domain can be null
201+ * @param username must not be null
202+ * @return the password for the user, or null if unknown
203+ */
204+ public abstract char[] getPassword(String domain, String username);
205+}