From patchwork Mon Aug 1 09:19:42 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Shilovsky X-Patchwork-Id: 1025122 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter2.kernel.org (8.14.4/8.14.4) with ESMTP id p719KIp9031141 for ; Mon, 1 Aug 2011 09:20:33 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752822Ab1HAJUd (ORCPT ); Mon, 1 Aug 2011 05:20:33 -0400 Received: from mail-fx0-f46.google.com ([209.85.161.46]:35513 "EHLO mail-fx0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751589Ab1HAJUc (ORCPT ); Mon, 1 Aug 2011 05:20:32 -0400 Received: by fxh19 with SMTP id 19so4371466fxh.19 for ; Mon, 01 Aug 2011 02:20:31 -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=PiSsxtJdKQhgpNcN/dJC5AIfN+Y3ujTQDK59dR0pNEo=; b=gURzpCGZ6QSLQ+EVhxcNc7i4DIrBMR5FwgZ3V81We5Vg3GlYrp0n0CmFE+EshA4aJk BMKDAEZzYYLlYxz5Qm2Ir8N/ldpq7nHHDHd+PmkziQEpLKpTSgRtIDOCnr6tqeShAjjp 4yGqX+qVbGQ38HTPi1uv1X3fSsisLkwcQbH5E= Received: by 10.204.114.11 with SMTP id c11mr1182430bkq.54.1312190431267; Mon, 01 Aug 2011 02:20:31 -0700 (PDT) Received: from localhost.localdomain ([85.26.232.135]) by mx.google.com with ESMTPS id a22sm1249911bke.53.2011.08.01.02.20.26 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 01 Aug 2011 02:20:30 -0700 (PDT) From: Pavel Shilovsky To: linux-cifs@vger.kernel.org Subject: [v5 PATCH 3/5] CIFS: Move RFC1002 check to a separate function Date: Mon, 1 Aug 2011 13:19:42 +0400 Message-Id: <1312190384-3376-4-git-send-email-piastryyy@gmail.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1312190384-3376-1-git-send-email-piastryyy@gmail.com> References: <1312190384-3376-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 (demeter2.kernel.org [140.211.167.43]); Mon, 01 Aug 2011 09:20:33 +0000 (UTC) Reviewed-and-Tested-by: Jeff Layton 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 a2e9fcf..2a53ade 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(void *p) { @@ -429,7 +486,6 @@ cifs_demultiplex_thread(void *p) 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; @@ -482,59 +538,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) {