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/Client.java (1 of 18352 files). Show all

Unified · Split

java/pkg/com/sun/security/ntlm/Client.java+212−0
@@ -0,0 +1,212 @@
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
26package com.sun.security.ntlm;
27
28import java.math.BigInteger;
29import java.util.Arrays;
30import java.util.Date;
31import java.util.Locale;
32
33/**
34 * The NTLM client. Not multi-thread enabled.<p>
35 * Example:
36 * <pre>
37 * Client client = new Client(null, "host", "dummy",
38 * "REALM", "t0pSeCr3t".toCharArray());
39 * byte[] type1 = client.type1();
40 * // Send type1 to server and receive response as type2
41 * byte[] type3 = client.type3(type2, nonce);
42 * // Send type3 to server
43 * </pre>
44 */
45public final class Client extends NTLM {
46 final private String hostname;
47 final private String username;
48
49 private String domain; // might be updated by Type 2 msg
50 private byte[] pw1, pw2;
51
52 /**
53 * Creates an NTLM Client instance.
54 * @param version the NTLM version to use, which can be:
55 * <ul>
56 * <li>LM/NTLM: Original NTLM v1
57 * <li>LM: Original NTLM v1, LM only
58 * <li>NTLM: Original NTLM v1, NTLM only
59 * <li>NTLM2: NTLM v1 with Client Challenge
60 * <li>LMv2/NTLMv2: NTLM v2
61 * <li>LMv2: NTLM v2, LM only
62 * <li>NTLMv2: NTLM v2, NTLM only
63 * </ul>
64 * If null, "LMv2/NTLMv2" will be used.
65 * @param hostname hostname of the client, can be null
66 * @param username username to be authenticated, must not be null
67 * @param domain domain of {@code username}, can be null
68 * @param password password for {@code username}, must not be not null.
69 * This method does not make any modification to this parameter, it neither
70 * needs to access the content of this parameter after this method call,
71 * so you are free to modify or nullify this parameter after this call.
72 * @throws NullPointerException if {@code username} or {@code password} is null.
73 * @throws NTLMException if {@code version} is illegal
74 */
75 public Client(String version, String hostname, String username,
76 String domain, char[] password) throws NTLMException {
77 super(version);
78 if ((username == null || password == null)) {
79 throw new NullPointerException("username/password cannot be null");
80 }
81 this.hostname = hostname;
82 this.username = username;
83 this.domain = domain;
84 this.pw1 = getP1(password);
85 this.pw2 = getP2(password);
86 debug("NTLM Client: (h,u,t,version(v)) = (%s,%s,%s,%s(%s))\n",
87 hostname, username, domain, version, v.toString());
88 }
89
90 /**
91 * Generates the Type 1 message
92 * @return the message generated
93 */
94 public byte[] type1() {
95 Writer p = new Writer(1, 32);
96 int flags = 0x8203;
97 if (hostname != null) {
98 flags |= 0x2000;
99 }
100 if (domain != null) {
101 flags |= 0x1000;
102 }
103 if (v != Version.NTLM) {
104 flags |= 0x80000;
105 }
106 p.writeInt(12, flags);
107 p.writeSecurityBuffer(24, hostname, false);
108 p.writeSecurityBuffer(16, domain, false);
109 debug("NTLM Client: Type 1 created\n");
110 debug(p.getBytes());
111 return p.getBytes();
112 }
113
114 /**
115 * Generates the Type 3 message
116 * @param type2 the responding Type 2 message from server, must not be null
117 * @param nonce random 8-byte array to be used in message generation,
118 * must not be null except for original NTLM v1
119 * @return the message generated
120 * @throws NullPointerException if {@code type2} or {@code nonce} is null
121 * for NTLM v1.
122 * @throws NTLMException if the incoming message is invalid
123 */
124 public byte[] type3(byte[] type2, byte[] nonce) throws NTLMException {
125 if (type2 == null || (v != Version.NTLM && nonce == null)) {
126 throw new NullPointerException("type2 and nonce cannot be null");
127 }
128 debug("NTLM Client: Type 2 received\n");
129 debug(type2);
130 Reader r = new Reader(type2);
131 byte[] challenge = r.readBytes(24, 8);
132 int inputFlags = r.readInt(20);
133 boolean unicode = (inputFlags & 1) == 1;
134 String domainFromServer = r.readSecurityBuffer(12, unicode);
135 if (domainFromServer != null) {
136 domain = domainFromServer;
137 }
138 if (domain == null) {
139 throw new NTLMException(NTLMException.NO_DOMAIN_INFO,
140 "No domain info");
141 }
142
143 int flags = 0x88200 | (inputFlags & 3);
144 Writer p = new Writer(3, 64);
145 byte[] lm = null, ntlm = null;
146
147 p.writeSecurityBuffer(28, domain, unicode);
148 p.writeSecurityBuffer(36, username, unicode);
149 p.writeSecurityBuffer(44, hostname, unicode);
150
151 if (v == Version.NTLM) {
152 byte[] lmhash = calcLMHash(pw1);
153 byte[] nthash = calcNTHash(pw2);
154 if (writeLM) lm = calcResponse (lmhash, challenge);
155 if (writeNTLM) ntlm = calcResponse (nthash, challenge);
156 } else if (v == Version.NTLM2) {
157 byte[] nthash = calcNTHash(pw2);
158 lm = ntlm2LM(nonce);
159 ntlm = ntlm2NTLM(nthash, nonce, challenge);
160 } else {
161 byte[] nthash = calcNTHash(pw2);
162 if (writeLM) lm = calcV2(nthash,
163 username.toUpperCase(Locale.US)+domain, nonce, challenge);
164 if (writeNTLM) {
165 byte[] alist = type2.length > 48 ?
166 r.readSecurityBuffer(40) : new byte[0];
167 byte[] blob = new byte[32+alist.length];
168 System.arraycopy(new byte[]{1,1,0,0,0,0,0,0}, 0, blob, 0, 8);
169 // TS
170 byte[] time = BigInteger.valueOf(new Date().getTime())
171 .add(new BigInteger("11644473600000"))
172 .multiply(BigInteger.valueOf(10000))
173 .toByteArray();
174 for (int i=0; i<time.length; i++) {
175 blob[8+time.length-i-1] = time[i];
176 }
177 System.arraycopy(nonce, 0, blob, 16, 8);
178 System.arraycopy(new byte[]{0,0,0,0}, 0, blob, 24, 4);
179 System.arraycopy(alist, 0, blob, 28, alist.length);
180 System.arraycopy(new byte[]{0,0,0,0}, 0,
181 blob, 28+alist.length, 4);
182 ntlm = calcV2(nthash, username.toUpperCase(Locale.US)+domain,
183 blob, challenge);
184 }
185 }
186 p.writeSecurityBuffer(12, lm);
187 p.writeSecurityBuffer(20, ntlm);
188 p.writeSecurityBuffer(52, new byte[0]);
189
190 p.writeInt(60, flags);
191 debug("NTLM Client: Type 3 created\n");
192 debug(p.getBytes());
193 return p.getBytes();
194 }
195
196 /**
197 * Returns the domain value provided by server after the authentication
198 * is complete, or the domain value provided by the client before it.
199 * @return the domain
200 */
201 public String getDomain() {
202 return domain;
203 }
204
205 /**
206 * Disposes any password-derived information.
207 */
208 public void dispose() {
209 Arrays.fill(pw1, (byte)0);
210 Arrays.fill(pw2, (byte)0);
211 }
212}