Source Code Cross Referenced for HTTPNTLMAuthentication.java in  » Source-Control » tmatesoft-SVN » org » tmatesoft » svn » core » internal » io » dav » http » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Source Control » tmatesoft SVN » org.tmatesoft.svn.core.internal.io.dav.http 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * ====================================================================
003:         * Copyright (c) 2004-2008 TMate Software Ltd.  All rights reserved.
004:         *
005:         * This software is licensed as described in the file COPYING, which
006:         * you should have received as part of this distribution.  The terms
007:         * are also available at http://svnkit.com/license.html
008:         * If newer versions of this license are posted there, you may use a
009:         * newer version instead, at your option.
010:         * ====================================================================
011:         */
012:        package org.tmatesoft.svn.core.internal.io.dav.http;
013:
014:        import java.io.UnsupportedEncodingException;
015:        import java.net.InetAddress;
016:        import java.net.UnknownHostException;
017:        import java.security.InvalidKeyException;
018:        import java.security.NoSuchAlgorithmException;
019:        import java.util.Iterator;
020:        import java.util.Map;
021:        import java.util.TreeMap;
022:
023:        import javax.crypto.BadPaddingException;
024:        import javax.crypto.Cipher;
025:        import javax.crypto.IllegalBlockSizeException;
026:        import javax.crypto.NoSuchPaddingException;
027:        import javax.crypto.spec.SecretKeySpec;
028:
029:        import org.tmatesoft.svn.core.SVNErrorCode;
030:        import org.tmatesoft.svn.core.SVNErrorMessage;
031:        import org.tmatesoft.svn.core.SVNException;
032:        import org.tmatesoft.svn.core.internal.util.SVNBase64;
033:        import org.tmatesoft.svn.core.internal.util.SVNFormatUtil;
034:        import org.tmatesoft.svn.core.internal.wc.SVNErrorManager;
035:
036:        /**
037:         * @version 1.1.1
038:         * @author  TMate Software Ltd.
039:         */
040:        class HTTPNTLMAuthentication extends HTTPAuthentication {
041:
042:            private static final String NTLM_CASE_CONVERTION_PROPERTY = "svnkit.http.ntlm.uppercase";
043:            private static final String OLD_NTLM_CASE_CONVERTION_PROPERTY = "javasvn.http.ntlm.uppercase";
044:
045:            private static final String DEFAULT_CHARSET = "ASCII";
046:            private static final String PROTOCOL_NAME = "NTLMSSP";
047:            private static final int LM_RESPONSE_LENGTH = 24;
048:            private static final int UNINITIATED = 0;
049:            private static final int TYPE1 = 1;
050:            private static final int TYPE3 = 3;
051:            private static byte[] ourMagicBytes = { (byte) 0x4B, (byte) 0x47,
052:                    (byte) 0x53, (byte) 0x21, (byte) 0x40, (byte) 0x23,
053:                    (byte) 0x24, (byte) 0x25 };
054:
055:            private static final long NEGOTIATE_UNICODE = 0x00000001L;
056:            private static final long NEGOTIATE_OEM = 0x00000002L;
057:            private static final long REQUEST_TARGET = 0x00000004L;
058:            private static final long NEGOTIATE_SIGN = 0x00000010L;
059:            private static final long NEGOTIATE_SEAL = 0x00000020L;
060:            private static final long NEGOTIATE_DATAGRAM_STYLE = 0x00000040L;
061:            private static final long NEGOTIATE_LAN_MANAGER_KEY = 0x00000080L;
062:            private static final long NEGOTIATE_NETWARE = 0x00000100L;
063:            private static final long NEGOTIATE_NTLM = 0x00000200L;
064:            private static final long NEGOTIATE_DOMAIN_SUPPLIED = 0x00001000L;
065:            private static final long NEGOTIATE_WORKSTATION_SUPPLIED = 0x00002000L;
066:            private static final long NEGOTIATE_LOCAL_CALL = 0x00004000L;
067:            private static final long NEGOTIATE_ALWAYS_SIGN = 0x00008000L;
068:            private static final long TARGET_TYPE_DOMAIN = 0x00010000L;
069:            private static final long TARGET_TYPE_SERVER = 0x00020000L;
070:            private static final long TARGET_TYPE_SHARE = 0x00040000L;
071:            private static final long NEGOTIATE_NTLM2_KEY = 0x00080000L;
072:            private static final long REQUEST_INIT_RESPONSE = 0x00100000L;
073:            private static final long REQUEST_ACCEPT_RESPONSE = 0x00200000L;
074:            private static final long REQUEST_NON_NT_SESSION_KEY = 0x00400000L;
075:            private static final long NEGOTIATE_TARGET_INFO = 0x00800000L;
076:            private static final long NEGOTIATE_128 = 0x20000000L;
077:            private static final long NEGOTIATE_KEY_EXCHANGE = 0x40000000L;
078:            private static final long NEGOTIATE_56 = 0x80000000L;
079:
080:            private static Map ourFlags = new TreeMap();
081:            static {
082:                ourFlags.put(new Long(NEGOTIATE_UNICODE),
083:                        "0x00000001 (Negotiate Unicode)");
084:                ourFlags.put(new Long(NEGOTIATE_OEM),
085:                        "0x00000002 (Negotiate OEM)");
086:                ourFlags.put(new Long(REQUEST_TARGET),
087:                        "0x00000004 (Request Target)");
088:                ourFlags.put(new Long(0x00000008L), "0x00000008 (Unknown)");
089:                ourFlags.put(new Long(NEGOTIATE_SIGN),
090:                        "0x00000010 (Negotiate Sign)");
091:                ourFlags.put(new Long(NEGOTIATE_SEAL),
092:                        "0x00000020 (Negotiate Seal)");
093:                ourFlags.put(new Long(NEGOTIATE_DATAGRAM_STYLE),
094:                        "0x00000040 (Negotiate Datagram Style)");
095:                ourFlags.put(new Long(NEGOTIATE_LAN_MANAGER_KEY),
096:                        "0x00000080 (Negotiate Lan Manager Key)");
097:                ourFlags.put(new Long(NEGOTIATE_NETWARE),
098:                        "0x00000100 (Negotiate Netware)");
099:                ourFlags.put(new Long(NEGOTIATE_NTLM),
100:                        "0x00000200 (Negotiate NTLM)");
101:                ourFlags.put(new Long(0x00000400L), "0x00000400 (Unknown)");
102:                ourFlags.put(new Long(0x00000800L), "0x00000800 (Unknown)");
103:                ourFlags.put(new Long(NEGOTIATE_DOMAIN_SUPPLIED),
104:                        "0x00001000 (Negotiate Domain Supplied)");
105:                ourFlags.put(new Long(NEGOTIATE_WORKSTATION_SUPPLIED),
106:                        "0x00002000 (Negotiate Workstation Supplied)");
107:                ourFlags.put(new Long(NEGOTIATE_LOCAL_CALL),
108:                        "0x00004000 (Negotiate Local Call)");
109:                ourFlags.put(new Long(NEGOTIATE_ALWAYS_SIGN),
110:                        "0x00008000 (Negotiate Always Sign)");
111:                ourFlags.put(new Long(TARGET_TYPE_DOMAIN),
112:                        "0x00010000 (Target Type Domain)");
113:                ourFlags.put(new Long(TARGET_TYPE_SERVER),
114:                        "0x00020000 (Target Type Server)");
115:                ourFlags.put(new Long(TARGET_TYPE_SHARE),
116:                        "0x00040000 (Target Type Share)");
117:                ourFlags.put(new Long(NEGOTIATE_NTLM2_KEY),
118:                        "0x00080000 (Negotiate NTLM2 Key)");
119:                ourFlags.put(new Long(REQUEST_INIT_RESPONSE),
120:                        "0x00100000 (Request Init Response)");
121:                ourFlags.put(new Long(REQUEST_ACCEPT_RESPONSE),
122:                        "0x00200000 (Request Accept Response)");
123:                ourFlags.put(new Long(REQUEST_NON_NT_SESSION_KEY),
124:                        "0x00400000 (Request Non-NT Session Key)");
125:                ourFlags.put(new Long(NEGOTIATE_TARGET_INFO),
126:                        "0x00800000 (Negotiate Target Info)");
127:                ourFlags.put(new Long(0x01000000L), "0x01000000 (Unknown)");
128:                ourFlags.put(new Long(0x02000000L), "0x02000000 (Unknown)");
129:                ourFlags.put(new Long(0x04000000L), "0x04000000 (Unknown)");
130:                ourFlags.put(new Long(0x08000000L), "0x08000000 (Unknown)");
131:                ourFlags.put(new Long(0x10000000L), "0x10000000 (Unknown)");
132:                ourFlags.put(new Long(NEGOTIATE_128),
133:                        "0x20000000 (Negotiate 128)");
134:                ourFlags.put(new Long(NEGOTIATE_KEY_EXCHANGE),
135:                        "0x40000000 (Negotiate Key Exchange)");
136:                ourFlags.put(new Long(NEGOTIATE_56),
137:                        "0x80000000 (Negotiate 56)");
138:            }
139:            private static Map ourTargetInfoTypes = new TreeMap();
140:            static {
141:                ourTargetInfoTypes.put(new Integer(1), "Server Name");
142:                ourTargetInfoTypes.put(new Integer(2), "Domain Name");
143:                ourTargetInfoTypes.put(new Integer(3), "DNS Host Name");
144:                ourTargetInfoTypes.put(new Integer(4), "DNS Domain Name");
145:            }
146:
147:            private int myState;
148:            private byte[] myResponse;
149:            private int myPosition;
150:            private byte[] myNonce;
151:            private boolean myIsNegotiateLocalCall;
152:            private String myCharset;
153:
154:            protected HTTPNTLMAuthentication(String charset) {
155:                myState = UNINITIATED;
156:                myIsNegotiateLocalCall = false;
157:                myCharset = charset;
158:            }
159:
160:            public void setType1State() {
161:                myState = TYPE1;
162:            }
163:
164:            public void setType3State() {
165:                myState = TYPE3;
166:            }
167:
168:            public boolean isInType3State() {
169:                return myState == TYPE3;
170:            }
171:
172:            private void initResponse(int bufferSize) {
173:                myResponse = new byte[bufferSize];
174:                myPosition = 0;
175:            }
176:
177:            private void addByte(byte b) {
178:                myResponse[myPosition++] = b;
179:            }
180:
181:            private void addBytes(byte[] bytes) {
182:                for (int i = 0; i < bytes.length; i++) {
183:                    myResponse[myPosition++] = bytes[i];
184:                }
185:            }
186:
187:            private byte[] convertToShortValue(int num) {
188:                byte[] val = new byte[2];
189:                val[0] = (byte) (num & 0xff);
190:                val[1] = (byte) ((num >> 8) & 0xff);
191:                return val;
192:            }
193:
194:            private String getResponse() {
195:                byte[] response;
196:                if (myResponse.length > myPosition) {
197:                    response = new byte[myPosition];
198:                    for (int i = 0; i < myPosition; i++) {
199:                        response[i] = myResponse[i];
200:                    }
201:                } else {
202:                    response = myResponse;
203:                }
204:
205:                return SVNBase64.byteArrayToBase64(response);
206:            }
207:
208:            public void parseChallenge(String challenge) throws SVNException {
209:                if (challenge == null) {
210:                    SVNErrorMessage err = SVNErrorMessage.create(
211:                            SVNErrorCode.RA_DAV_REQUEST_FAILED,
212:                            "NTLM HTTP auth: expected challenge");
213:                    SVNErrorManager.error(err);
214:                }
215:                byte[] challengeBase64Bytes = HTTPAuthentication.getBytes(
216:                        challenge, DEFAULT_CHARSET);
217:                byte[] resultBuffer = new byte[challengeBase64Bytes.length];
218:                int resultLength = 0;
219:                try {
220:                    resultLength = SVNBase64.base64ToByteArray(
221:                            new StringBuffer(new String(challengeBase64Bytes,
222:                                    myCharset)), resultBuffer);
223:                } catch (UnsupportedEncodingException e) {
224:                    SVNErrorMessage err = SVNErrorMessage.create(
225:                            SVNErrorCode.RA_DAV_REQUEST_FAILED,
226:                            "NTLM HTTP auth: " + e.getMessage());
227:                    SVNErrorManager.error(err);
228:                }
229:
230:                String proto = new String(resultBuffer, 0, 7);
231:                byte[] typeBytes = new byte[4];
232:                for (int i = 0; i < 4; i++) {
233:                    typeBytes[i] = resultBuffer[8 + i];
234:                }
235:                long type = toLong(typeBytes);
236:
237:                if (!PROTOCOL_NAME.equalsIgnoreCase(proto)) {
238:                    SVNErrorMessage err = SVNErrorMessage.create(
239:                            SVNErrorCode.RA_DAV_REQUEST_FAILED,
240:                            "NTLM HTTP auth: incorrect signature ''(0}''",
241:                            proto);
242:                    SVNErrorManager.error(err);
243:                } else if (type != 2) {
244:                    SVNErrorMessage err = SVNErrorMessage
245:                            .create(
246:                                    SVNErrorCode.RA_DAV_REQUEST_FAILED,
247:                                    "NTLM HTTP auth: expected type 2 message instead of ''(0, number, integer}''",
248:                                    new Long(type));
249:                    SVNErrorManager.error(err);
250:                }
251:
252:                myNonce = new byte[8];
253:                for (int i = 0; i < 8; i++) {
254:                    myNonce[i] = resultBuffer[i + 24];
255:                }
256:
257:                byte[] flagBytes = new byte[4];
258:                for (int i = 0; i < 4; i++) {
259:                    flagBytes[i] = resultBuffer[i + 20];
260:                }
261:                long flags = toLong(flagBytes);
262:
263:                StringBuffer log = new StringBuffer();
264:                String base64DecodedMessage = new String(resultBuffer, 0,
265:                        resultLength);
266:                log.append("NTLM auth message: " + base64DecodedMessage);
267:                log.append('\n');
268:                log.append("Length: " + base64DecodedMessage.length());
269:                log.append('\n');
270:                log.append("Signature: " + proto);
271:                log.append('\n');
272:                log.append("Type: " + type);
273:                log.append('\n');
274:                log.append("Flags: " + Long.toString(flags, 16));
275:                log.append('\n');
276:                for (Iterator flagsIter = ourFlags.keySet().iterator(); flagsIter
277:                        .hasNext();) {
278:                    Long curFlag = (Long) flagsIter.next();
279:                    if ((flags & curFlag.longValue()) != 0) {
280:                        log.append(ourFlags.get(curFlag));
281:                        log.append('\n');
282:                    }
283:                }
284:
285:                byte[] targetNameLengthBytes = new byte[2];
286:                for (int i = 0; i < 2; i++) {
287:                    targetNameLengthBytes[i] = resultBuffer[12 + i];
288:                }
289:                int targetNameLength = toInt(targetNameLengthBytes);
290:
291:                byte[] targetNameAllocatedBytes = new byte[2];
292:                for (int i = 0; i < 2; i++) {
293:                    targetNameAllocatedBytes[i] = resultBuffer[14 + i];
294:                }
295:                int targetNameAllocated = toInt(targetNameAllocatedBytes);
296:
297:                byte[] targetNameOffsetBytes = new byte[4];
298:                for (int i = 0; i < 4; i++) {
299:                    targetNameOffsetBytes[i] = resultBuffer[16 + i];
300:                }
301:                long targetNameOffset = toLong(targetNameOffsetBytes);
302:
303:                if (targetNameLength > 0) {
304:                    String targetName = new String(resultBuffer,
305:                            (int) targetNameOffset, targetNameAllocated);
306:                    log.append("Target Name: " + targetName);
307:                    log.append('\n');
308:                }
309:                log.append("Challenge: ");
310:                for (int i = 0; i < myNonce.length; i++) {
311:                    log.append(SVNFormatUtil.getHexNumberFromByte(myNonce[i]));
312:                }
313:                log.append('\n');
314:
315:                //check for local call
316:                long contextH = -1;
317:                long contextL = -1;
318:                boolean containsContext = false;
319:                if (targetNameOffset != 32 && resultLength >= 40) {
320:                    byte[] contextHBytes = new byte[4];
321:                    byte[] contextLBytes = new byte[4];
322:                    int i = 0;
323:                    for (i = 0; i < 4; i++) {
324:                        contextHBytes[i] = resultBuffer[i + 32];
325:                    }
326:                    for (; i < 8; i++) {
327:                        contextLBytes[i - 4] = resultBuffer[i + 32];
328:                    }
329:
330:                    contextH = toLong(contextHBytes);
331:                    contextL = toLong(contextLBytes);
332:                    if (contextL == 0) {
333:                        containsContext = true;
334:                        log.append("Context: ");
335:                        log.append(Long.toString(contextH, 16) + " "
336:                                + Long.toString(contextL, 16));
337:                        log.append('\n');
338:                    }
339:
340:                    if (contextH != 0 && (flags & NEGOTIATE_LOCAL_CALL) != 0) {
341:                        myIsNegotiateLocalCall = true;
342:                    } else {
343:                        myIsNegotiateLocalCall = false;
344:                    }
345:                } else {
346:                    myIsNegotiateLocalCall = false;
347:                }
348:
349:                if ((flags & NEGOTIATE_TARGET_INFO) != 0) {
350:                    int tgtInfoSecurityBufferOffset = containsContext ? 40 : 32;
351:
352:                    byte[] targetInfoLengthBytes = new byte[2];
353:                    for (int i = 0; i < 2; i++) {
354:                        targetInfoLengthBytes[i] = resultBuffer[tgtInfoSecurityBufferOffset
355:                                + i];
356:                    }
357:                    int targetInfoLength = toInt(targetInfoLengthBytes);
358:
359:                    byte[] targetInfoAllocatedBytes = new byte[2];
360:                    for (int i = 0; i < 2; i++) {
361:                        targetInfoAllocatedBytes[i] = resultBuffer[tgtInfoSecurityBufferOffset
362:                                + 2 + i];
363:                    }
364:                    int targetInfoAllocated = toInt(targetInfoAllocatedBytes);
365:
366:                    byte[] targetInfoOffsetBytes = new byte[4];
367:                    for (int i = 0; i < 4; i++) {
368:                        targetInfoOffsetBytes[i] = resultBuffer[tgtInfoSecurityBufferOffset
369:                                + 4 + i];
370:                    }
371:                    long targetInfoOffset = toLong(targetInfoOffsetBytes);
372:
373:                    byte[] targetInfoTypeBytes = new byte[2];
374:                    byte[] subblockLengthBytes = new byte[2];
375:                    int read = 0;
376:                    while (targetInfoLength > 0 && read <= targetInfoAllocated) {
377:                        for (int i = 0; i < 2; i++) {
378:                            targetInfoTypeBytes[i] = resultBuffer[(int) targetInfoOffset
379:                                    + i];
380:                        }
381:                        read += 2;
382:                        targetInfoOffset += 2;
383:                        int targetInfoType = toInt(targetInfoTypeBytes);
384:                        if (targetInfoType == 0) {
385:                            break;
386:                        }
387:
388:                        for (int i = 0; i < 2; i++) {
389:                            subblockLengthBytes[i] = resultBuffer[(int) targetInfoOffset
390:                                    + i];
391:                        }
392:                        read += 2;
393:                        targetInfoOffset += 2;
394:                        int subblockLength = toInt(subblockLengthBytes);
395:
396:                        String typeDescription = (String) ourTargetInfoTypes
397:                                .get(new Integer(targetInfoType));
398:                        if (typeDescription != null) {
399:                            String info = new String(resultBuffer,
400:                                    (int) targetInfoOffset, subblockLength);
401:                            log.append(typeDescription + ": " + info);
402:                            log.append('\n');
403:                        }
404:                        read += subblockLength;
405:                        targetInfoOffset += subblockLength;
406:                    }
407:                }
408:                log.append('\n');
409:            }
410:
411:            private static int toInt(byte[] num) {
412:                int l = 0;
413:                for (int i = 0; i < 2; i++) {
414:                    int b = num[i] & 0xff;
415:                    b = b << i * 8;
416:                    l |= b;
417:                }
418:                return l;
419:            }
420:
421:            private long toLong(byte[] num) {
422:                long l = 0;
423:                for (int i = 0; i < 4; i++) {
424:                    long b = num[i] & 0xff;
425:                    b = b << i * 8;
426:                    l |= b;
427:                }
428:                return l;
429:            }
430:
431:            public String authenticate() throws SVNException {
432:                if (myState != TYPE1 && myState != TYPE3) {
433:                    SVNErrorMessage err = SVNErrorMessage
434:                            .create(SVNErrorCode.RA_DAV_REQUEST_FAILED,
435:                                    "Unsupported message type in HTTP NTLM authentication");
436:                    SVNErrorManager.error(err);
437:                }
438:
439:                String login = getUserName();
440:                String domain = null;
441:                String username = null;
442:
443:                int slashInd = login != null ? login.indexOf('\\') : -1;
444:                if (slashInd != -1) {
445:                    domain = login.substring(0, slashInd);
446:                    int lastInd = slashInd + 1;
447:                    while (lastInd < login.length()
448:                            && login.charAt(lastInd) == '\\') {
449:                        lastInd++;
450:                    }
451:                    username = login.substring(lastInd);
452:                } else {
453:                    domain = "";
454:                    username = login;
455:                }
456:
457:                String hostName = null;
458:                try {
459:                    InetAddress localhost = InetAddress.getLocalHost();
460:                    hostName = localhost.getHostName();
461:                } catch (UnknownHostException uhe) {
462:                    hostName = "";
463:                }
464:
465:                if (isUpperCase()) {
466:                    domain = domain.toUpperCase();
467:                    hostName = hostName.toUpperCase();
468:                }
469:
470:                byte[] protocol = HTTPAuthentication.getBytes(PROTOCOL_NAME,
471:                        DEFAULT_CHARSET);
472:                byte[] domainBytes = HTTPAuthentication.getBytes(domain,
473:                        DEFAULT_CHARSET);
474:                byte[] hostNameBytes = HTTPAuthentication.getBytes(hostName,
475:                        DEFAULT_CHARSET);
476:                byte[] domLen = convertToShortValue(domainBytes.length);
477:                byte[] hostLen = convertToShortValue(hostNameBytes.length);
478:                StringBuffer sublog = new StringBuffer();
479:                sublog.append("Signature: " + PROTOCOL_NAME);
480:                sublog.append('\n');
481:
482:                long flags = NEGOTIATE_OEM | REQUEST_TARGET | NEGOTIATE_NTLM
483:                        | NEGOTIATE_LOCAL_CALL;
484:                if (domain.length() > 0) {
485:                    flags |= NEGOTIATE_DOMAIN_SUPPLIED;
486:                }
487:
488:                if (myState == TYPE1) {
489:                    int responseLength = 32 + domainBytes.length
490:                            + hostNameBytes.length;
491:
492:                    initResponse(responseLength);
493:
494:                    //NTLMSSP\0 signature (8 bytes long)
495:                    addBytes(protocol);
496:                    addByte((byte) 0);
497:
498:                    // Type1 - Negotiate (4 bytes long)
499:                    addByte((byte) 1);
500:                    addByte((byte) 0);
501:                    addByte((byte) 0);
502:                    addByte((byte) 0);
503:                    sublog.append("Type: " + 1);
504:                    sublog.append('\n');
505:
506:                    // Flags (4 bytes long): 'Negotiate OEM', 'Request Target', 
507:                    // 'Negotiate NTLM', 'Negotiate Always Sign'
508:                    addByte((byte) (flags & 0xff));
509:                    addByte((byte) ((flags >> 8) & 0xff));
510:                    addByte((byte) ((flags >> 16) & 0xff));
511:                    addByte((byte) ((flags >> 24) & 0xff));
512:                    sublog.append("Flags: " + Long.toString(flags, 16));
513:                    sublog.append('\n');
514:                    for (Iterator flagsIter = ourFlags.keySet().iterator(); flagsIter
515:                            .hasNext();) {
516:                        Long curFlag = (Long) flagsIter.next();
517:                        if ((flags & curFlag.longValue()) != 0) {
518:                            sublog.append(ourFlags.get(curFlag));
519:                            sublog.append('\n');
520:                        }
521:                    }
522:
523:                    // Domain name length (2 bytes short)
524:                    addBytes(domLen);
525:                    // Allocated space for the domain name (2 bytes short)
526:                    addBytes(domLen);
527:
528:                    // Domain name offset (4 bytes long)
529:                    byte[] domainOffset = convertToShortValue(hostNameBytes.length + 32);
530:                    addBytes(domainOffset);
531:                    addByte((byte) 0);
532:                    addByte((byte) 0);
533:
534:                    // Host name length (2 bytes short).
535:                    addBytes(hostLen);
536:                    // Allocated space for the host name (2 bytes short)
537:                    addBytes(hostLen);
538:
539:                    // Host name offset (always 32, 4 bytes long).
540:                    byte[] hostOffset = convertToShortValue(32);
541:                    addBytes(hostOffset);
542:                    addByte((byte) 0);
543:                    addByte((byte) 0);
544:
545:                    // Host name 
546:                    addBytes(hostNameBytes);
547:                    if (hostName.length() > 0) {
548:                        sublog.append("Host Name: " + hostName);
549:                        sublog.append('\n');
550:                    }
551:
552:                    // Domain name
553:                    addBytes(domainBytes);
554:                    if (domain.length() > 0) {
555:                        sublog.append("Domain: " + domain);
556:                        sublog.append('\n');
557:                    }
558:                } else if (myState == TYPE3) {
559:                    byte[] userBytes = username.getBytes();
560:                    sublog.append("Type: " + 3);
561:                    sublog.append('\n');
562:                    sublog.append("Flags: " + Long.toString(flags, 16));
563:                    sublog.append('\n');
564:                    for (Iterator flagsIter = ourFlags.keySet().iterator(); flagsIter
565:                            .hasNext();) {
566:                        Long curFlag = (Long) flagsIter.next();
567:                        if ((flags & curFlag.longValue()) != 0) {
568:                            sublog.append(ourFlags.get(curFlag));
569:                            sublog.append('\n');
570:                        }
571:                    }
572:
573:                    if (!myIsNegotiateLocalCall) {
574:                        int responseLength = 64 + LM_RESPONSE_LENGTH
575:                                + domainBytes.length + hostNameBytes.length
576:                                + userBytes.length;
577:
578:                        initResponse(responseLength);
579:
580:                        addBytes(protocol);
581:                        addByte((byte) 0);
582:
583:                        //Type3
584:                        addByte((byte) 3);
585:                        addByte((byte) 0);
586:                        addByte((byte) 0);
587:                        addByte((byte) 0);
588:
589:                        byte[] lmResponseLength = convertToShortValue(24);
590:                        // LM Response Length 
591:                        addBytes(lmResponseLength);
592:                        // LM Response allocated space
593:                        addBytes(lmResponseLength);
594:
595:                        // LM Response Offset
596:                        addBytes(convertToShortValue(responseLength - 24));
597:                        addByte((byte) 0);
598:                        addByte((byte) 0);
599:
600:                        byte[] ntlmResponseLength = convertToShortValue(0);
601:                        // NTLM Response Length 
602:                        addBytes(ntlmResponseLength);
603:                        // NTLM Response allocated space
604:                        addBytes(ntlmResponseLength);
605:
606:                        byte[] responseLengthShortBytes = convertToShortValue(responseLength);
607:                        // NTLM Response Offset
608:                        addBytes(responseLengthShortBytes);
609:                        addByte((byte) 0);
610:                        addByte((byte) 0);
611:
612:                        // Domain length
613:                        addBytes(domLen);
614:                        // Domain allocated space
615:                        addBytes(domLen);
616:
617:                        // Domain Offset
618:                        addBytes(convertToShortValue(64));
619:                        addByte((byte) 0);
620:                        addByte((byte) 0);
621:
622:                        byte[] usernameLength = convertToShortValue(userBytes.length);
623:                        // Username Length 
624:                        addBytes(usernameLength);
625:                        // Username allocated space
626:                        addBytes(usernameLength);
627:
628:                        // User offset
629:                        addBytes(convertToShortValue(64 + domainBytes.length));
630:                        addByte((byte) 0);
631:                        addByte((byte) 0);
632:
633:                        // Host name length
634:                        addBytes(hostLen);
635:                        // Host name allocated space
636:                        addBytes(hostLen);
637:
638:                        // Host offset
639:                        addBytes(convertToShortValue(64 + domainBytes.length
640:                                + userBytes.length));
641:
642:                        for (int i = 0; i < 6; i++) {
643:                            addByte((byte) 0);
644:                        }
645:
646:                        // Message length
647:                        addBytes(responseLengthShortBytes);
648:                        addByte((byte) 0);
649:                        addByte((byte) 0);
650:
651:                        // Flags
652:                        addByte((byte) (flags & 0xff));
653:                        addByte((byte) ((flags >> 8) & 0xff));
654:                        addByte((byte) ((flags >> 16) & 0xff));
655:                        addByte((byte) ((flags >> 24) & 0xff));
656:
657:                        addBytes(domainBytes);
658:                        if (domain.length() > 0) {
659:                            sublog.append("Domain: " + domain);
660:                            sublog.append('\n');
661:                        }
662:
663:                        addBytes(userBytes);
664:                        if (username.length() > 0) {
665:                            sublog.append("User Name: " + username);
666:                            sublog.append('\n');
667:                        }
668:
669:                        addBytes(hostNameBytes);
670:                        if (hostName.length() > 0) {
671:                            sublog.append("Host Name: " + hostName);
672:                            sublog.append('\n');
673:                        }
674:
675:                        String password = getPassword();
676:                        byte[] hash = hashPassword(password != null ? password
677:                                : "");
678:                        addBytes(hash);
679:
680:                        sublog.append("Hash: " + new String(hash));
681:                        sublog.append('\n');
682:
683:                    } else {
684:                        int responseLength = 64;
685:                        byte[] responseLengthShortBytes = convertToShortValue(responseLength);
686:                        initResponse(responseLength);
687:
688:                        addBytes(protocol);
689:                        addByte((byte) 0);
690:
691:                        //Type3
692:                        addByte((byte) 3);
693:                        addByte((byte) 0);
694:                        addByte((byte) 0);
695:                        addByte((byte) 0);
696:
697:                        // LM Response Length 
698:                        addByte((byte) 0);
699:                        addByte((byte) 0);
700:                        // LM Response allocated space
701:                        addByte((byte) 0);
702:                        addByte((byte) 0);
703:
704:                        // LM Response Offset
705:                        addBytes(responseLengthShortBytes);
706:                        addByte((byte) 0);
707:                        addByte((byte) 0);
708:
709:                        // NTLM Response Length 
710:                        addByte((byte) 0);
711:                        addByte((byte) 0);
712:                        // NTLM Response allocated space
713:                        addByte((byte) 0);
714:                        addByte((byte) 0);
715:                        // NTLM Response Offset
716:                        addBytes(responseLengthShortBytes);
717:                        addByte((byte) 0);
718:                        addByte((byte) 0);
719:
720:                        // Domain length
721:                        addByte((byte) 0);
722:                        addByte((byte) 0);
723:                        // Domain allocated space
724:                        addByte((byte) 0);
725:                        addByte((byte) 0);
726:                        // Domain Offset
727:                        addBytes(responseLengthShortBytes);
728:                        addByte((byte) 0);
729:                        addByte((byte) 0);
730:
731:                        // Username Length 
732:                        addByte((byte) 0);
733:                        addByte((byte) 0);
734:                        // Username allocated space
735:                        addByte((byte) 0);
736:                        addByte((byte) 0);
737:                        // User offset
738:                        addBytes(responseLengthShortBytes);
739:                        addByte((byte) 0);
740:                        addByte((byte) 0);
741:
742:                        // Host name length
743:                        addByte((byte) 0);
744:                        addByte((byte) 0);
745:                        // Host name allocated space
746:                        addByte((byte) 0);
747:                        addByte((byte) 0);
748:                        // Host offset
749:                        addBytes(responseLengthShortBytes);
750:
751:                        for (int i = 0; i < 6; i++) {
752:                            addByte((byte) 0);
753:                        }
754:
755:                        // Message length
756:                        addBytes(responseLengthShortBytes);
757:                        addByte((byte) 0);
758:                        addByte((byte) 0);
759:
760:                        // Flags
761:                        addByte((byte) (flags & 0xff));
762:                        addByte((byte) ((flags >> 8) & 0xff));
763:                        addByte((byte) ((flags >> 16) & 0xff));
764:                        addByte((byte) ((flags >> 24) & 0xff));
765:                    }
766:                    setType1State();
767:                }
768:
769:                StringBuffer log = new StringBuffer();
770:                String message = new String(myResponse, 0, myPosition);
771:                log.append("NTLM auth message: " + message);
772:                log.append('\n');
773:                log.append("Length: " + message.length());
774:                log.append('\n');
775:                log.append(sublog);
776:
777:                return "NTLM " + getResponse();
778:            }
779:
780:            private boolean isUpperCase() {
781:                String upperCase = System.getProperty(
782:                        NTLM_CASE_CONVERTION_PROPERTY, System.getProperty(
783:                                OLD_NTLM_CASE_CONVERTION_PROPERTY, "true"));
784:                return Boolean.valueOf(upperCase).booleanValue();
785:            }
786:
787:            private byte[] hashPassword(String password) throws SVNException {
788:                byte[] passw = isUpperCase() ? password.toUpperCase()
789:                        .getBytes() : password.getBytes();
790:                byte[] lmPw1 = new byte[7];
791:                byte[] lmPw2 = new byte[7];
792:
793:                int len = passw.length;
794:                if (len > 7) {
795:                    len = 7;
796:                }
797:
798:                int idx;
799:                for (idx = 0; idx < len; idx++) {
800:                    lmPw1[idx] = passw[idx];
801:                }
802:
803:                for (; idx < 7; idx++) {
804:                    lmPw1[idx] = (byte) 0;
805:                }
806:
807:                len = passw.length;
808:                if (len > 14) {
809:                    len = 14;
810:                }
811:                for (idx = 7; idx < len; idx++) {
812:                    lmPw2[idx - 7] = passw[idx];
813:                }
814:                for (; idx < 14; idx++) {
815:                    lmPw2[idx - 7] = (byte) 0;
816:                }
817:
818:                byte[] lmHpw1;
819:                lmHpw1 = encrypt(lmPw1, ourMagicBytes);
820:
821:                byte[] lmHpw2 = encrypt(lmPw2, ourMagicBytes);
822:
823:                byte[] lmHpw = new byte[21];
824:                for (int i = 0; i < lmHpw1.length; i++) {
825:                    lmHpw[i] = lmHpw1[i];
826:                }
827:                for (int i = 0; i < lmHpw2.length; i++) {
828:                    lmHpw[i + 8] = lmHpw2[i];
829:                }
830:                for (int i = 0; i < 5; i++) {
831:                    lmHpw[i + 16] = (byte) 0;
832:                }
833:
834:                // Create the responses.
835:                byte[] lmResp = new byte[24];
836:                calcResp(lmHpw, lmResp);
837:
838:                return lmResp;
839:            }
840:
841:            private void calcResp(byte[] keys, byte[] results)
842:                    throws SVNException {
843:                byte[] keys1 = new byte[7];
844:                byte[] keys2 = new byte[7];
845:                byte[] keys3 = new byte[7];
846:
847:                for (int i = 0; i < 7; i++) {
848:                    keys1[i] = keys[i];
849:                }
850:
851:                for (int i = 0; i < 7; i++) {
852:                    keys2[i] = keys[i + 7];
853:                }
854:
855:                for (int i = 0; i < 7; i++) {
856:                    keys3[i] = keys[i + 14];
857:                }
858:
859:                byte[] results1 = encrypt(keys1, myNonce);
860:
861:                byte[] results2 = encrypt(keys2, myNonce);
862:
863:                byte[] results3 = encrypt(keys3, myNonce);
864:
865:                for (int i = 0; i < 8; i++) {
866:                    results[i] = results1[i];
867:                }
868:
869:                for (int i = 0; i < 8; i++) {
870:                    results[i + 8] = results2[i];
871:                }
872:
873:                for (int i = 0; i < 8; i++) {
874:                    results[i + 16] = results3[i];
875:                }
876:            }
877:
878:            private byte[] encrypt(byte[] key, byte[] bytes)
879:                    throws SVNException {
880:                Cipher ecipher = getCipher(key);
881:                try {
882:                    byte[] enc = ecipher.doFinal(bytes);
883:                    return enc;
884:                } catch (IllegalBlockSizeException e) {
885:                    SVNErrorMessage err = SVNErrorMessage.create(
886:                            SVNErrorCode.IO_ERROR,
887:                            "Invalid block size for DES encryption: {0}", e
888:                                    .getLocalizedMessage());
889:                    SVNErrorManager.error(err);
890:                } catch (BadPaddingException e) {
891:                    SVNErrorMessage err = SVNErrorMessage
892:                            .create(
893:                                    SVNErrorCode.IO_ERROR,
894:                                    "Data not padded correctly for DES encryption: {0}",
895:                                    e.getLocalizedMessage());
896:                    SVNErrorManager.error(err);
897:                }
898:                return null;
899:            }
900:
901:            private Cipher getCipher(byte[] key) throws SVNException {
902:                try {
903:                    final Cipher ecipher = Cipher
904:                            .getInstance("DES/ECB/NoPadding");
905:                    key = setupKey(key);
906:                    ecipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key,
907:                            "DES"));
908:                    return ecipher;
909:                } catch (NoSuchAlgorithmException e) {
910:                    SVNErrorMessage err = SVNErrorMessage.create(
911:                            SVNErrorCode.IO_ERROR,
912:                            "DES encryption is not available: {0}", e
913:                                    .getLocalizedMessage());
914:                    SVNErrorManager.error(err);
915:                } catch (InvalidKeyException e) {
916:                    SVNErrorMessage err = SVNErrorMessage.create(
917:                            SVNErrorCode.IO_ERROR,
918:                            "Invalid key for DES encryption: {0}", e
919:                                    .getLocalizedMessage());
920:                    SVNErrorManager.error(err);
921:                } catch (NoSuchPaddingException e) {
922:                    SVNErrorMessage err = SVNErrorMessage.create(
923:                            SVNErrorCode.IO_ERROR,
924:                            "NoPadding option for DES is not available: {0}", e
925:                                    .getLocalizedMessage());
926:                    SVNErrorManager.error(err);
927:                }
928:                return null;
929:            }
930:
931:            private byte[] setupKey(byte[] key56) {
932:                byte[] key = new byte[8];
933:                key[0] = (byte) ((key56[0] >> 1) & 0xff);
934:                key[1] = (byte) ((((key56[0] & 0x01) << 6) | (((key56[1] & 0xff) >> 2) & 0xff)) & 0xff);
935:                key[2] = (byte) ((((key56[1] & 0x03) << 5) | (((key56[2] & 0xff) >> 3) & 0xff)) & 0xff);
936:                key[3] = (byte) ((((key56[2] & 0x07) << 4) | (((key56[3] & 0xff) >> 4) & 0xff)) & 0xff);
937:                key[4] = (byte) ((((key56[3] & 0x0f) << 3) | (((key56[4] & 0xff) >> 5) & 0xff)) & 0xff);
938:                key[5] = (byte) ((((key56[4] & 0x1f) << 2) | (((key56[5] & 0xff) >> 6) & 0xff)) & 0xff);
939:                key[6] = (byte) ((((key56[5] & 0x3f) << 1) | (((key56[6] & 0xff) >> 7) & 0xff)) & 0xff);
940:                key[7] = (byte) (key56[6] & 0x7f);
941:
942:                for (int i = 0; i < key.length; i++) {
943:                    key[i] = (byte) (key[i] << 1);
944:                }
945:                return key;
946:            }
947:
948:            public String getAuthenticationScheme() {
949:                return "NTLM";
950:            }
951:
952:        }
ww_w__.___j__av_a2___s.__c__o___m | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.