1 18 19 package jcifs.smb; 20 21 import java.util.Vector ; 22 import java.util.Enumeration ; 23 import java.net.InetAddress ; 24 import java.net.UnknownHostException ; 25 import jcifs.Config; 26 import jcifs.UniAddress; 27 import jcifs.netbios.NbtAddress; 28 29 52 53 public final class SmbSession { 54 55 private static final String LOGON_SHARE = 56 Config.getProperty( "jcifs.smb.client.logonShare", null ); 57 private static final int LOOKUP_RESP_LIMIT = 58 Config.getInt( "jcifs.netbios.lookupRespLimit", 3 ); 59 private static final String DOMAIN = 60 Config.getProperty("jcifs.smb.client.domain", null); 61 private static final String USERNAME = 62 Config.getProperty("jcifs.smb.client.username", null); 63 private static final int CACHE_POLICY = 64 Config.getInt( "jcifs.netbios.cachePolicy", 60 * 10 ) * 60; 65 66 static NbtAddress[] dc_list = null; 67 static long dc_list_expiration; 68 static int dc_list_counter; 69 70 private static NtlmChallenge interrogate( NbtAddress addr ) throws SmbException { 71 UniAddress dc = new UniAddress( addr ); 72 SmbTransport trans = SmbTransport.getSmbTransport( dc, 0 ); 73 if (USERNAME == null) { 74 trans.connect(); 75 if (SmbTransport.log.level > 2) 76 SmbTransport.log.println( 77 "Default credentials (jcifs.smb.client.username/password)" + 78 " not specified. SMB signing may not work propertly." + 79 " Skipping DC interrogation." ); 80 } else { 81 SmbSession ssn = trans.getSmbSession( NtlmPasswordAuthentication.DEFAULT ); 82 ssn.getSmbTree( LOGON_SHARE, null ).treeConnect( null, null ); 83 } 84 return new NtlmChallenge( trans.server.encryptionKey, dc ); 85 } 86 public static NtlmChallenge getChallengeForDomain() 87 throws SmbException, UnknownHostException { 88 if( DOMAIN == null ) { 89 throw new SmbException( "A domain was not specified" ); 90 } 91 synchronized (DOMAIN) { 92 long now = System.currentTimeMillis(); 93 if (dc_list_expiration < now) { 94 dc_list_expiration = now + CACHE_POLICY * 1000L; 95 NbtAddress[] list = NbtAddress.getAllByName( DOMAIN, 0x1C, null, null ); 96 if (list != null && list.length > 0) { 97 dc_list = list; 98 } else { 99 dc_list_expiration = now + 1000 * 60 * 15; 100 if (SmbTransport.log.level > 1) { 101 SmbTransport.log.println( "Failed to retrieve DC list from WINS" ); 102 } 103 } 104 } 105 106 int max = Math.min( dc_list.length, LOOKUP_RESP_LIMIT ); 107 for (int j = 0; j < max; j++) { 108 int i = dc_list_counter++ % max; 109 if (dc_list[i] != null) { 110 try { 111 return interrogate( dc_list[i] ); 112 } catch (SmbException se) { 113 if (SmbTransport.log.level > 1) { 114 SmbTransport.log.println( "Failed validate DC: " + dc_list[i] ); 115 if (SmbTransport.log.level > 2) 116 se.printStackTrace( SmbTransport.log ); 117 } 118 } 119 dc_list[i] = null; 120 } 121 } 122 123 dc_list_expiration = now + 1000 * 60 * 15; 124 } 125 126 throw new UnknownHostException ( 127 "Failed to negotiate with a suitable domain controller for " + DOMAIN ); 128 } 129 130 public static byte[] getChallenge( UniAddress dc ) 131 throws SmbException, UnknownHostException { 132 return getChallenge(dc, 0); 133 } 134 135 public static byte[] getChallenge( UniAddress dc, int port ) 136 throws SmbException, UnknownHostException { 137 SmbTransport trans = SmbTransport.getSmbTransport( dc, port ); 138 trans.connect(); 139 return trans.server.encryptionKey; 140 } 141 152 public static void logon( UniAddress dc, 153 NtlmPasswordAuthentication auth ) throws SmbException { 154 logon(dc, 0, auth); 155 } 156 157 public static void logon( UniAddress dc, int port, 158 NtlmPasswordAuthentication auth ) throws SmbException { 159 SmbTree tree = SmbTransport.getSmbTransport( dc, port ).getSmbSession( auth ).getSmbTree( LOGON_SHARE, null ); 160 if( LOGON_SHARE == null ) { 161 tree.treeConnect( null, null ); 162 } else { 163 Trans2FindFirst2 req = new Trans2FindFirst2( "\\", "*", SmbFile.ATTR_DIRECTORY ); 164 Trans2FindFirst2Response resp = new Trans2FindFirst2Response(); 165 tree.send( req, resp ); 166 } 167 } 168 169 private int uid; 170 private Vector trees; 171 private boolean sessionSetup; 172 private UniAddress address; 174 private int port, localPort; 175 private InetAddress localAddr; 176 177 SmbTransport transport = null; 178 NtlmPasswordAuthentication auth; 179 long expiration; 180 181 SmbSession( UniAddress address, int port, 182 InetAddress localAddr, int localPort, 183 NtlmPasswordAuthentication auth ) { 184 this.address = address; 185 this.port = port; 186 this.localAddr = localAddr; 187 this.localPort = localPort; 188 this.auth = auth; 189 trees = new Vector (); 190 } 191 192 synchronized SmbTree getSmbTree( String share, String service ) { 193 SmbTree t; 194 195 if( share == null ) { 196 share = "IPC$"; 197 } 198 for( Enumeration e = trees.elements(); e.hasMoreElements(); ) { 199 t = (SmbTree)e.nextElement(); 200 if( t.matches( share, service )) { 201 return t; 202 } 203 } 204 t = new SmbTree( this, share, service ); 205 trees.addElement( t ); 206 return t; 207 } 208 boolean matches( NtlmPasswordAuthentication auth ) { 209 return this.auth == auth || this.auth.equals( auth ); 210 } 211 synchronized SmbTransport transport() { 212 if( transport == null ) { 213 transport = SmbTransport.getSmbTransport( address, port, localAddr, localPort ); 214 } 215 return transport; 216 } 217 void send( ServerMessageBlock request, 218 ServerMessageBlock response ) throws SmbException { 219 if( response != null ) { 220 response.received = false; 221 } 222 expiration = System.currentTimeMillis() + SmbTransport.SO_TIMEOUT; 223 sessionSetup( request, response ); 224 if( response != null && response.received ) { 225 return; 226 } 227 request.uid = uid; 228 request.auth = auth; 229 transport.send( request, response ); 230 } 231 void sessionSetup( ServerMessageBlock andx, 232 ServerMessageBlock andxResponse ) throws SmbException { 233 synchronized( transport() ) { 234 if( sessionSetup ) { 235 return; 236 } 237 238 transport.connect(); 239 240 243 244 if( transport.log.level > 3 ) 245 transport.log.println( "sessionSetup: accountName=" + auth.username + ",primaryDomain=" + auth.domain ); 246 247 SmbComSessionSetupAndX request = new SmbComSessionSetupAndX( this, andx ); 248 SmbComSessionSetupAndXResponse response = new SmbComSessionSetupAndXResponse( andxResponse ); 249 250 254 if (transport.isSignatureSetupRequired( auth )) { 255 if( auth.hashesExternal && NtlmPasswordAuthentication.DEFAULT_PASSWORD != NtlmPasswordAuthentication.BLANK ) { 256 258 transport.getSmbSession( NtlmPasswordAuthentication.DEFAULT ).getSmbTree( LOGON_SHARE, null ).treeConnect( null, null ); 259 } 260 request.digest = new SigningDigest( transport, auth ); 261 } 262 263 request.auth = auth; 264 transport.send( request, response ); 265 266 if( response.isLoggedInAsGuest && 267 "GUEST".equalsIgnoreCase( auth.username ) == false) { 268 throw new SmbAuthException( NtStatus.NT_STATUS_LOGON_FAILURE ); 269 } 270 271 uid = response.uid; 272 sessionSetup = true; 273 274 if( request.digest != null ) { 275 276 transport.digest = request.digest; 277 } 278 } 279 } 280 void logoff( boolean inError ) { 281 synchronized( transport() ) { 282 if( sessionSetup == false ) { 283 return; 284 } 285 286 for( Enumeration e = trees.elements(); e.hasMoreElements(); ) { 287 SmbTree t = (SmbTree)e.nextElement(); 288 t.treeDisconnect( inError ); 289 } 290 291 if( !inError && transport.server.security != ServerMessageBlock.SECURITY_SHARE ) { 292 293 296 297 SmbComLogoffAndX request = new SmbComLogoffAndX( null ); 298 request.uid = uid; 299 try { 300 transport.send( request, null ); 301 } catch( SmbException se ) { 302 } 303 } 304 305 sessionSetup = false; 306 } 307 } 308 public String toString() { 309 return "SmbSession[accountName=" + auth.username + 310 ",primaryDomain=" + auth.domain + 311 ",uid=" + uid + 312 ",sessionSetup=" + sessionSetup + "]"; 313 } 314 } 315 | Popular Tags |