xref: /onnv-gate/usr/src/uts/common/fs/smbsrv/smb_signing.c (revision 10966:37e5dcdf36d3)
15331Samw /*
25331Samw  * CDDL HEADER START
35331Samw  *
45331Samw  * The contents of this file are subject to the terms of the
55331Samw  * Common Development and Distribution License (the "License").
65331Samw  * You may not use this file except in compliance with the License.
75331Samw  *
85331Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw  * or http://www.opensolaris.org/os/licensing.
105331Samw  * See the License for the specific language governing permissions
115331Samw  * and limitations under the License.
125331Samw  *
135331Samw  * When distributing Covered Code, include this CDDL HEADER in each
145331Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw  * If applicable, add the following below this CDDL HEADER, with the
165331Samw  * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw  *
195331Samw  * CDDL HEADER END
205331Samw  */
215331Samw /*
22*10966SJordan.Brown@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
235331Samw  * Use is subject to license terms.
245331Samw  */
255331Samw 
265331Samw /*
275331Samw  * These routines provide the SMB MAC signing for the SMB server.
285331Samw  * The routines calculate the signature of a SMB message in an mbuf chain.
295331Samw  *
307348SJose.Borrego@Sun.COM  * The following table describes the client server
317348SJose.Borrego@Sun.COM  * signing registry relationship
327348SJose.Borrego@Sun.COM  *
337348SJose.Borrego@Sun.COM  *		| Required	| Enabled     | Disabled
347348SJose.Borrego@Sun.COM  * -------------+---------------+------------ +--------------
357348SJose.Borrego@Sun.COM  * Required	| Signed	| Signed      | Fail
367348SJose.Borrego@Sun.COM  * -------------+---------------+-------------+-----------------
377348SJose.Borrego@Sun.COM  * Enabled	| Signed	| Signed      | Not Signed
387348SJose.Borrego@Sun.COM  * -------------+---------------+-------------+----------------
397348SJose.Borrego@Sun.COM  * Disabled	| Fail		| Not Signed  | Not Signed
405331Samw  */
415331Samw 
425331Samw #include <sys/uio.h>
43*10966SJordan.Brown@Sun.COM #include <smbsrv/smb_kproto.h>
445331Samw #include <smbsrv/msgbuf.h>
455331Samw #include <sys/crypto/api.h>
465331Samw 
476600Sas200622 #define	SMBAUTH_SESSION_KEY_SZ 16
485331Samw #define	SMB_SIG_SIZE	8
495331Samw #define	SMB_SIG_OFFS	14
505331Samw 
517348SJose.Borrego@Sun.COM int
527348SJose.Borrego@Sun.COM smb_sign_calc(struct mbuf_chain *mbc,
537348SJose.Borrego@Sun.COM     struct smb_sign *sign,
547348SJose.Borrego@Sun.COM     uint32_t seqnum,
557348SJose.Borrego@Sun.COM     unsigned char *mac_sign);
567348SJose.Borrego@Sun.COM 
577348SJose.Borrego@Sun.COM #ifdef DEBUG
587348SJose.Borrego@Sun.COM void smb_sign_find_seqnum(
597348SJose.Borrego@Sun.COM     struct smb_sign *sign,
607348SJose.Borrego@Sun.COM     struct mbuf_chain *command,
617348SJose.Borrego@Sun.COM     unsigned char *mac_sig,
627348SJose.Borrego@Sun.COM     unsigned char *sr_sig,
637348SJose.Borrego@Sun.COM     boolean_t *found);
647348SJose.Borrego@Sun.COM 
657348SJose.Borrego@Sun.COM #define	SMB_CHECK_SEQNUM(sign, command, mac_sig, sr_sig, found) \
667348SJose.Borrego@Sun.COM { \
677348SJose.Borrego@Sun.COM 	if (smb_sign_debug) \
687348SJose.Borrego@Sun.COM 		smb_sign_find_seqnum(sign, command, mac_sig, sr_sig, found); \
697348SJose.Borrego@Sun.COM }
707348SJose.Borrego@Sun.COM #else
717348SJose.Borrego@Sun.COM #define	SMB_CHECK_SEQNUM(sign, command, mac_sig, sr_sig, found) \
727348SJose.Borrego@Sun.COM 	{  }
737348SJose.Borrego@Sun.COM #endif
747348SJose.Borrego@Sun.COM 
757348SJose.Borrego@Sun.COM #ifdef DEBUG
767348SJose.Borrego@Sun.COM void
777348SJose.Borrego@Sun.COM smb_sign_find_seqnum(
787348SJose.Borrego@Sun.COM     struct smb_sign *sign,
797348SJose.Borrego@Sun.COM     struct mbuf_chain *command,
807348SJose.Borrego@Sun.COM     unsigned char *mac_sig,
817348SJose.Borrego@Sun.COM     unsigned char *sr_sig,
827348SJose.Borrego@Sun.COM     boolean_t *found)
837348SJose.Borrego@Sun.COM {
847348SJose.Borrego@Sun.COM int start_seqnum;
857348SJose.Borrego@Sun.COM int i;
867348SJose.Borrego@Sun.COM 
877348SJose.Borrego@Sun.COM 	/* Debug code to hunt for the sequence number */
887348SJose.Borrego@Sun.COM 	*found = B_FALSE;
897348SJose.Borrego@Sun.COM 	start_seqnum = (int)sign->seqnum - 6;
907348SJose.Borrego@Sun.COM 	if (start_seqnum < 0)
917348SJose.Borrego@Sun.COM 		start_seqnum = 0;
927348SJose.Borrego@Sun.COM 	for (i = start_seqnum; i <= start_seqnum + 6; i++) {
937639SNick.Todd@Sun.COM 		(void) smb_sign_calc(command, sign, i, mac_sig);
947348SJose.Borrego@Sun.COM 		if (memcmp(mac_sig, sr_sig, SMB_SIG_SIZE) == 0) {
957348SJose.Borrego@Sun.COM 			sign->seqnum = i;
967348SJose.Borrego@Sun.COM 			*found = B_TRUE;
977348SJose.Borrego@Sun.COM 			break;
987348SJose.Borrego@Sun.COM 		}
997348SJose.Borrego@Sun.COM 		cmn_err(CE_WARN, "smb_sign_find_seqnum: seqnum%d mismatch", i);
1007348SJose.Borrego@Sun.COM 	}
1017348SJose.Borrego@Sun.COM 	cmn_err(CE_WARN, "smb_sign_find_seqnum: found=%d", *found);
1027348SJose.Borrego@Sun.COM }
1037348SJose.Borrego@Sun.COM #endif
1045331Samw /* This holds the MD5 mechanism */
1055331Samw static	crypto_mechanism_t crypto_mech = {CRYPTO_MECHANISM_INVALID, 0, 0};
1065331Samw 
1075331Samw /*
1085331Samw  * smb_sign_init
1095331Samw  *
1105331Samw  * Intializes MAC key based on the user session key and
1115331Samw  * NTLM response and store it in the signing structure.
1125331Samw  */
1135331Samw void
1146139Sjb150015 smb_sign_init(smb_request_t *sr, smb_session_key_t *session_key,
1155331Samw 	char *resp, int resp_len)
1165331Samw {
1176139Sjb150015 	struct smb_sign *sign = &sr->session->signing;
1185331Samw 
1195331Samw 	/*
1205331Samw 	 * Initialise the crypto mechanism to MD5 if it not
1215331Samw 	 * already initialised.
1225331Samw 	 */
1235331Samw 	if (crypto_mech.cm_type ==  CRYPTO_MECHANISM_INVALID) {
1245331Samw 		crypto_mech.cm_type = crypto_mech2id(SUN_CKM_MD5);
1255331Samw 		if (crypto_mech.cm_type == CRYPTO_MECHANISM_INVALID) {
1265331Samw 			/*
1275331Samw 			 * There is no MD5 crypto mechanism
1285331Samw 			 * so turn off signing
1295331Samw 			 */
1306139Sjb150015 			sr->sr_cfg->skc_signing_enable = 0;
1316139Sjb150015 			sr->session->secmode &=
1325331Samw 			    (~NEGOTIATE_SECURITY_SIGNATURES_ENABLED);
1335331Samw 			cmn_err(CE_WARN,
1345331Samw 			    "SmbSignInit: signing disabled (no MD5)");
1355331Samw 			return;
1365331Samw 		}
1375331Samw 	}
1385331Samw 
1395331Samw 	/* MAC key = concat (SessKey, NTLMResponse) */
1405331Samw 
1415331Samw 	bcopy(session_key, sign->mackey, sizeof (smb_session_key_t));
1425331Samw 	bcopy(resp, &(sign->mackey[sizeof (smb_session_key_t)]),
1435331Samw 	    resp_len);
1445331Samw 	sign->mackey_len = sizeof (smb_session_key_t) + resp_len;
1455331Samw 
1466139Sjb150015 	sr->reply_seqnum = 1;
1475331Samw 	sign->seqnum = 2;
1485331Samw 	sign->flags = SMB_SIGNING_ENABLED;
1495331Samw 
1505331Samw }
1515331Samw 
1525331Samw /*
1535331Samw  * smb_sign_calc
1545331Samw  *
1555331Samw  * Calculates MAC signature for the given buffer and returns
1565331Samw  * it in the mac_sign parameter.
1575331Samw  *
1585331Samw  * The sequence number is placed in the first four bytes of the signature
1595331Samw  * field of the signature and the other 4 bytes are zeroed.
1605331Samw  * The signature is the first 8 bytes of the MD5 result of the
1615331Samw  * concatenated MAC key and the SMB message.
1625331Samw  *
1635331Samw  * MACsig = head(MD5(concat(MACKey, SMBMsg)), 8)
1645331Samw  *
1655331Samw  * where
1665331Samw  *
1675331Samw  *	MACKey = concat( UserSessionKey, NTLMResp )
1685331Samw  *
1695331Samw  * and
1705331Samw  *
1715331Samw  *	SMBMsg is the SMB message containing the sequence number.
1725331Samw  *
1735331Samw  * Return 0 if  success else -1
1745331Samw  *
1755331Samw  */
1767348SJose.Borrego@Sun.COM int
1775331Samw smb_sign_calc(struct mbuf_chain *mbc,
1785331Samw     struct smb_sign *sign,
1795331Samw     uint32_t seqnum,
1805331Samw     unsigned char *mac_sign)
1815331Samw {
1825331Samw 	uint32_t seq_buf[2] = {0, 0};
1835331Samw 	unsigned char mac[16];
1845331Samw 	struct mbuf *mbuf = mbc->chain;
1855331Samw 	int offset = mbc->chain_offset;
1865331Samw 	int size;
1875331Samw 	int status;
1885331Samw 
1895331Samw 	crypto_data_t data;
1905331Samw 	crypto_data_t digest;
1915331Samw 	crypto_context_t crypto_ctx;
1925331Samw 
1935331Samw 	data.cd_format = CRYPTO_DATA_RAW;
1945331Samw 	data.cd_offset = 0;
1955331Samw 	data.cd_length = (size_t)-1;
1965331Samw 	data.cd_miscdata = 0;
1975331Samw 
1985331Samw 	digest.cd_format = CRYPTO_DATA_RAW;
1995331Samw 	digest.cd_offset = 0;
2005331Samw 	digest.cd_length = (size_t)-1;
2015331Samw 	digest.cd_miscdata = 0;
2025331Samw 	digest.cd_raw.iov_base = (char *)mac;
2035331Samw 	digest.cd_raw.iov_len = sizeof (mac);
2045331Samw 
2055331Samw 	status = crypto_digest_init(&crypto_mech, &crypto_ctx, 0);
2066600Sas200622 	if (status != CRYPTO_SUCCESS)
2076600Sas200622 		goto error;
2085331Samw 
2095331Samw 	/*
2105331Samw 	 * Put the sequence number into the first 4 bytes
2115331Samw 	 * of the signature field in little endian format.
2125331Samw 	 * We are using a buffer to represent the signature
2135331Samw 	 * rather than modifying the SMB message.
2145331Samw 	 */
2155331Samw #ifdef __sparc
2165331Samw 	{
2175331Samw 		uint32_t temp;
2185331Samw 		((uint8_t *)&temp)[0] = ((uint8_t *)&seqnum)[3];
2195331Samw 		((uint8_t *)&temp)[1] = ((uint8_t *)&seqnum)[2];
2205331Samw 		((uint8_t *)&temp)[2] = ((uint8_t *)&seqnum)[1];
2215331Samw 		((uint8_t *)&temp)[3] = ((uint8_t *)&seqnum)[0];
2225331Samw 
2235331Samw 		seq_buf[0] = temp;
2245331Samw 	}
2255331Samw #else
2265331Samw 	seq_buf[0] = seqnum;
2275331Samw #endif
2285331Samw 
2295331Samw 	/* Digest the MACKey */
2305331Samw 	data.cd_raw.iov_base = (char *)sign->mackey;
2315331Samw 	data.cd_raw.iov_len = sign->mackey_len;
2326600Sas200622 	data.cd_length = sign->mackey_len;
2336600Sas200622 	status = crypto_digest_update(crypto_ctx, &data, 0);
2346600Sas200622 	if (status != CRYPTO_SUCCESS)
2356600Sas200622 		goto error;
2365331Samw 
2375331Samw 	/* Find start of data in chain */
2385331Samw 	while (offset >= mbuf->m_len) {
2395331Samw 		offset -= mbuf->m_len;
2405331Samw 		mbuf = mbuf->m_next;
2415331Samw 	}
2425331Samw 
2435331Samw 	/* Digest the SMB packet up to the signature field */
2445331Samw 	size = SMB_SIG_OFFS;
2455331Samw 	while (size >= mbuf->m_len - offset) {
2465331Samw 		data.cd_raw.iov_base = &mbuf->m_data[offset];
2475331Samw 		data.cd_raw.iov_len = mbuf->m_len - offset;
2486600Sas200622 		data.cd_length = mbuf->m_len - offset;
2496600Sas200622 		status = crypto_digest_update(crypto_ctx, &data, 0);
2506600Sas200622 		if (status != CRYPTO_SUCCESS)
2516600Sas200622 			goto error;
2525331Samw 
2535331Samw 		size -= mbuf->m_len - offset;
2545331Samw 		mbuf = mbuf->m_next;
2555331Samw 		offset = 0;
2565331Samw 	}
2575331Samw 	if (size > 0) {
2585331Samw 		data.cd_raw.iov_base = &mbuf->m_data[offset];
2595331Samw 		data.cd_raw.iov_len = size;
2606600Sas200622 		data.cd_length = size;
2616600Sas200622 		status = crypto_digest_update(crypto_ctx, &data, 0);
2626600Sas200622 		if (status != CRYPTO_SUCCESS)
2636600Sas200622 			goto error;
2645331Samw 		offset += size;
2655331Samw 	}
2665331Samw 
2675331Samw 	/*
2685331Samw 	 * Digest in the seq_buf instead of the signature
2695331Samw 	 * which has the sequence number
2705331Samw 	 */
2715331Samw 
2725331Samw 	data.cd_raw.iov_base = (char *)seq_buf;
2735331Samw 	data.cd_raw.iov_len = SMB_SIG_SIZE;
2746600Sas200622 	data.cd_length = SMB_SIG_SIZE;
2756600Sas200622 	status = crypto_digest_update(crypto_ctx, &data, 0);
2766600Sas200622 	if (status != CRYPTO_SUCCESS)
2776600Sas200622 		goto error;
2785331Samw 
2795331Samw 	/* Find the end of the signature field  */
2805331Samw 	offset += SMB_SIG_SIZE;
2815331Samw 	while (offset >= mbuf->m_len) {
2825331Samw 		offset -= mbuf->m_len;
2835331Samw 		mbuf = mbuf->m_next;
2845331Samw 	}
2855331Samw 	/* Digest the rest of the SMB packet */
2865331Samw 	while (mbuf) {
2875331Samw 		data.cd_raw.iov_base = &mbuf->m_data[offset];
2885331Samw 		data.cd_raw.iov_len = mbuf->m_len - offset;
2896600Sas200622 		data.cd_length = mbuf->m_len - offset;
2906600Sas200622 		status = crypto_digest_update(crypto_ctx, &data, 0);
2916600Sas200622 		if (status != CRYPTO_SUCCESS)
2926600Sas200622 			goto error;
2935331Samw 		mbuf = mbuf->m_next;
2945331Samw 		offset = 0;
2955331Samw 	}
2966600Sas200622 	digest.cd_length = SMBAUTH_SESSION_KEY_SZ;
2976600Sas200622 	status = crypto_digest_final(crypto_ctx, &digest, 0);
2986600Sas200622 	if (status != CRYPTO_SUCCESS)
2996600Sas200622 		goto error;
3005331Samw 	bcopy(mac, mac_sign, SMB_SIG_SIZE);
3015331Samw 	return (0);
3025331Samw error:
3035331Samw 	cmn_err(CE_WARN, "SmbSignCalc: crypto error %d", status);
3045331Samw 	return (-1);
3055331Samw 
3065331Samw }
3075331Samw 
3085331Samw 
3095331Samw /*
3105331Samw  * smb_sign_check_request
3115331Samw  *
3125331Samw  * Calculates MAC signature for the request mbuf chain
3135331Samw  * using the next expected sequence number and compares
3145331Samw  * it to the given signature.
3155331Samw  *
3165331Samw  * Note it does not check the signature for secondary transactions
3175331Samw  * as their sequence number is the same as the original request.
3185331Samw  *
3195331Samw  * Return 0 if the signature verifies, otherwise, returns -1;
3205331Samw  *
3215331Samw  */
3225331Samw int
3236139Sjb150015 smb_sign_check_request(smb_request_t *sr)
3245331Samw {
3256139Sjb150015 	struct mbuf_chain command = sr->command;
3265331Samw 	unsigned char mac_sig[SMB_SIG_SIZE];
3276139Sjb150015 	struct smb_sign *sign = &sr->session->signing;
3285331Samw 	int rtn = 0;
3297348SJose.Borrego@Sun.COM 	boolean_t found = B_TRUE;
3305331Samw 	/*
3315331Samw 	 * Don't check secondary transactions - we dont know the sequence
3325331Samw 	 * number.
3335331Samw 	 */
3346139Sjb150015 	if (sr->smb_com == SMB_COM_TRANSACTION_SECONDARY ||
3356139Sjb150015 	    sr->smb_com == SMB_COM_TRANSACTION2_SECONDARY ||
3366139Sjb150015 	    sr->smb_com == SMB_COM_NT_TRANSACT_SECONDARY)
3375331Samw 		return (0);
3385331Samw 
3397348SJose.Borrego@Sun.COM 	/* Reset the offset to begining of header */
3407348SJose.Borrego@Sun.COM 	command.chain_offset = sr->orig_request_hdr;
3415331Samw 
3427348SJose.Borrego@Sun.COM 	/* calculate mac signature */
3437348SJose.Borrego@Sun.COM 	if (smb_sign_calc(&command, sign, sign->seqnum, mac_sig) != 0)
3447348SJose.Borrego@Sun.COM 		return (-1);
3455331Samw 
3467348SJose.Borrego@Sun.COM 	/* compare the signatures */
3477348SJose.Borrego@Sun.COM 	if (memcmp(mac_sig, sr->smb_sig, SMB_SIG_SIZE) != 0) {
3487348SJose.Borrego@Sun.COM 		DTRACE_PROBE2(smb__signing__req, smb_request_t, sr,
3497348SJose.Borrego@Sun.COM 		    smb_sign_t *, sr->smb_sig);
3507348SJose.Borrego@Sun.COM 		cmn_err(CE_NOTE, "message signing: bad signature");
3517348SJose.Borrego@Sun.COM 		/*
3527348SJose.Borrego@Sun.COM 		 * check nearby sequence numbers in debug mode
3537348SJose.Borrego@Sun.COM 		 */
3547348SJose.Borrego@Sun.COM 		SMB_CHECK_SEQNUM(sign, &command, mac_sig, sr->smb_sig, &found);
3557348SJose.Borrego@Sun.COM 		if (found == B_FALSE)
3565331Samw 			rtn = -1;
3575331Samw 	}
3585331Samw 	/*
3597348SJose.Borrego@Sun.COM 	 * Increment the sequence number for the reply, save the reply
3605331Samw 	 * and set it for the next expect command.
3617348SJose.Borrego@Sun.COM 	 * There is no reply for NT Cancel so just increment it for the
3625331Samw 	 * next expected command.
3635331Samw 	 */
3645331Samw 	sign->seqnum++;
3655331Samw 
3666139Sjb150015 	if (sr->smb_com == SMB_COM_NT_CANCEL)
3676139Sjb150015 		sr->reply_seqnum = 0;
3685331Samw 	else
3696139Sjb150015 		sr->reply_seqnum = sign->seqnum++;
3705331Samw 
3715331Samw 	return (rtn);
3725331Samw }
3735331Samw 
3745331Samw /*
3755331Samw  * smb_sign_check_secondary
3765331Samw  *
3775331Samw  * Calculates MAC signature for the secondary transaction mbuf chain
3785331Samw  * and compares it to the given signature.
3795331Samw  * Return 0 if the signature verifies, otherwise, returns -1;
3805331Samw  *
3815331Samw  */
3825331Samw int
3836139Sjb150015 smb_sign_check_secondary(smb_request_t *sr, unsigned int reply_seqnum)
3845331Samw {
3856139Sjb150015 	struct mbuf_chain command = sr->command;
3865331Samw 	unsigned char mac_sig[SMB_SIG_SIZE];
3876139Sjb150015 	struct smb_sign *sign = &sr->session->signing;
3885331Samw 	int rtn = 0;
3895331Samw 
3907348SJose.Borrego@Sun.COM 	/* Reset the offset to begining of header */
3917348SJose.Borrego@Sun.COM 	command.chain_offset = sr->orig_request_hdr;
3925331Samw 
3937348SJose.Borrego@Sun.COM 	/* calculate mac signature */
3947348SJose.Borrego@Sun.COM 	if (smb_sign_calc(&command, sign, reply_seqnum - 1,
3957348SJose.Borrego@Sun.COM 	    mac_sig) != 0)
3967348SJose.Borrego@Sun.COM 		return (-1);
3975331Samw 
3985331Samw 
3997348SJose.Borrego@Sun.COM 	/* compare the signatures */
4007348SJose.Borrego@Sun.COM 	if (memcmp(mac_sig, sr->smb_sig, SMB_SIG_SIZE) != 0) {
4017348SJose.Borrego@Sun.COM 		cmn_err(CE_WARN, "SmbSignCheckSecond: bad signature");
4027348SJose.Borrego@Sun.COM 		rtn = -1;
4035331Samw 	}
4045331Samw 	/* Save the reply sequence number */
4056139Sjb150015 	sr->reply_seqnum = reply_seqnum;
4065331Samw 
4075331Samw 	return (rtn);
4085331Samw }
4095331Samw 
4105331Samw 
4115331Samw 
4125331Samw 
4135331Samw /*
4145331Samw  * smb_sign_reply
4155331Samw  *
4165331Samw  * Calculates MAC signature for the given mbuf chain,
4175331Samw  * and write it to the signature field in the mbuf.
4185331Samw  *
4195331Samw  */
4205331Samw void
4216139Sjb150015 smb_sign_reply(smb_request_t *sr, struct mbuf_chain *reply)
4225331Samw {
4235331Samw 	struct mbuf_chain resp;
4246139Sjb150015 	struct smb_sign *sign = &sr->session->signing;
4255331Samw 	unsigned char signature[SMB_SIG_SIZE];
4265331Samw 	struct mbuf *mbuf;
4275331Samw 	int size = SMB_SIG_SIZE;
4285331Samw 	unsigned char *sig_ptr = signature;
4295331Samw 	int offset = 0;
4305331Samw 
4315331Samw 	if (reply)
4325331Samw 		resp = *reply;
4335331Samw 	else
4346139Sjb150015 		resp = sr->reply;
4355331Samw 
4365331Samw 	/* Reset offset to start of reply */
4375331Samw 	resp.chain_offset = 0;
4385331Samw 	mbuf = resp.chain;
4395331Samw 
4405331Samw 	/*
4415331Samw 	 * Calculate MAC signature
4425331Samw 	 */
4436139Sjb150015 	if (smb_sign_calc(&resp, sign, sr->reply_seqnum, signature) != 0)
4445331Samw 		return;
4455331Samw 
4465331Samw 	/*
4475331Samw 	 * Put signature in the response
4485331Samw 	 *
4495331Samw 	 * First find start of signature in chain (offset + signature offset)
4505331Samw 	 */
4515331Samw 	offset += SMB_SIG_OFFS;
4525331Samw 	while (offset >= mbuf->m_len) {
4535331Samw 		offset -= mbuf->m_len;
4545331Samw 		mbuf = mbuf->m_next;
4555331Samw 	}
4565331Samw 
4575331Samw 	while (size >= mbuf->m_len - offset) {
4585331Samw 		(void) memcpy(&mbuf->m_data[offset],
4595331Samw 		    sig_ptr, mbuf->m_len - offset);
4605331Samw 		offset = 0;
4615331Samw 		sig_ptr += mbuf->m_len - offset;
4625331Samw 		size -= mbuf->m_len - offset;
4635331Samw 		mbuf = mbuf->m_next;
4645331Samw 	}
4655331Samw 	if (size > 0) {
4665331Samw 		(void) memcpy(&mbuf->m_data[offset], sig_ptr, size);
4675331Samw 	}
4685331Samw }
469