📄 sess.c
字号:
/* * fs/cifs/sess.c * * SMB/CIFS session setup handling routines * * Copyright (c) International Business Machines Corp., 2006, 2007 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include <linux/fs.h>#include "cifspdu.h"#include "cifsglob.h"#include "cifsproto.h"#include "cifs_unicode.h"#include "cifs_debug.h"#include "ntlmssp.h"#include "nterr.h"#include <linux/utsname.h>extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24);static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB){ __u32 capabilities = 0; /* init fields common to all four types of SessSetup */ /* note that header is initialized to zero in header_assemble */ pSMB->req.AndXCommand = 0xFF; pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */ /* BB verify whether signing required on neg or just on auth frame (and NTLM case) */ capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | CAP_LARGE_WRITE_X | CAP_LARGE_READ_X; if (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; if (ses->capabilities & CAP_UNICODE) { pSMB->req.hdr.Flags2 |= SMBFLG2_UNICODE; capabilities |= CAP_UNICODE; } if (ses->capabilities & CAP_STATUS32) { pSMB->req.hdr.Flags2 |= SMBFLG2_ERR_STATUS; capabilities |= CAP_STATUS32; } if (ses->capabilities & CAP_DFS) { pSMB->req.hdr.Flags2 |= SMBFLG2_DFS; capabilities |= CAP_DFS; } if (ses->capabilities & CAP_UNIX) capabilities |= CAP_UNIX; /* BB check whether to init vcnum BB */ return capabilities;}static void unicode_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses, const struct nls_table *nls_cp){ char *bcc_ptr = *pbcc_area; int bytes_ret = 0; /* BB FIXME add check that strings total less than 335 or will need to send them as arrays */ /* unicode strings, must be word aligned before the call *//* if ((long) bcc_ptr % 2) { *bcc_ptr = 0; bcc_ptr++; } */ /* copy user */ if (ses->userName == NULL) { /* null user mount */ *bcc_ptr = 0; *(bcc_ptr+1) = 0; } else { /* 300 should be long enough for any conceivable user name */ bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->userName, 300, nls_cp); } bcc_ptr += 2 * bytes_ret; bcc_ptr += 2; /* account for null termination */ /* copy domain */ if (ses->domainName == NULL) { /* Sending null domain better than using a bogus domain name (as we did briefly in 2.6.18) since server will use its default */ *bcc_ptr = 0; *(bcc_ptr+1) = 0; bytes_ret = 0; } else bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName, 256, nls_cp); bcc_ptr += 2 * bytes_ret; bcc_ptr += 2; /* account for null terminator */ /* Copy OS version */ bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32, nls_cp); bcc_ptr += 2 * bytes_ret;#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18) bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, init_utsname()->release, 32, nls_cp);#else bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32, nls_cp);#endif bcc_ptr += 2 * bytes_ret; bcc_ptr += 2; /* trailing null */ bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS, 32, nls_cp); bcc_ptr += 2 * bytes_ret; bcc_ptr += 2; /* trailing null */ *pbcc_area = bcc_ptr;}static void ascii_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses, const struct nls_table *nls_cp){ char *bcc_ptr = *pbcc_area; /* copy user */ /* BB what about null user mounts - check that we do this BB */ /* copy user */ if (ses->userName == NULL) { /* BB what about null user mounts - check that we do this BB */ } else { /* 300 should be long enough for any conceivable user name */ strncpy(bcc_ptr, ses->userName, 300); } /* BB improve check for overflow */ bcc_ptr += strnlen(ses->userName, 300); *bcc_ptr = 0; bcc_ptr++; /* account for null termination */ /* copy domain */ if (ses->domainName != NULL) { strncpy(bcc_ptr, ses->domainName, 256); bcc_ptr += strnlen(ses->domainName, 256); } /* else we will send a null domain name so the server will default to its own domain */ *bcc_ptr = 0; bcc_ptr++; /* BB check for overflow here */ strcpy(bcc_ptr, "Linux version "); bcc_ptr += strlen("Linux version ");#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18) strcpy(bcc_ptr, init_utsname()->release); bcc_ptr += strlen(init_utsname()->release) + 1;#else strcpy(bcc_ptr, system_utsname.release); bcc_ptr += strlen(system_utsname.release) + 1;#endif strcpy(bcc_ptr, CIFS_NETWORK_OPSYS); bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1; *pbcc_area = bcc_ptr;}static int decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifsSesInfo *ses, const struct nls_table *nls_cp){ int rc = 0; int words_left, len; char *data = *pbcc_area; cFYI(1, ("bleft %d", bleft)); /* SMB header is unaligned, so cifs servers word align start of Unicode strings */ data++; bleft--; /* Windows servers do not always double null terminate their final Unicode string - in which case we now will not attempt to decode the byte of junk which follows it */ words_left = bleft / 2; /* save off server operating system */ len = UniStrnlen((wchar_t *) data, words_left);/* We look for obvious messed up bcc or strings in response so we do not go off the end since (at least) WIN2K and Windows XP have a major bug in not null terminating last Unicode string in response */ if (len >= words_left) return rc; kfree(ses->serverOS); /* UTF-8 string will not grow more than four times as big as UCS-16 */ ses->serverOS = kzalloc(4 * len, GFP_KERNEL); if (ses->serverOS != NULL) cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, nls_cp); data += 2 * (len + 1); words_left -= len + 1; /* save off server network operating system */ len = UniStrnlen((wchar_t *) data, words_left); if (len >= words_left) return rc; kfree(ses->serverNOS); ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */ if (ses->serverNOS != NULL) { cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len, nls_cp); if (strncmp(ses->serverNOS, "NT LAN Manager 4", 16) == 0) { cFYI(1, ("NT4 server")); ses->flags |= CIFS_SES_NT4; } } data += 2 * (len + 1); words_left -= len + 1; /* save off server domain */ len = UniStrnlen((wchar_t *) data, words_left); if (len > words_left) return rc; kfree(ses->serverDomain); ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */ if (ses->serverDomain != NULL) { cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len, nls_cp); ses->serverDomain[2*len] = 0; ses->serverDomain[(2*len) + 1] = 0; } data += 2 * (len + 1); words_left -= len + 1; cFYI(1, ("words left: %d", words_left)); return rc;}static int decode_ascii_ssetup(char **pbcc_area, int bleft, struct cifsSesInfo *ses, const struct nls_table *nls_cp){ int rc = 0; int len; char *bcc_ptr = *pbcc_area; cFYI(1, ("decode sessetup ascii. bleft %d", bleft)); len = strnlen(bcc_ptr, bleft); if (len >= bleft) return rc; kfree(ses->serverOS);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -