⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cifssmb.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	else /* if override flags set only sign/seal OR them with global auth */		secFlags = extended_security | ses->overrideSecFlg;	cFYI(1, ("secFlags 0x%x", secFlags));	pSMB->hdr.Mid = GetNextMid(server);	pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);	if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)		pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;	else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {		cFYI(1, ("Kerberos only mechanism, enable extended security"));		pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;	}	count = 0;	for (i = 0; i < CIFS_NUM_PROT; i++) {		strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);		count += strlen(protocols[i].name) + 1;		/* null at end of source and target buffers anyway */	}	pSMB->hdr.smb_buf_length += count;	pSMB->ByteCount = cpu_to_le16(count);	rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);	if (rc != 0)		goto neg_err_exit;	dialect = le16_to_cpu(pSMBr->DialectIndex);	cFYI(1, ("Dialect: %d", dialect));	/* Check wct = 1 error case */	if ((pSMBr->hdr.WordCount < 13) || (dialect == BAD_PROT)) {		/* core returns wct = 1, but we do not ask for core - otherwise		small wct just comes when dialect index is -1 indicating we		could not negotiate a common dialect */		rc = -EOPNOTSUPP;		goto neg_err_exit;#ifdef CONFIG_CIFS_WEAK_PW_HASH	} else if ((pSMBr->hdr.WordCount == 13)			&& ((dialect == LANMAN_PROT)				|| (dialect == LANMAN2_PROT))) {		__s16 tmp;		struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;		if ((secFlags & CIFSSEC_MAY_LANMAN) ||			(secFlags & CIFSSEC_MAY_PLNTXT))			server->secType = LANMAN;		else {			cERROR(1, ("mount failed weak security disabled"				   " in /proc/fs/cifs/SecurityFlags"));			rc = -EOPNOTSUPP;			goto neg_err_exit;		}		server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);		server->maxReq = le16_to_cpu(rsp->MaxMpxCount);		server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),				(__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);		GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);		/* even though we do not use raw we might as well set this		accurately, in case we ever find a need for it */		if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {			server->maxRw = 0xFF00;			server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;		} else {			server->maxRw = 0;/* we do not need to use raw anyway */			server->capabilities = CAP_MPX_MODE;		}		tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);		if (tmp == -1) {			/* OS/2 often does not set timezone therefore			 * we must use server time to calc time zone.			 * Could deviate slightly from the right zone.			 * Smallest defined timezone difference is 15 minutes			 * (i.e. Nepal).  Rounding up/down is done to match			 * this requirement.			 */			int val, seconds, remain, result;			struct timespec ts, utc;			utc = CURRENT_TIME;			ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date),						le16_to_cpu(rsp->SrvTime.Time));			cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",				(int)ts.tv_sec, (int)utc.tv_sec,				(int)(utc.tv_sec - ts.tv_sec)));			val = (int)(utc.tv_sec - ts.tv_sec);			seconds = abs(val);			result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;			remain = seconds % MIN_TZ_ADJ;			if (remain >= (MIN_TZ_ADJ / 2))				result += MIN_TZ_ADJ;			if (val < 0)				result = - result;			server->timeAdj = result;		} else {			server->timeAdj = (int)tmp;			server->timeAdj *= 60; /* also in seconds */		}		cFYI(1, ("server->timeAdj: %d seconds", server->timeAdj));		/* BB get server time for time conversions and add		code to use it and timezone since this is not UTC */		if (rsp->EncryptionKeyLength ==				cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {			memcpy(server->cryptKey, rsp->EncryptionKey,				CIFS_CRYPTO_KEY_SIZE);		} else if (server->secMode & SECMODE_PW_ENCRYPT) {			rc = -EIO; /* need cryptkey unless plain text */			goto neg_err_exit;		}		cFYI(1, ("LANMAN negotiated"));		/* we will not end up setting signing flags - as no signing		was in LANMAN and server did not return the flags on */		goto signing_check;#else /* weak security disabled */	} else if (pSMBr->hdr.WordCount == 13) {		cERROR(1, ("mount failed, cifs module not built "			  "with CIFS_WEAK_PW_HASH support"));			rc = -EOPNOTSUPP;#endif /* WEAK_PW_HASH */		goto neg_err_exit;	} else if (pSMBr->hdr.WordCount != 17) {		/* unknown wct */		rc = -EOPNOTSUPP;		goto neg_err_exit;	}	/* else wct == 17 NTLM */	server->secMode = pSMBr->SecurityMode;	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)		server->secType = NTLM;	else if (secFlags & CIFSSEC_MAY_NTLMV2)		server->secType = NTLMv2;	else if (secFlags & CIFSSEC_MAY_KRB5)		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"));		goto neg_err_exit;	}	/* else ... any others ...? */	/* one byte, so no need to convert this or EncryptionKeyLen from	   little endian */	server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);	/* probably no need to store and check maxvcs */	server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),			(__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);	server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);	cFYI(0, ("Max buf = %d", ses->server->maxBuf));	GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);	server->capabilities = le32_to_cpu(pSMBr->Capabilities);	server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);	server->timeAdj *= 60;	if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {		memcpy(server->cryptKey, pSMBr->u.EncryptionKey,		       CIFS_CRYPTO_KEY_SIZE);	} else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)			&& (pSMBr->EncryptionKeyLength == 0)) {		/* decode security blob */	} else if (server->secMode & SECMODE_PW_ENCRYPT) {		rc = -EIO; /* no crypt key only if plain text pwd */		goto neg_err_exit;	}	/* BB might be helpful to save off the domain of server here */	if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&		(server->capabilities & CAP_EXTENDED_SECURITY)) {		count = pSMBr->ByteCount;		if (count < 16) {			rc = -EIO;			goto neg_err_exit;		}		if (server->socketUseCount.counter > 1) {			if (memcmp(server->server_GUID,				   pSMBr->u.extended_response.				   GUID, 16) != 0) {				cFYI(1, ("server UID changed"));				memcpy(server->server_GUID,					pSMBr->u.extended_response.GUID,					16);			}		} else			memcpy(server->server_GUID,			       pSMBr->u.extended_response.GUID, 16);		if (count == 16) {			server->secType = RawNTLMSSP;		} else {			rc = decode_negTokenInit(pSMBr->u.extended_response.						 SecurityBlob,						 count - 16,						 &server->secType);			if (rc == 1) {				rc = 0;			} else {				rc = -EINVAL;			}		}	} else		server->capabilities &= ~CAP_EXTENDED_SECURITY;#ifdef CONFIG_CIFS_WEAK_PW_HASHsigning_check:#endif	if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {		/* MUST_SIGN already includes the MAY_SIGN FLAG		   so if this is zero it means that signing is disabled */		cFYI(1, ("Signing disabled"));		if (server->secMode & SECMODE_SIGN_REQUIRED) {			cERROR(1, ("Server requires "				   "packet signing to be enabled in "				   "/proc/fs/cifs/SecurityFlags."));			rc = -EOPNOTSUPP;		}		server->secMode &=			~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);	} else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {		/* signing required */		cFYI(1, ("Must sign - secFlags 0x%x", secFlags));		if ((server->secMode &			(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {			cERROR(1,				("signing required but server lacks support"));			rc = -EOPNOTSUPP;		} else			server->secMode |= SECMODE_SIGN_REQUIRED;	} else {		/* signing optional ie CIFSSEC_MAY_SIGN */		if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)			server->secMode &=				~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);	}neg_err_exit:	cifs_buf_release(pSMB);	cFYI(1, ("negprot rc %d", rc));	return rc;}intCIFSSMBTDis(const int xid, struct cifsTconInfo *tcon){	struct smb_hdr *smb_buffer;	int rc = 0;	cFYI(1, ("In tree disconnect"));	/*	 *  If last user of the connection and	 *  connection alive - disconnect it	 *  If this is the last connection on the server session disconnect it	 *  (and inside session disconnect we should check if tcp socket needs	 *  to be freed and kernel thread woken up).	 */	if (tcon)		down(&tcon->tconSem);	else		return -EIO;	atomic_dec(&tcon->useCount);	if (atomic_read(&tcon->useCount) > 0) {		up(&tcon->tconSem);		return -EBUSY;	}	/* No need to return error on this operation if tid invalidated and	closed on server already e.g. due to tcp session crashing */	if (tcon->tidStatus == CifsNeedReconnect) {		up(&tcon->tconSem);		return 0;	}	if ((tcon->ses == NULL) || (tcon->ses->server == NULL)) {		up(&tcon->tconSem);		return -EIO;	}	rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,			    (void **)&smb_buffer);	if (rc) {		up(&tcon->tconSem);		return rc;	}	rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);	if (rc)		cFYI(1, ("Tree disconnect failed %d", rc));	up(&tcon->tconSem);	/* No need to return error on this operation if tid invalidated and	closed on server already e.g. due to tcp session crashing */	if (rc == -EAGAIN)		rc = 0;	return rc;}intCIFSSMBLogoff(const int xid, struct cifsSesInfo *ses){	LOGOFF_ANDX_REQ *pSMB;	int rc = 0;	cFYI(1, ("In SMBLogoff for session disconnect"));	if (ses)		down(&ses->sesSem);	else		return -EIO;	atomic_dec(&ses->inUse);	if (atomic_read(&ses->inUse) > 0) {		up(&ses->sesSem);		return -EBUSY;	}	rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);	if (rc) {		up(&ses->sesSem);		return rc;	}	if (ses->server) {		pSMB->hdr.Mid = GetNextMid(ses->server);		if (ses->server->secMode &		   (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))			pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;	}	pSMB->hdr.Uid = ses->Suid;	pSMB->AndXCommand = 0xFF;	rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);	if (ses->server) {		atomic_dec(&ses->server->socketUseCount);		if (atomic_read(&ses->server->socketUseCount) == 0) {			spin_lock(&GlobalMid_Lock);			ses->server->tcpStatus = CifsExiting;			spin_unlock(&GlobalMid_Lock);			rc = -ESHUTDOWN;		}	}	up(&ses->sesSem);	/* if session dead then we do not need to do ulogoff,		since server closed smb session, no sense reporting		error */	if (rc == -EAGAIN)		rc = 0;	return rc;}intCIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,		 __u16 type, const struct nls_table *nls_codepage, int remap){	TRANSACTION2_SPI_REQ *pSMB = NULL;	TRANSACTION2_SPI_RSP *pSMBr = NULL;	struct unlink_psx_rq *pRqD;	int name_len;	int rc = 0;	int bytes_returned = 0;	__u16 params, param_offset, offset, byte_count;	cFYI(1, ("In POSIX delete"));PsxDelete:	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,		      (void **) &pSMBr);	if (rc)		return rc;	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {		name_len =		    cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,				     PATH_MAX, nls_codepage, remap);		name_len++;	/* trailing null */		name_len *= 2;	} else { /* BB add path length overrun check */		name_len = strnlen(fileName, PATH_MAX);		name_len++;	/* trailing null */		strncpy(pSMB->FileName, fileName, name_len);	}	params = 6 + name_len;	pSMB->MaxParameterCount = cpu_to_le16(2);	pSMB->MaxDataCount = 0; /* BB double check this with jra */	pSMB->MaxSetupCount = 0;	pSMB->Reserved = 0;	pSMB->Flags = 0;	pSMB->Timeout = 0;	pSMB->Reserved2 = 0;	param_offset = offsetof(struct smb_com_transaction2_spi_req,				InformationLevel) - 4;	offset = param_offset + params;	/* Setup pointer to Request Data (inode type) */	pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);	pRqD->type = cpu_to_le16(type);	pSMB->ParameterOffset = cpu_to_le16(param_offset);	pSMB->DataOffset = cpu_to_le16(offset);	pSMB->SetupCount = 1;	pSMB->Reserved3 = 0;	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);	byte_count = 3 /* pad */  + params + sizeof(struct unlink_psx_rq);	pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));	pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));	pSMB->ParameterCount = cpu_to_le16(params);	pSMB->TotalParameterCount = pSMB->ParameterCount;	pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);	pSMB->Reserved4 = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -