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

Unified · Split

java/pkg/com/sun/net/httpserver/BasicAuthenticator.java+309−0
@@ -0,0 +1,309 @@
1/*
2 * Copyright (c) 2006, 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.net.httpserver;
27
28/**
29 * BasicAuthenticator provides an implementation of HTTP Basic
30 * authentication. It is an abstract class and must be extended
31 * to provide an implementation of {@link #checkCredentials(String,String)}
32 * which is called to verify each incoming request.
33 */
34public abstract class BasicAuthenticator extends Authenticator {
35
36 protected String realm;
37
38 /**
39 * Creates a BasicAuthenticator for the given HTTP realm
40 * @param realm The HTTP Basic authentication realm
41 * @throws NullPointerException if the realm is an empty string
42 */
43 public BasicAuthenticator (String realm) {
44 this.realm = realm;
45 }
46
47 /**
48 * returns the realm this BasicAuthenticator was created with
49 * @return the authenticator's realm string.
50 */
51 public String getRealm () {
52 return realm;
53 }
54
55 public Result authenticate (HttpExchange t)
56 {
57 Headers rmap = (Headers) t.getRequestHeaders();
58 /*
59 * look for auth token
60 */
61 String auth = rmap.getFirst ("Authorization");
62 if (auth == null) {
63 Headers map = (Headers) t.getResponseHeaders();
64 map.set ("WWW-Authenticate", "Basic realm=" + "\""+realm+"\"");
65 return new Authenticator.Retry (401);
66 }
67 int sp = auth.indexOf (' ');
68 if (sp == -1 || !auth.substring(0, sp).equals ("Basic")) {
69 return new Authenticator.Failure (401);
70 }
71 byte[] b = Base64.base64ToByteArray (auth.substring(sp+1));
72 String userpass = new String (b);
73 int colon = userpass.indexOf (':');
74 String uname = userpass.substring (0, colon);
75 String pass = userpass.substring (colon+1);
76
77 if (checkCredentials (uname, pass)) {
78 return new Authenticator.Success (
79 new HttpPrincipal (
80 uname, realm
81 )
82 );
83 } else {
84 /* reject the request again with 401 */
85
86 Headers map = (Headers) t.getResponseHeaders();
87 map.set ("WWW-Authenticate", "Basic realm=" + "\""+realm+"\"");
88 return new Authenticator.Failure(401);
89 }
90 }
91
92 /**
93 * called for each incoming request to verify the
94 * given name and password in the context of this
95 * Authenticator's realm. Any caching of credentials
96 * must be done by the implementation of this method
97 * @param username the username from the request
98 * @param password the password from the request
99 * @return <code>true</code> if the credentials are valid,
100 * <code>false</code> otherwise.
101 */
102 public abstract boolean checkCredentials (String username, String password);
103}
104
105class Base64 {
106
107 /**
108 * Translates the specified byte array into a Base64 string as per
109 * Preferences.put(byte[]).
110 */
111 static String byteArrayToBase64(byte[] a) {
112 return byteArrayToBase64(a, false);
113 }
114
115 /**
116 * Translates the specified byte array into an "aternate representation"
117 * Base64 string. This non-standard variant uses an alphabet that does
118 * not contain the uppercase alphabetic characters, which makes it
119 * suitable for use in situations where case-folding occurs.
120 */
121 static String byteArrayToAltBase64(byte[] a) {
122 return byteArrayToBase64(a, true);
123 }
124
125 private static String byteArrayToBase64(byte[] a, boolean alternate) {
126 int aLen = a.length;
127 int numFullGroups = aLen/3;
128 int numBytesInPartialGroup = aLen - 3*numFullGroups;
129 int resultLen = 4*((aLen + 2)/3);
130 StringBuffer result = new StringBuffer(resultLen);
131 char[] intToAlpha = (alternate ? intToAltBase64 : intToBase64);
132
133 // Translate all full groups from byte array elements to Base64
134 int inCursor = 0;
135 for (int i=0; i<numFullGroups; i++) {
136 int byte0 = a[inCursor++] & 0xff;
137 int byte1 = a[inCursor++] & 0xff;
138 int byte2 = a[inCursor++] & 0xff;
139 result.append(intToAlpha[byte0 >> 2]);
140 result.append(intToAlpha[(byte0 << 4)&0x3f | (byte1 >> 4)]);
141 result.append(intToAlpha[(byte1 << 2)&0x3f | (byte2 >> 6)]);
142 result.append(intToAlpha[byte2 & 0x3f]);
143 }
144
145 // Translate partial group if present
146 if (numBytesInPartialGroup != 0) {
147 int byte0 = a[inCursor++] & 0xff;
148 result.append(intToAlpha[byte0 >> 2]);
149 if (numBytesInPartialGroup == 1) {
150 result.append(intToAlpha[(byte0 << 4) & 0x3f]);
151 result.append("==");
152 } else {
153 // assert numBytesInPartialGroup == 2;
154 int byte1 = a[inCursor++] & 0xff;
155 result.append(intToAlpha[(byte0 << 4)&0x3f | (byte1 >> 4)]);
156 result.append(intToAlpha[(byte1 << 2)&0x3f]);
157 result.append('=');
158 }
159 }
160 // assert inCursor == a.length;
161 // assert result.length() == resultLen;
162 return result.toString();
163 }
164
165 /**
166 * This array is a lookup table that translates 6-bit positive integer
167 * index values into their "Base64 Alphabet" equivalents as specified
168 * in Table 1 of RFC 2045.
169 */
170 private static final char intToBase64[] = {
171 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
172 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
173 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
174 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
175 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
176 };
177
178 /**
179 * This array is a lookup table that translates 6-bit positive integer
180 * index values into their "Alternate Base64 Alphabet" equivalents.
181 * This is NOT the real Base64 Alphabet as per in Table 1 of RFC 2045.
182 * This alternate alphabet does not use the capital letters. It is
183 * designed for use in environments where "case folding" occurs.
184 */
185 private static final char intToAltBase64[] = {
186 '!', '"', '#', '$', '%', '&', '\'', '(', ')', ',', '-', '.', ':',
187 ';', '<', '>', '@', '[', ']', '^', '`', '_', '{', '|', '}', '~',
188 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
189 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
190 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '?'
191 };
192
193 /**
194 * Translates the specified Base64 string (as per Preferences.get(byte[]))
195 * into a byte array.
196 *
197 * @throw IllegalArgumentException if <tt>s</tt> is not a valid Base64
198 * string.
199 */
200 static byte[] base64ToByteArray(String s) {
201 return base64ToByteArray(s, false);
202 }
203
204 /**
205 * Translates the specified "aternate representation" Base64 string
206 * into a byte array.
207 *
208 * @throw IllegalArgumentException or ArrayOutOfBoundsException
209 * if <tt>s</tt> is not a valid alternate representation
210 * Base64 string.
211 */
212 static byte[] altBase64ToByteArray(String s) {
213 return base64ToByteArray(s, true);
214 }
215
216 private static byte[] base64ToByteArray(String s, boolean alternate) {
217 byte[] alphaToInt = (alternate ? altBase64ToInt : base64ToInt);
218 int sLen = s.length();
219 int numGroups = sLen/4;
220 if (4*numGroups != sLen)
221 throw new IllegalArgumentException(
222 "String length must be a multiple of four.");
223 int missingBytesInLastGroup = 0;
224 int numFullGroups = numGroups;
225 if (sLen != 0) {
226 if (s.charAt(sLen-1) == '=') {
227 missingBytesInLastGroup++;
228 numFullGroups--;
229 }
230 if (s.charAt(sLen-2) == '=')
231 missingBytesInLastGroup++;
232 }
233 byte[] result = new byte[3*numGroups - missingBytesInLastGroup];
234
235 // Translate all full groups from base64 to byte array elements
236 int inCursor = 0, outCursor = 0;
237 for (int i=0; i<numFullGroups; i++) {
238 int ch0 = base64toInt(s.charAt(inCursor++), alphaToInt);
239 int ch1 = base64toInt(s.charAt(inCursor++), alphaToInt);
240 int ch2 = base64toInt(s.charAt(inCursor++), alphaToInt);
241 int ch3 = base64toInt(s.charAt(inCursor++), alphaToInt);
242 result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4));
243 result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2));
244 result[outCursor++] = (byte) ((ch2 << 6) | ch3);
245 }
246
247 // Translate partial group, if present
248 if (missingBytesInLastGroup != 0) {
249 int ch0 = base64toInt(s.charAt(inCursor++), alphaToInt);
250 int ch1 = base64toInt(s.charAt(inCursor++), alphaToInt);
251 result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4));
252
253 if (missingBytesInLastGroup == 1) {
254 int ch2 = base64toInt(s.charAt(inCursor++), alphaToInt);
255 result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2));
256 }
257 }
258 // assert inCursor == s.length()-missingBytesInLastGroup;
259 // assert outCursor == result.length;
260 return result;
261 }
262
263 /**
264 * Translates the specified character, which is assumed to be in the
265 * "Base 64 Alphabet" into its equivalent 6-bit positive integer.
266 *
267 * @throw IllegalArgumentException or ArrayOutOfBoundsException if
268 * c is not in the Base64 Alphabet.
269 */
270 private static int base64toInt(char c, byte[] alphaToInt) {
271 int result = alphaToInt[c];
272 if (result < 0)
273 throw new IllegalArgumentException("Illegal character " + c);
274 return result;
275 }
276
277 /**
278 * This array is a lookup table that translates unicode characters
279 * drawn from the "Base64 Alphabet" (as specified in Table 1 of RFC 2045)
280 * into their 6-bit positive integer equivalents. Characters that
281 * are not in the Base64 alphabet but fall within the bounds of the
282 * array are translated to -1.
283 */
284 private static final byte base64ToInt[] = {
285 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
286 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
287 -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54,
288 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4,
289 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
290 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34,
291 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
292 };
293
294 /**
295 * This array is the analogue of base64ToInt, but for the nonstandard
296 * variant that avoids the use of uppercase alphabetic characters.
297 */
298 private static final byte altBase64ToInt[] = {
299 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
300 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1,
301 2, 3, 4, 5, 6, 7, 8, -1, 62, 9, 10, 11, -1 , 52, 53, 54, 55, 56, 57,
302 58, 59, 60, 61, 12, 13, 14, -1, 15, 63, 16, -1, -1, -1, -1, -1, -1,
303 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
304 -1, -1, -1, 17, -1, 18, 19, 21, 20, 26, 27, 28, 29, 30, 31, 32, 33,
305 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
306 51, 22, 23, 24, 25
307 };
308
309}