[jcifs] Fail-over capability with WINS

Eric Glass eric.glass at gmail.com
Fri Dec 1 12:27:12 GMT 2006


> Go for it. I recommend using JNDI to do an SRV lookup for
> _ldap._tcp.example.com to get the list of DCs. Then post a patch and
> we'll drop it in the patches directory. I'm sure it would be appreciated.
>

Here it is (patch against 1.2.11b).  This actually does a SRV lookup
against "_ldap._tcp.dc._msdcs.example.com" (to further qualify the
results as domain controllers rather than just LDAP servers, although
in practice it probably wouldn't make a difference).

This kicks in when SmbSession.getChallengeForDomain() is called; if no
WINS server is configured (NbtAddress.getWINSAddress() returns null),
then the DNS SRV lookup is performed against the domain specified in
"jcifs.smb.client.domain", and the DC list is populated from the
result.  Obviously in this case jcifs.smb.client.domain would need to
specify a DNS-style domain (e.g. "example.com") rather than
NetBIOS-style ("EXAMPLE").  You would also need to specify
jcifs.http.loadBalance=true for the NtlmFilter configuration (which
makes sense, since if you weren't load balancing the domain
controllers you wouldn't really need this functionality for the filter
anyway).

This has a slight side effect on preauthentication/signing, as that
also uses the jcifs.smb.client.domain property; the preauthentication
would be done against the DNS-style domain name rather than NetBIOS
style (i.e. authenticating as "example.com\username" rather than
"EXAMPLE\username").  This should work fine though (it does for me);
any domain controller listed in the SRV results is going to be Win2K+,
and should support the DNS-style domain name for NTLM authentication.


Eric
-------------- next part --------------
diff -Naur old-src/jcifs/smb/SmbSession.java src/jcifs/smb/SmbSession.java
--- old-src/jcifs/smb/SmbSession.java	2006-11-29 12:12:52.000000000 -0500
+++ src/jcifs/smb/SmbSession.java	2006-12-01 06:52:28.498008700 -0500
@@ -18,6 +18,8 @@
 
 package jcifs.smb;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Vector;
 import java.util.Enumeration;
 import java.net.InetAddress;
@@ -26,6 +28,11 @@
 import jcifs.UniAddress;
 import jcifs.netbios.NbtAddress;
 
+import javax.naming.NamingException;
+
+import javax.naming.directory.Attributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.InitialDirContext;
 /**
  * The class represents a user's session established with an SMB/CIFS
  * server. This class is used internally to the jCIFS library however
@@ -63,12 +70,11 @@
     private static final int CACHE_POLICY =
                 Config.getInt( "jcifs.netbios.cachePolicy", 60 * 10 ) * 60; /* 10 hours */
 
-    static NbtAddress[] dc_list = null;
+    static UniAddress[] dc_list = null;
     static long dc_list_expiration;
     static int dc_list_counter;
 
-    private static NtlmChallenge interrogate( NbtAddress addr ) throws SmbException {
-        UniAddress dc = new UniAddress( addr );
+    private static NtlmChallenge interrogate( UniAddress dc ) throws SmbException {
         SmbTransport trans = SmbTransport.getSmbTransport( dc, 0 );
         if (USERNAME == null) {
             trans.connect();
@@ -95,13 +101,59 @@
 do {
             if (dc_list_expiration < now) {
                 dc_list_expiration = now + CACHE_POLICY * 1000L;
-                NbtAddress[] list = NbtAddress.getAllByName( DOMAIN, 0x1C, null, null );
-                if (list != null && list.length > 0) {
+                UniAddress[] list = null;
+                if (NbtAddress.getWINSAddress() != null) {
+                    NbtAddress[] nbt_list = NbtAddress.getAllByName( DOMAIN,
+                            0x1C, null, null );
+                    if (nbt_list != null && nbt_list.length > 0) {
+                        list = new UniAddress[nbt_list.length];
+                        for (int i = 0; i < list.length; i++) {
+                            list[i] = new UniAddress(nbt_list[i]);
+                        }
+                    }
+                } else {
+                    try {
+                        DirContext context = new InitialDirContext();
+                        Attributes attributes = context.getAttributes(
+                                "dns:/_ldap._tcp.dc._msdcs." + DOMAIN,
+                                        new String[] { "SRV" });
+                        Enumeration values = attributes.get("SRV").getAll();
+                        List results = new ArrayList();
+                        while (values.hasMoreElements()) {
+                            String value = (String) values.nextElement();
+                            value = value.replaceFirst(
+                                    "^\\d* \\d* \\d+ (.*)\\.$", "$1");
+                            try {
+                                InetAddress server =
+                                        InetAddress.getByName(value);
+                                results.add(new UniAddress(server));
+                            } catch (UnknownHostException ex) {
+                                if (SmbTransport.log.level >= 2) {
+                                    SmbTransport.log.println(
+                                            "Unable to resolve DC SRV entry: " +
+                                                    value);
+                                    if (SmbTransport.log.level > 2) {
+                                        ex.printStackTrace(SmbTransport.log);
+                                    }
+                                }
+                            }
+                        }
+                        if (!results.isEmpty()) {
+                            list = (UniAddress[])
+                                    results.toArray(new UniAddress[0]);
+                        }
+                    } catch (NamingException ne) {
+                        if (SmbTransport.log.level > 2) {
+                            ne.printStackTrace(SmbTransport.log);
+                        }
+                    }
+                }
+                if (list != null) {
                     dc_list = list;
                 } else { /* keep using the old list */
                     dc_list_expiration = now + 1000 * 60 * 15; /* 15 min */
                     if (SmbTransport.log.level >= 2) {
-                        SmbTransport.log.println( "Failed to retrieve DC list from WINS" );
+                        SmbTransport.log.println( "Failed to retrieve DC list" );
                     }
                 }
             }


More information about the jcifs mailing list