View Javadoc
1   package org.eclipse.aether.transport.http;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   * 
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   * 
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.net.InetAddress;
23  import java.net.UnknownHostException;
24  import java.util.HashMap;
25  import java.util.Iterator;
26  import java.util.Map;
27  
28  import org.apache.http.auth.AuthScope;
29  import org.apache.http.auth.Credentials;
30  import org.apache.http.auth.NTCredentials;
31  import org.apache.http.auth.UsernamePasswordCredentials;
32  import org.apache.http.client.CredentialsProvider;
33  import org.apache.http.impl.client.BasicCredentialsProvider;
34  import org.eclipse.aether.repository.AuthenticationContext;
35  
36  /**
37   * Credentials provider that defers calls into the auth context until authentication is actually requested.
38   */
39  final class DeferredCredentialsProvider
40      implements CredentialsProvider
41  {
42  
43      private final CredentialsProvider delegate;
44  
45      private final Map<AuthScope, Factory> factories;
46  
47      DeferredCredentialsProvider()
48      {
49          delegate = new BasicCredentialsProvider();
50          factories = new HashMap<>();
51      }
52  
53      public void setCredentials( AuthScope authScope, Factory factory )
54      {
55          factories.put( authScope, factory );
56      }
57  
58      @Override
59      public void setCredentials( AuthScope authScope, Credentials credentials )
60      {
61          delegate.setCredentials( authScope, credentials );
62      }
63  
64      @Override
65      public Credentials getCredentials( AuthScope authScope )
66      {
67          synchronized ( factories )
68          {
69              for ( Iterator<Map.Entry<AuthScope, Factory>> it = factories.entrySet().iterator(); it.hasNext(); )
70              {
71                  Map.Entry<AuthScope, Factory> entry = it.next();
72                  if ( authScope.match( entry.getKey() ) >= 0 )
73                  {
74                      it.remove();
75                      delegate.setCredentials( entry.getKey(), entry.getValue().newCredentials() );
76                  }
77              }
78          }
79          return delegate.getCredentials( authScope );
80      }
81  
82      @Override
83      public void clear()
84      {
85          delegate.clear();
86      }
87  
88      interface Factory
89      {
90  
91          Credentials newCredentials();
92  
93      }
94  
95      static class BasicFactory
96          implements Factory
97      {
98  
99          private final AuthenticationContext authContext;
100 
101         BasicFactory( AuthenticationContext authContext )
102         {
103             this.authContext = authContext;
104         }
105 
106         @Override
107         public Credentials newCredentials()
108         {
109             String username = authContext.get( AuthenticationContext.USERNAME );
110             if ( username == null )
111             {
112                 return null;
113             }
114             String password = authContext.get( AuthenticationContext.PASSWORD );
115             return new UsernamePasswordCredentials( username, password );
116         }
117 
118     }
119 
120     static class NtlmFactory
121         implements Factory
122     {
123 
124         private final AuthenticationContext authContext;
125 
126         NtlmFactory( AuthenticationContext authContext )
127         {
128             this.authContext = authContext;
129         }
130 
131         @Override
132         public Credentials newCredentials()
133         {
134             String username = authContext.get( AuthenticationContext.USERNAME );
135             if ( username == null )
136             {
137                 return null;
138             }
139             String password = authContext.get( AuthenticationContext.PASSWORD );
140             String domain = authContext.get( AuthenticationContext.NTLM_DOMAIN );
141             String workstation = authContext.get( AuthenticationContext.NTLM_WORKSTATION );
142 
143             if ( domain == null )
144             {
145                 int backslash = username.indexOf( '\\' );
146                 if ( backslash < 0 )
147                 {
148                     domain = guessDomain();
149                 }
150                 else
151                 {
152                     domain = username.substring( 0, backslash );
153                     username = username.substring( backslash + 1 );
154                 }
155             }
156             if ( workstation == null )
157             {
158                 workstation = guessWorkstation();
159             }
160 
161             return new NTCredentials( username, password, workstation, domain );
162         }
163 
164         private static String guessDomain()
165         {
166             return safeNtlmString( System.getProperty( "http.auth.ntlm.domain" ), System.getenv( "USERDOMAIN" ) );
167         }
168 
169         private static String guessWorkstation()
170         {
171             String localHost = null;
172             try
173             {
174                 localHost = InetAddress.getLocalHost().getHostName();
175             }
176             catch ( UnknownHostException e )
177             {
178                 // well, we have other options to try
179             }
180             return safeNtlmString( System.getProperty( "http.auth.ntlm.host" ), System.getenv( "COMPUTERNAME" ),
181                                    localHost );
182         }
183 
184         private static String safeNtlmString( String... strings )
185         {
186             for ( String string : strings )
187             {
188                 if ( string != null )
189                 {
190                     return string;
191                 }
192             }
193             // avoid NPE from httpclient and trigger proper auth failure instead
194             return "";
195         }
196 
197     }
198 
199 }