[linux-cifs-client] [PATCH] allow NTLM plaintext password authentication.

Bart Oldeman bartoldeman at users.sourceforge.net
Sun Mar 30 19:27:13 GMT 2008


Hi,

the following patch allows plaintext password authentication with NTLM, as 
implemented by some servers (see also
http://lists.samba.org/archive/linux-cifs-client/2007-November/002373.html
)

/proc/fs/cifs/SecurityFlags needs to be or'ed with 0x20, or else plain 
text passwords are rejected.

Referenced: cli_session_setup_plaintext() in Samba's source/libsmb/cliconnect.c

On a related note: in sess.c for NTMLv2 there is the following code:
====
 		if (first_time) /* should this be moved into common code
 				   with similar ntlmv2 path? */
 		/* 
cifs_calculate_ntlmv2_mac_key(ses->server->mac_signing_key,
 				response BB FIXME, v2_sess_key); */

 		/* copy session key */

 	/*	memcpy(bcc_ptr, (char *)ntlm_session_key,LM2_SESS_KEY_SIZE);
 		bcc_ptr += LM2_SESS_KEY_SIZE; */
 		memcpy(bcc_ptr, (char *)v2_sess_key,
 		       sizeof(struct ntlmv2_resp));
 		bcc_ptr += sizeof(struct ntlmv2_resp);
====
which looks suspect to me since "if (first_time)" applies to 
the unindented memcpy(bcc_ptr,...) and bcc_ptr is updated unconditionally.

Bart

Signed-off-by: Bart Oldeman <bartoldeman at users.sourceforge.net>

diff -urp -X linux-2.6/Documentation/dontdiff linux-2.6/fs/cifs.orig/cifssmb.c linux-2.6/fs/cifs/cifssmb.c
--- linux-2.6/fs/cifs.orig/cifssmb.c	2008-03-30 14:35:58.000000000 -0400
+++ linux-2.6/fs/cifs/cifssmb.c	2008-03-30 15:15:15.000000000 -0400
@@ -565,13 +565,6 @@ CIFSSMBNegotiate(unsigned int xid, struc
  	if ((server->secMode & SECMODE_USER) == 0)
  		cFYI(1, ("share mode security"));

-	if ((server->secMode & SECMODE_PW_ENCRYPT) == 0)
-#ifdef CONFIG_CIFS_WEAK_PW_HASH
-		if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
-#endif /* CIFS_WEAK_PW_HASH */
-			cERROR(1, ("Server requests plain text password"
-				  " but client support disabled"));
-
  	if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
  		server->secType = NTLMv2;
  	else if (secFlags & CIFSSEC_MAY_NTLM)
@@ -582,10 +575,6 @@ CIFSSMBNegotiate(unsigned int xid, struc
  		server->secType = Kerberos;
  	else if (secFlags & CIFSSEC_MAY_LANMAN)
  		server->secType = LANMAN;
-/* #ifdef CONFIG_CIFS_EXPERIMENTAL
-	else if (secFlags & CIFSSEC_MAY_PLNTXT)
-		server->secType = ??
-#endif */
  	else {
  		rc = -EOPNOTSUPP;
  		cERROR(1, ("Invalid security type"));
@@ -593,6 +582,17 @@ CIFSSMBNegotiate(unsigned int xid, struc
  	}
  	/* else ... any others ...? */

+	if ((server->secMode & SECMODE_PW_ENCRYPT) == 0) {
+#ifdef CONFIG_CIFS_WEAK_PW_HASH
+		if ((secFlags & CIFSSEC_MAY_PLNTXT)) {
+			if (server->secType == NTLM)
+				server->secType = PLAINTXT;
+		} else
+#endif /* CIFS_WEAK_PW_HASH */
+			cERROR(1, ("Server requests plain text password"
+				  " but client support disabled"));
+	}
+
  	/* one byte, so no need to convert this or EncryptionKeyLen from
  	   little endian */
  	server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
diff -urp -X linux-2.6/Documentation/dontdiff linux-2.6/fs/cifs.orig/sess.c linux-2.6/fs/cifs/sess.c
--- linux-2.6/fs/cifs.orig/sess.c	2008-02-01 16:25:43.000000000 -0500
+++ linux-2.6/fs/cifs/sess.c	2008-03-30 15:08:55.000000000 -0400
@@ -364,7 +364,7 @@ CIFS_SessSetup(unsigned int xid, struct
  		return -EOPNOTSUPP;
  #endif
  		wct = 10; /* lanman 2 style sessionsetup */
-	} else if ((type == NTLM) || (type == NTLMv2)) {
+	} else if ((type == NTLM) || (type == NTLMv2) || (type == PLAINTXT)) {
  		/* For NTLMv2 failures eventually may need to retry NTLM */
  		wct = 13; /* old style NTLM sessionsetup */
  	} else /* same size: negotiate or auth, NTLMSSP or extended security */
@@ -432,6 +432,36 @@ CIFS_SessSetup(unsigned int xid, struct
  		cFYI(1, ("Negotiating LANMAN setting up strings"));
  		/* Unicode not allowed for LANMAN dialects */
  		ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
+	} else if (type == PLAINTXT) {
+		int bytes_ret;
+
+		pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
+		if (ses->capabilities & CAP_UNICODE) {
+			/* unicode strings must be word aligned */
+			if (iov[0].iov_len % 2) {
+				*bcc_ptr = 0;
+				bcc_ptr++;
+			}
+			bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr,
+				ses->password, 128, nls_cp);
+			bytes_ret = 2 * (bytes_ret + 1);
+			bcc_ptr += bytes_ret;
+			pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
+			pSMB->req_no_secext.CaseSensitivePasswordLength =
+				cpu_to_le16(bytes_ret);
+			unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
+		} else {
+			/* Password cannot be longer than 128 characters */
+			bytes_ret = strnlen(ses->password, 128);
+			memcpy(bcc_ptr, ses->password, bytes_ret);
+			/* account for null termination */
+			bcc_ptr[bytes_ret++] = 0;
+			bcc_ptr += bytes_ret;
+			pSMB->req_no_secext.CaseInsensitivePasswordLength =
+				cpu_to_le16(bytes_ret);
+			pSMB->req_no_secext.CaseSensitivePasswordLength = 0;
+			ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
+		}
  #endif
  	} else if (type == NTLM) {
  		char ntlm_session_key[CIFS_SESS_KEY_SIZE];


More information about the linux-cifs-client mailing list