- Installation and Setup
- Non MSIE Clients and "Basic" Authentication
- JCIFS Properties Meaningful to NTLM HTTP Authentication
- Must Restart The Container
- Tomcat
- MalformedURLException: unknown protocol: smb
- Transparent Authentication and the Network Password Dialog
- Personal Workstation AD Security Policy
- HTTP POST and Protecting Sub-Content
- SMB Signatures and Windows 2003
- NTLM HTTP Authentication Protocol Details
Installation and Setup
Put the latest jCIFS jar file in the lib/ directory of your webapp [1]. Because jCIFS properties are loaded once when the jCIFS classes are first accessed, it is necessary to actually stop and restart the container if any jCIFS properties have been changed. Below are two web.xml configurations. Note that the jcifs.smb.client.domain and jcifs.smb.client.domainController properties are mutually exclusive.Production web.xml Example
A minimalistic web.xml file with filter and filter-mapping directives might look like the following:<filter> <filter-name>NtlmHttpFilter</filter-name> <filter-class>jcifs.http.NtlmHttpFilter</filter-class> <init-param> <param-name>jcifs.smb.client.domain</param-name> <param-value>NYC-USERS</param-value> </init-param> <init-param> <param-name>jcifs.netbios.wins</param-name> <param-value>10.169.10.77,10.169.10.66</param-value> </init-param> </filter> <filter-mapping> <filter-name>NtlmHttpFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>This filter section illustrates the setup for authenticating clients against the domain NYC-USERS. This is suitable for large numbers of concurrent users as jCIFS will cycle through domain controllers and use an alternate WINS server if necessary. The above will authenticate users accessing all content against the domain NYC-USERS. The WINS server 10.169.10.77 will be queried to resolve NYC-USERS to an IP address of a domain controller. If that WINS server is not responding, 10.169.10.66 will be queried.
Alternate web.xml Example
The below example filter section illistrates how to specify the IP address of the domain controller specifically using the jcifs.http.domainController property. The target machine does not need to be a real domain controller -- it could be just a workstation. Also illustrated below is the jcifs.smb.client.logonShare property. This will cause jCIFS to attempt to access the resource \\192.168.2.15\JCIFSACL when authenticating users. By creating that share and changing the Access Control List only certain users or groups of users will have access to your website.<filter> <filter-name>NtlmHttpFilter</filter-name> <filter-class>jcifs.http.NtlmHttpFilter</filter-class> <init-param> <param-name>jcifs.http.domainController</param-name> <param-value>192.168.2.15</param-value> </init-param> <init-param> <param-name>jcifs.smb.client.logonShare</param-name> <param-value>JCIFSACL</param-value> </init-param> </filter> <filter-mapping> <filter-name>NtlmHttpFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>This filter section illustrates the setup for authenticating against a JCIFSACL share for testing or a site with a small number of concurrent users (e.g. 1000) Either a jcifs.smb.client.domain or jcifs.smb.client.domainController property is required. This will be suitable to authenticate clients that are members of the specified domain as well as other domains with which it has trusts relationships. Running the NtlmHttpAuthExample.java example should be a suitable test of the Filter.
The significance of the POST test is that after negotiating NTLM HTTP Authentication once, IE will not POST any form data until it has negotiated the password hashes again. If the NTLM HTTP Authentication Filter is not enabled something like the following will be displayed:NTLM HTTP Authentication Example
NYC-USERS\MIALLEN successfully logged inPlease submit some form data using POST
field1 = hello
null successfully logged inNotice the user was permitted access. Unlike this example, developers might add an additional check to make sure getRemoteUser does not return null.
Non MSIE Clients and "Basic" Authentication
NTLM HTTP authentication is only supported by MSIE transparently. Mozilla 1.6 supports NTLM HTTP negotiation but it will always prompt the user for credentials by default (although the Mozilla documentation on Integrated Authentication describes how to make it transparent to the user for trusted sites). For other clients it is possible to use basic authentication to pass NTLM password credentials. This is strongly discouraged if SSL is not being used because it sends these credentials in plain text. It would not be difficult for another user to download and install a program to "snoop" LAN traffic and obtain other user's passwords. Regardless, this functionality has been added to the NtlmHttpFilter and NtlmServlet (for pre 2.3 servlet containers) although it is disabled by default. To enable this capability set the jcifs.http.basicRealm, jcifs.http.enableBasic, and jcifs.http.insecureBasic properties described in the table below.JCIFS Properties Meaningful to NTLM HTTP Authentication
All parameters that begin with 'jcifs.' will be set as jCIFS properties which means that any jCIFS properties may be used as init parameters. These properties must be set before jCIFS classes are used. For a complete list of jCIFS properties refer to the overview page of the API documentation. Here is a select subset of jCIFS properties with additional notes in the context of NTLM HTTP Authentication.jcifs.smb.client.domain | The NT domain against which clients should be authenticated. Generally it is necessary to also set the jcifs.netbios.wins parameter or a domain controller may not be found. This parameter will be ignored for NTLM HTTP authentication purposes if a jcifs.http.domainController property is specified (although they can be used together for "preauthenctication" as described in the SMB Signatures and Windows 2003 section below). |
jcifs.http.domainController | The IP address of any SMB server that should be used to authenticate HTTP clients with the NtlmHttpFilter class. If this is not specified the jcifs.smb.client.domain 0x1C NetBIOS group name will be queried. If these queries fail an UnknownHostException will be thrown. It is not necessary for this to specify a real domain controller. The IP address of a workstation will do for simple purposes. |
jcifs.http.basicRelm | The realm for basic authentication. This property defaults to 'jCIFS'. |
jcifs.http.enableBasic | Setting this property to true enables basic authentication over HTTPS only. |
jcifs.http.insecureBasic | Setting this property to true enables basic authentication over plain HTTP. This configuration passes user credentials in plain text over the network. It should not be used in environment where security is required. |
jcifs.http.loadBalance | If a jcifs.smb.client.domain property is specified (and domainController is not specified) the NtlmHttpFilter will query for domain controllers by name. If this property is true the Filter will rotate through the list of domain controllers when authenticating users. The default value is true. The jcifs.netbios.lookupRespLimit property can also be used to limit the number of domain controllers used. |
jcifs.netbios.lookupRespLimit | The 0x1C NetBIOS name query returns a list of domain controllers. It is believed that the servers at the top of this list should be favored. This property limits the range of servers returned by name queries. The default value is 5 meaning the top 5 domain controllers will be used. |
jcifs.netbios.wins | The IP address of the WINS server. This is required when accessing hosts on different subnets (like a domain controller by name) and it is highly recommended if a wins server is available. |
jcifs.smb.client.laddr | The ip address of the local interface the client should bind to if it is different from the default. For example if jCIFS is used to authenticate clients on one interface and the domain controller for those clients is accessible only on another interface of a webserver with two NICs it may be necessary to specify which interface jCIFS should use. |
jcifs.netbios.laddr | The ip address of the local interface the client should bind to for name queries if it is different from the default. Likely set to the same as the above property. |
jcifs.smb.client.attrExpirationPeriod | Attributes of a file are cached for attrExpirationPeriod milliseconds. The default is 5000 but the NetworkExplorer servlet will attempt to set this property to 120000. Otherwise, when listing large directories, the attributes of SmbFiles may expire within the default period resulting in a large number of additional network messages and severe performance degradation. |
jcifs.smb.client.soTimeout | To prevent the client from holding server resources unnecessarily, sockets are closed after this time period if there is no activity. This time is specified in milliseconds. The default is 15000 however when NTLM HTTP Authentication is used, the NtlmHttpFilter will attempt to set this value to 5 minutes so that frequent calls to SmbSession.logon() do not provoke redundant messages being submitted to the domain controller. If it is not desirable to cache password hashes set this value back to 15000. |
jcifs.netbios.cachePolicy | When a NetBIOS name is resolved with the NbtAddress class it is cached to reduce redundant name queries. This property controls how long, in seconds, these names are cached. The default is 30 seconds, 0 is no caching, and -1 is forever. When NTLM HTTP Authentication is used, NtlmHttpFilter will attempt to set this value to 20 minutes so that frequent queries for a domain controller will be cached. |
Must Restart The Container
If you change any jcifs properties or replace an existing jcifs jar file with a different one, the container must be restarted. This is because most jcifs properties are retrieved only once when classes are first loaded.Tomcat
Tomcat requires that all filter directives be adjacent to one another, all filter-mapping directives appear adjacent to one another, all servlet directives ... and so on. This is because Tomcat validates the web.xml against the deployment descriptor DTD.MalformedURLException: unknown protocol: smb
If you get the following exception try upgrading to jcifs-0.7.0b12 or later. Also read the FAQ.Exception MalformedURLException: unknown protocol: smb at java.net.URL.(URL.java:480) at java.net.URL.(URL.java:376) at java.net.URL.(URL.java:330) at jcifs.smb.SmbFile.(SmbFile.java:355) ...
Transparent Authentication and the Network Password Dialog
If the Filter is working properly the Network Password Dialog should never appear. However there are several requirements that must be met for a web browser to transparently negotiate credentials using NTLM HTTP authenication. If any of these requirements are not met, the default behavior is to present the user with the Network Password dialog. The requirements are:- The client must be logged into the Windows NT domain identified by the jcifs.smb.client.domain parameter (or the domain of the host identified by the jcifs.smb.client.domainController parameter if it is used instead). The client may also be logged into a domain that has a trust relationship with the target domain. Indeed it is not uncommon to configure workstations to join a different domain from those of users. Note that Windows 95/98/ME systems cannot really join a domain but can be configured to do so enough to participate in transparent NTLM HTTP authentication.
- Only Internet Explorer will negotiate NTLM HTTP authentication transparently. Mozilla will always prompt the user for credentials (someone please notify us when/if this is not true anymore). At the time this FAQ was written it was not known which other browsers, if any, can negotiate NTLM HTTP authenication transparently.
- Either the target URL must contain a server in the local domain (e.g. ws1.mycompany.com) or the client's security settings must be changed (e.g. Tools > Internet Options > Security > Local Intranet > Sites > Advanced > add your site). If the URL does not contain a URL in the defined IntrAnet zone (e.g. not an IP address), Internet Explorer will assume that the server is in the IntErnet zone and present the user with the Network Password dialog. It would be very bad if a server on the Internet could convince IE to send it your NTLM password hashes. These hashes are easily cracked with brute force dictionary attacks. To prevent this scenario, IE tries to distinguish between Intranet sites and Internet sites. Here are some important notes to consider when deploying a site with NTLM HTTP Authentication regardless of whether or not jCIFS is used to do it.
- Internet Explorer May Prompt You for a Password
http://support.microsoft.com/default.aspx?scid=kb;en-us;Q258063 - How to Use Security Zones in Internet Explorer
http://support.microsoft.com/default.aspx?scid=kb;en-us;Q174360 - An Intranet Site Is Identified as an Internet Site When You Use an FQDN or IP Address
http://support.microsoft.com/default.aspx?scid=kb;en-us;Q303650
- Internet Explorer May Prompt You for a Password
- The user's credentials must be valid. For example if the account has expired, been disabled or is locked out the Network Password dialog will appear. To determine which error was at fault it will be necessary to modify the NtlmHttpFilter to inspect the SmbAuthException in doFilter.
- The jCIFS client must support the lmCompatibility level necessary for communication with the domain controller. If the server does not permit NTLMv1 try to set jcifs.smb.lmCompatibility = 3.
Personal Workstation AD Security Policy
If your Active Directory security policy requires that users only log into the domain from their personal workstations JCIFS will fail to authenticate and the server security log will have entries like "\\JCIFS10_40_4A cannot be authorized". This occurs because the domain controller is failing to resolve the dynamically generated "calling name" submitted by the client during protocol negotiation. To get around this it is necessary to set the jcifs.netbios.hostname property to a valid NetBIOS name that can be resolved by the NetBIOS name service (e.g. WINS) and add that name to the AD security policy as a permitted client. For example, you can set this property using an init-paremeter in the web.xml file for the NTLM HTTP filter as follows:<init-parameter> <parameter-name>jcifs.netbios.hostname</parameter-name> <parameter-value>MYHOSTNAME</parameter-value> </init-parameter>
HTTP POST and Protecting Sub-Content
Once IE has negotiated NTLM HTTP authentication it will proactively renegotiate NTLM for POST requests for all content associated with the server (based on IP?). Therefore when using HTTP POST requests it is not possible to restrict access to some content on the server as IE will attempt and fail to negotiate NTLM (standard IE error page?). This is a protocol limitation and there does not appear to be a way to convince IE to stop proactively negotiating for POST requests once it has been determined that the server is capable of negotiating NTLM authentication.SMB Signatures and Windows 2003
If the domain controller against which you are authenticating clients requires SMB signatures (Windows 2003 does by default), it is recommended that you provide init-parameters for the jcifs.smb.client.{domain,username,password} to perform "preauthentication" for each transport to a domain contoller so that a proper SMB signing key will be generated. In fact, this may be necessary for proper operation; it has been observed that NT 4.0 does not check the signatures of authentication requests but the behavior has not been confirmed in all environments. If the Filter works for the first authentication but fails with a second user shortly thereafter this would suggest that signing was established but subsequent authentications are failing due to the lack of a good signing key. Additionally, without a proper signing key certain requests (SMB_COM_TREE_DISCONNECT and SMB_COM_LOGOFF_ANDX) will cause signature verification failures (although they are harmless to the client). A third solution for signature issues is to change the jcifs.smb.client.ssnLimit to 1. This will require that every authentication uses a separate transport. Because the MAC signing key is only used on SMB communication occuring after the initial authentication, signing will be effectively ignored. However, this solution will significantly reduce scalability as each authentication will open it's own transport. For this reason the second solution of using a "workstation account" to preauthenticate transports is considered the superior method and should be used by default for servers that requires signatures.NTLM HTTP Authentication Protocol Details
The NTLM HTTP Authentication process is described well in these documents:http://davenport.sourceforge.net/ntlm.html
http://www.innovation.ch/java/ntlm.html