From patchwork Sun Jul 24 14:59:46 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Shilovsky X-Patchwork-Id: 1003042 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.4) with ESMTP id p6OF09EC015623 for ; Sun, 24 Jul 2011 15:00:14 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752784Ab1GXPAO (ORCPT ); Sun, 24 Jul 2011 11:00:14 -0400 Received: from mail-fx0-f52.google.com ([209.85.161.52]:49515 "EHLO mail-fx0-f52.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752838Ab1GXPAN (ORCPT ); Sun, 24 Jul 2011 11:00:13 -0400 Received: by mail-fx0-f52.google.com with SMTP id 18so7679812fxd.11 for ; Sun, 24 Jul 2011 08:00:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=from:to:subject:date:message-id:x-mailer:in-reply-to:references; bh=PnQ/jArpkWShZITfwPFZMCyXWCfFTnTR3XO/k5qQ2Vc=; b=J9VyUsbE5ygSHUFclnPpI0v4ZxUTzFnJIlUnSi0ddmS+iMJZ6z9Nf3F620onA2UMPC akamw++L1mw0rPlZNFhY+Zze1fLbNhitc8atC2BGRBUZz4F5Li4XgjiEiCveDRCI4I7w guMSfy44IIyib8MrilMGdVi59lL/5PmtkFFmI= Received: by 10.204.148.90 with SMTP id o26mr998653bkv.263.1311519612754; Sun, 24 Jul 2011 08:00:12 -0700 (PDT) Received: from localhost.localdomain ([85.26.232.196]) by mx.google.com with ESMTPS id p24sm299970bkw.41.2011.07.24.08.00.10 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 24 Jul 2011 08:00:12 -0700 (PDT) From: Pavel Shilovsky To: linux-cifs@vger.kernel.org Subject: [v4 PATCH 3/5] CIFS: Move RFC1002 check to a separate function Date: Sun, 24 Jul 2011 18:59:46 +0400 Message-Id: <1311519588-2457-3-git-send-email-piastryyy@gmail.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1311519588-2457-1-git-send-email-piastryyy@gmail.com> References: <1311519588-2457-1-git-send-email-piastryyy@gmail.com> Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Sun, 24 Jul 2011 15:00:14 +0000 (UTC) Signed-off-by: Pavel Shilovsky --- fs/cifs/connect.c | 116 ++++++++++++++++++++++++++++++---------------------- 1 files changed, 67 insertions(+), 49 deletions(-) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index e8a1d64..92260b0 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -416,6 +416,63 @@ read_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg, return rc; } +static bool +check_rfc1002_header(struct TCP_Server_Info *server, char *buf) +{ + char temp = *buf; + unsigned int pdu_length = be32_to_cpu( + ((struct smb_hdr *)buf)->smb_buf_length); + + /* + * The first byte big endian of the length field, + * is actually not part of the length but the type + * with the most common, zero, as regular data. + */ + if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) { + return false; + } else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) { + cFYI(1, "Good RFC 1002 session rsp"); + return false; + } else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) { + /* + * We get this from Windows 98 instead of an error on + * SMB negprot response. + */ + cFYI(1, "Negative RFC1002 Session Response Error 0x%x)", + pdu_length); + /* give server a second to clean up */ + msleep(1000); + /* + * Always try 445 first on reconnect since we get NACK + * on some if we ever connected to port 139 (the NACK + * is since we do not begin with RFC1001 session + * initialize frame). + */ + cifs_set_port((struct sockaddr *) + &server->dstaddr, CIFS_PORT); + cifs_reconnect(server); + wake_up(&server->response_q); + return false; + } else if (temp != (char) 0) { + cERROR(1, "Unknown RFC 1002 frame"); + cifs_dump_mem(" Received Data: ", buf, 4); + cifs_reconnect(server); + return false; + } + + /* else we have an SMB response */ + if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) || + (pdu_length < sizeof(struct smb_hdr) - 1 - 4)) { + cERROR(1, "Invalid size SMB length %d pdu_length %d", + 4, pdu_length+4); + cifs_reconnect(server); + wake_up(&server->response_q); + return false; + } + + return true; +} + static int cifs_demultiplex_thread(struct TCP_Server_Info *server) { @@ -428,7 +485,6 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) struct list_head *tmp, *tmp2; struct task_struct *task_to_wake = NULL; struct mid_q_entry *mid_entry; - char temp; bool isLargeBuf = false; bool isMultiRsp; int rc; @@ -481,59 +537,21 @@ incomplete_rcv: else if (rc == 1) continue; - /* The right amount was read from socket - 4 bytes */ - /* so we can now interpret the length field */ - - /* the first byte big endian of the length field, - is actually not part of the length but the type - with the most common, zero, as regular data */ - temp = *buf; + /* + * The right amount was read from socket - 4 bytes, + * so we can now interpret the length field. + */ - /* Note that FC 1001 length is big endian on the wire, - but we convert it here so it is always manipulated - as host byte order */ + /* + * Note that RFC 1001 length is big endian on the wire, + * but we convert it here so it is always manipulated + * as host byte order. + */ pdu_length = be32_to_cpu(smb_buffer->smb_buf_length); cFYI(1, "rfc1002 length 0x%x", pdu_length+4); - - if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) { - continue; - } else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) { - cFYI(1, "Good RFC 1002 session rsp"); - continue; - } else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) { - /* we get this from Windows 98 instead of - an error on SMB negprot response */ - cFYI(1, "Negative RFC1002 Session Response Error 0x%x)", - pdu_length); - /* give server a second to clean up */ - msleep(1000); - /* always try 445 first on reconnect since we get NACK - * on some if we ever connected to port 139 (the NACK - * is since we do not begin with RFC1001 session - * initialize frame) - */ - cifs_set_port((struct sockaddr *) - &server->dstaddr, CIFS_PORT); - cifs_reconnect(server); - wake_up(&server->response_q); - continue; - } else if (temp != (char) 0) { - cERROR(1, "Unknown RFC 1002 frame"); - cifs_dump_mem(" Received Data: ", buf, length); - cifs_reconnect(server); - continue; - } - - /* else we have an SMB response */ - if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) || - (pdu_length < sizeof(struct smb_hdr) - 1 - 4)) { - cERROR(1, "Invalid size SMB length %d pdu_length %d", - length, pdu_length+4); - cifs_reconnect(server); - wake_up(&server->response_q); + if (!check_rfc1002_header(server, buf)) continue; - } /* else length ok */ if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {