1
1
/*
2
- * Copyright (c) 2012-2013 Sonatype, Inc. All rights reserved.
2
+ * Copyright (c) 2012 Sonatype, Inc. All rights reserved.
3
3
*
4
4
* This program is licensed to you under the Apache License Version 2.0,
5
5
* and you may not use this file except in compliance with the Apache License Version 2.0.
39
39
import com .ning .http .client .filter .FilterContext ;
40
40
import com .ning .http .client .filter .ResponseFilter ;
41
41
import com .ning .http .client .listener .TransferCompletionHandler ;
42
+ import com .ning .http .client .ntlm .NTLMEngine ;
42
43
import com .ning .http .client .websocket .WebSocket ;
43
44
import com .ning .http .client .websocket .WebSocketByteListener ;
44
45
import com .ning .http .client .websocket .WebSocketCloseCodeReasonListener ;
@@ -172,8 +173,7 @@ public class GrizzlyAsyncHttpProvider implements AsyncHttpProvider {
172
173
DelayedExecutor .Resolver <Connection > resolver ;
173
174
private DelayedExecutor timeoutExecutor ;
174
175
175
-
176
-
176
+ private final static NTLMEngine ntlmEngine = new NTLMEngine ();
177
177
178
178
// ------------------------------------------------------------ Constructors
179
179
@@ -222,7 +222,9 @@ public void completed(final Connection c) {
222
222
try {
223
223
execute (c , request , handler , future );
224
224
} catch (Exception e ) {
225
- if (e instanceof IOException ) {
225
+ if (e instanceof RuntimeException ) {
226
+ failed (e );
227
+ } else if (e instanceof IOException ) {
226
228
failed (e );
227
229
}
228
230
if (LOGGER .isWarnEnabled ()) {
@@ -399,7 +401,7 @@ public void onTimeout(Connection connection) {
399
401
}
400
402
fcb .add (eventFilter );
401
403
fcb .add (clientFilter );
402
-
404
+
403
405
if (providerConfig != null ) {
404
406
final TransportCustomizer customizer = (TransportCustomizer )
405
407
providerConfig .getProperty (TRANSPORT_CUSTOMIZER );
@@ -435,6 +437,7 @@ void touchConnection(final Connection c, final Request request) {
435
437
436
438
// --------------------------------------------------------- Private Methods
437
439
440
+
438
441
private static boolean configSendFileSupport () {
439
442
440
443
return !((System .getProperty ("os.name" ).equalsIgnoreCase ("linux" )
@@ -933,6 +936,18 @@ private void convertToUpgradeRequest(final HttpTransactionContext ctx) {
933
936
ctx .requestUrl = sb .toString ();
934
937
}
935
938
939
+
940
+ /* private ProxyServer getProxyServer(Request request) {
941
+
942
+ ProxyServer proxyServer = request.getProxyServer();
943
+ if (proxyServer == null) {
944
+ proxyServer = config.getProxyServer();
945
+ }
946
+ return proxyServer;
947
+
948
+ }*/
949
+
950
+
936
951
private void addHeaders (final Request request ,
937
952
final HttpRequestPacket requestPacket ,
938
953
final ProxyServer proxy ) throws IOException {
@@ -970,8 +985,9 @@ private void addHeaders(final Request request,
970
985
requestPacket .setHeader (Header .ProxyConnection , "keep-alive" );
971
986
}
972
987
973
- if (proxy .getPrincipal () != null && proxy .isBasic ()) {
974
- requestPacket .setHeader (Header .ProxyAuthorization , AuthenticatorUtils .computeBasicAuthentication (proxy ));
988
+ if (null == requestPacket .getHeader (Header .ProxyAuthorization ) )
989
+ {
990
+ requestPacket .setHeader (Header .ProxyAuthorization , AuthenticatorUtils .computeBasicAuthentication (proxy ));
975
991
}
976
992
977
993
}
@@ -1367,10 +1383,18 @@ protected void onHttpHeadersParsed(HttpHeader httpHeader,
1367
1383
protected boolean onHttpPacketParsed (HttpHeader httpHeader , FilterChainContext ctx ) {
1368
1384
1369
1385
boolean result ;
1370
- if (httpHeader .isSkipRemainder ()) {
1371
- clearResponse (ctx .getConnection ());
1372
- cleanup (ctx , provider );
1373
- return false ;
1386
+ final String proxy_auth = httpHeader .getHeader (Header .ProxyAuthenticate );
1387
+
1388
+ if (httpHeader .isSkipRemainder () ) {
1389
+ if (!ProxyAuthorizationHandler .isNTLMSecondHandShake (proxy_auth )) {
1390
+ clearResponse (ctx .getConnection ());
1391
+ cleanup (ctx , provider );
1392
+ return false ;
1393
+ } else {
1394
+ super .onHttpPacketParsed (httpHeader , ctx );
1395
+ httpHeader .getProcessingState ().setKeepAlive (true );
1396
+ return false ;
1397
+ }
1374
1398
}
1375
1399
1376
1400
result = super .onHttpPacketParsed (httpHeader , ctx );
@@ -1453,6 +1477,14 @@ private static HttpTransactionContext cleanup(final FilterChainContext ctx,
1453
1477
1454
1478
}
1455
1479
1480
+
1481
+ private static URI getURI (String url ) {
1482
+
1483
+ return AsyncHttpProviderUtils .createUri (url );
1484
+
1485
+ }
1486
+
1487
+
1456
1488
private static boolean redirectCountExceeded (final HttpTransactionContext context ) {
1457
1489
1458
1490
return (context .redirectCount .get () > context .maxRedirectCount );
@@ -1590,7 +1622,7 @@ public boolean handleStatus(final HttpResponsePacket responsePacket,
1590
1622
String principal = proxyServer .getPrincipal ();
1591
1623
String password = proxyServer .getPassword ();
1592
1624
Realm realm = new Realm .RealmBuilder ().setPrincipal (principal )
1593
- .setPassword (password )
1625
+ .setPassword (password )
1594
1626
.setUri ("/" )
1595
1627
.setMethodName ("CONNECT" )
1596
1628
.setUsePreemptiveAuth (true )
@@ -1615,36 +1647,123 @@ public boolean handleStatus(final HttpResponsePacket responsePacket,
1615
1647
} catch (UnsupportedEncodingException e ) {
1616
1648
throw new IllegalStateException ("Unsupported encoding." , e );
1617
1649
}
1618
- } else {
1650
+ }else if (proxy_auth .toLowerCase ().startsWith ("ntlm" )) {
1651
+
1652
+ req .getHeaders ().remove (Header .ProxyAuthenticate .toString ());
1653
+ req .getHeaders ().remove (Header .ProxyAuthorization .toString ());
1654
+
1655
+ String msg = null ;
1656
+ try {
1657
+
1658
+ if (isNTLMFirstHandShake (proxy_auth ))
1659
+ {
1660
+ msg = ntlmEngine .generateType1Msg (proxyServer .getNtlmDomain (), "" );
1661
+ }else {
1662
+ String serverChallenge = proxy_auth .trim ().substring ("NTLM " .length ());
1663
+ msg = ntlmEngine .generateType3Msg (principal , password , proxyServer .getNtlmDomain (), proxyServer .getHost (), serverChallenge );
1664
+ }
1665
+
1666
+ req .getHeaders ().add (Header .ProxyAuthorization .toString (), "NTLM " + msg );
1667
+ } catch (Exception e1 ) {
1668
+ e1 .printStackTrace ();
1669
+ }
1670
+ } else if (proxy_auth .toLowerCase ().startsWith ("negotiate" )){
1671
+ //this is for kerberos
1672
+ req .getHeaders ().remove (Header .ProxyAuthenticate .toString ());
1673
+ req .getHeaders ().remove (Header .ProxyAuthorization .toString ());
1674
+
1675
+ }else {
1619
1676
throw new IllegalStateException ("Unsupported authorization method: " + proxy_auth );
1620
1677
}
1621
1678
1622
1679
final ConnectionManager m = httpTransactionContext .provider .connectionManager ;
1680
+ InvocationStatus tempInvocationStatus = InvocationStatus .STOP ;
1681
+
1623
1682
try {
1624
- final Connection c = m .obtainConnection (req ,
1625
- httpTransactionContext .future );
1626
- final HttpTransactionContext newContext =
1627
- httpTransactionContext .copy ();
1628
- httpTransactionContext .future = null ;
1629
- httpTransactionContext .provider .setHttpTransactionContext (c , newContext );
1630
- newContext .invocationStatus = InvocationStatus .STOP ;
1631
- try {
1632
- httpTransactionContext .provider .execute (c ,
1633
- req ,
1634
- httpTransactionContext .handler ,
1635
- httpTransactionContext .future );
1636
- return false ;
1637
- } catch (IOException ioe ) {
1638
- newContext .abort (ioe );
1639
- return false ;
1683
+
1684
+ if (isNTLMFirstHandShake (proxy_auth ))
1685
+ {
1686
+ tempInvocationStatus = InvocationStatus .CONTINUE ;
1687
+
1688
+ }
1689
+
1690
+ if (proxy_auth .toLowerCase ().startsWith ("negotiate" ))
1691
+ {
1692
+ final Connection c = m .obtainConnection (req , httpTransactionContext .future );
1693
+ final HttpTransactionContext newContext = httpTransactionContext .copy ();
1694
+ httpTransactionContext .future = null ;
1695
+ httpTransactionContext .provider .setHttpTransactionContext (c , newContext );
1696
+
1697
+ newContext .invocationStatus = tempInvocationStatus ;
1698
+
1699
+ String challengeHeader = null ;
1700
+ String server = proxyServer .getHost ();
1701
+
1702
+ challengeHeader = GSSSPNEGOWrapper .generateToken (server );
1703
+
1704
+ req .getHeaders ().add (Header .ProxyAuthorization .toString (), "Negotiate " + challengeHeader );
1705
+
1706
+
1707
+ return exceuteRequest (httpTransactionContext , req , c ,
1708
+ newContext );
1709
+ }else if (isNTLMSecondHandShake (proxy_auth ))
1710
+ {
1711
+ final Connection c = ctx .getConnection ();
1712
+ final HttpTransactionContext newContext = httpTransactionContext .copy ();
1713
+
1714
+ httpTransactionContext .future = null ;
1715
+ httpTransactionContext .provider .setHttpTransactionContext (c , newContext );
1716
+
1717
+ newContext .invocationStatus = tempInvocationStatus ;
1718
+ httpTransactionContext .establishingTunnel = true ;
1719
+
1720
+ return exceuteRequest (httpTransactionContext , req , c ,
1721
+ newContext );
1722
+
1723
+ }
1724
+ else {
1725
+ final Connection c = m .obtainConnection (req , httpTransactionContext .future );
1726
+ final HttpTransactionContext newContext = httpTransactionContext .copy ();
1727
+ httpTransactionContext .future = null ;
1728
+ httpTransactionContext .provider .setHttpTransactionContext (c , newContext );
1729
+
1730
+ newContext .invocationStatus = tempInvocationStatus ;
1731
+
1732
+ //NTLM needs the same connection to be used for exchange of tokens
1733
+ return exceuteRequest (httpTransactionContext , req , c ,
1734
+ newContext );
1640
1735
}
1641
1736
} catch (Exception e ) {
1642
1737
httpTransactionContext .abort (e );
1643
1738
}
1644
- httpTransactionContext .invocationStatus = InvocationStatus . STOP ;
1739
+ httpTransactionContext .invocationStatus = tempInvocationStatus ;
1645
1740
return false ;
1646
1741
}
1647
1742
1743
+ private boolean exceuteRequest (
1744
+ final HttpTransactionContext httpTransactionContext ,
1745
+ final Request req , final Connection c ,
1746
+ final HttpTransactionContext newContext ) {
1747
+ try {
1748
+ httpTransactionContext .provider .execute (c ,
1749
+ req ,
1750
+ httpTransactionContext .handler ,
1751
+ httpTransactionContext .future );
1752
+ return false ;
1753
+ } catch (IOException ioe ) {
1754
+ newContext .abort (ioe );
1755
+ return false ;
1756
+ }
1757
+ }
1758
+
1759
+ public static boolean isNTLMSecondHandShake (final String proxy_auth ) {
1760
+ return (proxy_auth .toLowerCase ().startsWith ("ntlm" ) && !proxy_auth .equalsIgnoreCase ("ntlm" ));
1761
+ }
1762
+ public static boolean isNTLMFirstHandShake (final String proxy_auth ) {
1763
+ return (proxy_auth .equalsIgnoreCase ("ntlm" ));
1764
+ }
1765
+
1766
+
1648
1767
} // END AuthorizationHandler
1649
1768
1650
1769
@@ -2418,6 +2537,7 @@ Connection obtainConnection(final Request request,
2418
2537
final Connection c = obtainConnection0 (request , requestFuture , requestFuture .getProxyServer ());
2419
2538
markConnectionAsDoNotCache (c );
2420
2539
return c ;
2540
+
2421
2541
}
2422
2542
2423
2543
void doAsyncConnect (final Request request ,
@@ -2472,6 +2592,7 @@ boolean returnConnection(final Request request, final Connection c) {
2472
2592
}
2473
2593
}
2474
2594
return result ;
2595
+
2475
2596
}
2476
2597
2477
2598
@@ -2948,4 +3069,7 @@ public int hashCode() {
2948
3069
}
2949
3070
} // END AHCWebSocketListenerAdapter
2950
3071
2951
- }
3072
+ }
3073
+
3074
+
3075
+
0 commit comments