xref: /onnv-gate/usr/src/uts/common/fs/smbsrv/smb_signing.c (revision 7348:73b61202d5d6)
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 /*
226139Sjb150015  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
235331Samw  * Use is subject to license terms.
245331Samw  */
255331Samw 
26*7348SJose.Borrego@Sun.COM #pragma ident	"@(#)smb_signing.c	1.4	08/07/08 SMI"
275331Samw 
285331Samw /*
295331Samw  * These routines provide the SMB MAC signing for the SMB server.
305331Samw  * The routines calculate the signature of a SMB message in an mbuf chain.
315331Samw  *
32*7348SJose.Borrego@Sun.COM  * The following table describes the client server
33*7348SJose.Borrego@Sun.COM  * signing registry relationship
34*7348SJose.Borrego@Sun.COM  *
35*7348SJose.Borrego@Sun.COM  *		| Required	| Enabled     | Disabled
36*7348SJose.Borrego@Sun.COM  * -------------+---------------+------------ +--------------
37*7348SJose.Borrego@Sun.COM  * Required	| Signed	| Signed      | Fail
38*7348SJose.Borrego@Sun.COM  * -------------+---------------+-------------+-----------------
39*7348SJose.Borrego@Sun.COM  * Enabled	| Signed	| Signed      | Not Signed
40*7348SJose.Borrego@Sun.COM  * -------------+---------------+-------------+----------------
41*7348SJose.Borrego@Sun.COM  * Disabled	| Fail		| Not Signed  | Not Signed
425331Samw  */
435331Samw 
445331Samw #include <sys/uio.h>
455331Samw #include <smbsrv/mbuf.h>
465331Samw #include <smbsrv/msgbuf.h>
475331Samw #include <sys/crypto/api.h>
485331Samw #include <smbsrv/smb_incl.h>
495331Samw 
506600Sas200622 #define	SMBAUTH_SESSION_KEY_SZ 16
515331Samw #define	SMB_SIG_SIZE	8
525331Samw #define	SMB_SIG_OFFS	14
535331Samw 
54*7348SJose.Borrego@Sun.COM int
55*7348SJose.Borrego@Sun.COM smb_sign_calc(struct mbuf_chain *mbc,
56*7348SJose.Borrego@Sun.COM     struct smb_sign *sign,
57*7348SJose.Borrego@Sun.COM     uint32_t seqnum,
58*7348SJose.Borrego@Sun.COM     unsigned char *mac_sign);
59*7348SJose.Borrego@Sun.COM 
60*7348SJose.Borrego@Sun.COM #ifdef DEBUG
61*7348SJose.Borrego@Sun.COM void smb_sign_find_seqnum(
62*7348SJose.Borrego@Sun.COM     struct smb_sign *sign,
63*7348SJose.Borrego@Sun.COM     struct mbuf_chain *command,
64*7348SJose.Borrego@Sun.COM     unsigned char *mac_sig,
65*7348SJose.Borrego@Sun.COM     unsigned char *sr_sig,
66*7348SJose.Borrego@Sun.COM     boolean_t *found);
67*7348SJose.Borrego@Sun.COM 
68*7348SJose.Borrego@Sun.COM #define	SMB_CHECK_SEQNUM(sign, command, mac_sig, sr_sig, found) \
69*7348SJose.Borrego@Sun.COM { \
70*7348SJose.Borrego@Sun.COM 	if (smb_sign_debug) \
71*7348SJose.Borrego@Sun.COM 		smb_sign_find_seqnum(sign, command, mac_sig, sr_sig, found); \
72*7348SJose.Borrego@Sun.COM }
73*7348SJose.Borrego@Sun.COM #else
74*7348SJose.Borrego@Sun.COM #define	SMB_CHECK_SEQNUM(sign, command, mac_sig, sr_sig, found) \
75*7348SJose.Borrego@Sun.COM 	{  }
76*7348SJose.Borrego@Sun.COM #endif
77*7348SJose.Borrego@Sun.COM 
78*7348SJose.Borrego@Sun.COM #ifdef DEBUG
79*7348SJose.Borrego@Sun.COM void
80*7348SJose.Borrego@Sun.COM smb_sign_find_seqnum(
81*7348SJose.Borrego@Sun.COM     struct smb_sign *sign,
82*7348SJose.Borrego@Sun.COM     struct mbuf_chain *command,
83*7348SJose.Borrego@Sun.COM     unsigned char *mac_sig,
84*7348SJose.Borrego@Sun.COM     unsigned char *sr_sig,
85*7348SJose.Borrego@Sun.COM     boolean_t *found)
86*7348SJose.Borrego@Sun.COM {
87*7348SJose.Borrego@Sun.COM int start_seqnum;
88*7348SJose.Borrego@Sun.COM int i;
89*7348SJose.Borrego@Sun.COM 
90*7348SJose.Borrego@Sun.COM 	/* Debug code to hunt for the sequence number */
91*7348SJose.Borrego@Sun.COM 	*found = B_FALSE;
92*7348SJose.Borrego@Sun.COM 	start_seqnum = (int)sign->seqnum - 6;
93*7348SJose.Borrego@Sun.COM 	if (start_seqnum < 0)
94*7348SJose.Borrego@Sun.COM 		start_seqnum = 0;
95*7348SJose.Borrego@Sun.COM 	for (i = start_seqnum; i <= start_seqnum + 6; i++) {
96*7348SJose.Borrego@Sun.COM 		smb_sign_calc(command, sign, i, mac_sig);
97*7348SJose.Borrego@Sun.COM 		if (memcmp(mac_sig, sr_sig, SMB_SIG_SIZE) == 0) {
98*7348SJose.Borrego@Sun.COM 			sign->seqnum = i;
99*7348SJose.Borrego@Sun.COM 			*found = B_TRUE;
100*7348SJose.Borrego@Sun.COM 			break;
101*7348SJose.Borrego@Sun.COM 		}
102*7348SJose.Borrego@Sun.COM 		cmn_err(CE_WARN, "smb_sign_find_seqnum: seqnum%d mismatch", i);
103*7348SJose.Borrego@Sun.COM 	}
104*7348SJose.Borrego@Sun.COM 	cmn_err(CE_WARN, "smb_sign_find_seqnum: found=%d", *found);
105*7348SJose.Borrego@Sun.COM }
106*7348SJose.Borrego@Sun.COM #endif
1075331Samw /* This holds the MD5 mechanism */
1085331Samw static	crypto_mechanism_t crypto_mech = {CRYPTO_MECHANISM_INVALID, 0, 0};
1095331Samw 
1105331Samw /*
1115331Samw  * smb_sign_init
1125331Samw  *
1135331Samw  * Intializes MAC key based on the user session key and
1145331Samw  * NTLM response and store it in the signing structure.
1155331Samw  */
1165331Samw void
1176139Sjb150015 smb_sign_init(smb_request_t *sr, smb_session_key_t *session_key,
1185331Samw 	char *resp, int resp_len)
1195331Samw {
1206139Sjb150015 	struct smb_sign *sign = &sr->session->signing;
1215331Samw 
1225331Samw 	/*
1235331Samw 	 * Initialise the crypto mechanism to MD5 if it not
1245331Samw 	 * already initialised.
1255331Samw 	 */
1265331Samw 	if (crypto_mech.cm_type ==  CRYPTO_MECHANISM_INVALID) {
1275331Samw 		crypto_mech.cm_type = crypto_mech2id(SUN_CKM_MD5);
1285331Samw 		if (crypto_mech.cm_type == CRYPTO_MECHANISM_INVALID) {
1295331Samw 			/*
1305331Samw 			 * There is no MD5 crypto mechanism
1315331Samw 			 * so turn off signing
1325331Samw 			 */
1336139Sjb150015 			sr->sr_cfg->skc_signing_enable = 0;
1346139Sjb150015 			sr->session->secmode &=
1355331Samw 			    (~NEGOTIATE_SECURITY_SIGNATURES_ENABLED);
1365331Samw 			cmn_err(CE_WARN,
1375331Samw 			    "SmbSignInit: signing disabled (no MD5)");
1385331Samw 			return;
1395331Samw 		}
1405331Samw 	}
1415331Samw 
1425331Samw 	/* MAC key = concat (SessKey, NTLMResponse) */
1435331Samw 
1445331Samw 	bcopy(session_key, sign->mackey, sizeof (smb_session_key_t));
1455331Samw 	bcopy(resp, &(sign->mackey[sizeof (smb_session_key_t)]),
1465331Samw 	    resp_len);
1475331Samw 	sign->mackey_len = sizeof (smb_session_key_t) + resp_len;
1485331Samw 
1496139Sjb150015 	sr->reply_seqnum = 1;
1505331Samw 	sign->seqnum = 2;
1515331Samw 	sign->flags = SMB_SIGNING_ENABLED;
1525331Samw 
1535331Samw }
1545331Samw 
1555331Samw /*
1565331Samw  * smb_sign_calc
1575331Samw  *
1585331Samw  * Calculates MAC signature for the given buffer and returns
1595331Samw  * it in the mac_sign parameter.
1605331Samw  *
1615331Samw  * The sequence number is placed in the first four bytes of the signature
1625331Samw  * field of the signature and the other 4 bytes are zeroed.
1635331Samw  * The signature is the first 8 bytes of the MD5 result of the
1645331Samw  * concatenated MAC key and the SMB message.
1655331Samw  *
1665331Samw  * MACsig = head(MD5(concat(MACKey, SMBMsg)), 8)
1675331Samw  *
1685331Samw  * where
1695331Samw  *
1705331Samw  *	MACKey = concat( UserSessionKey, NTLMResp )
1715331Samw  *
1725331Samw  * and
1735331Samw  *
1745331Samw  *	SMBMsg is the SMB message containing the sequence number.
1755331Samw  *
1765331Samw  * Return 0 if  success else -1
1775331Samw  *
1785331Samw  */
179*7348SJose.Borrego@Sun.COM int
1805331Samw smb_sign_calc(struct mbuf_chain *mbc,
1815331Samw     struct smb_sign *sign,
1825331Samw     uint32_t seqnum,
1835331Samw     unsigned char *mac_sign)
1845331Samw {
1855331Samw 	uint32_t seq_buf[2] = {0, 0};
1865331Samw 	unsigned char mac[16];
1875331Samw 	struct mbuf *mbuf = mbc->chain;
1885331Samw 	int offset = mbc->chain_offset;
1895331Samw 	int size;
1905331Samw 	int status;
1915331Samw 
1925331Samw 	crypto_data_t data;
1935331Samw 	crypto_data_t digest;
1945331Samw 	crypto_context_t crypto_ctx;
1955331Samw 
1965331Samw 	data.cd_format = CRYPTO_DATA_RAW;
1975331Samw 	data.cd_offset = 0;
1985331Samw 	data.cd_length = (size_t)-1;
1995331Samw 	data.cd_miscdata = 0;
2005331Samw 
2015331Samw 	digest.cd_format = CRYPTO_DATA_RAW;
2025331Samw 	digest.cd_offset = 0;
2035331Samw 	digest.cd_length = (size_t)-1;
2045331Samw 	digest.cd_miscdata = 0;
2055331Samw 	digest.cd_raw.iov_base = (char *)mac;
2065331Samw 	digest.cd_raw.iov_len = sizeof (mac);
2075331Samw 
2085331Samw 	status = crypto_digest_init(&crypto_mech, &crypto_ctx, 0);
2096600Sas200622 	if (status != CRYPTO_SUCCESS)
2106600Sas200622 		goto error;
2115331Samw 
2125331Samw 	/*
2135331Samw 	 * Put the sequence number into the first 4 bytes
2145331Samw 	 * of the signature field in little endian format.
2155331Samw 	 * We are using a buffer to represent the signature
2165331Samw 	 * rather than modifying the SMB message.
2175331Samw 	 */
2185331Samw #ifdef __sparc
2195331Samw 	{
2205331Samw 		uint32_t temp;
2215331Samw 		((uint8_t *)&temp)[0] = ((uint8_t *)&seqnum)[3];
2225331Samw 		((uint8_t *)&temp)[1] = ((uint8_t *)&seqnum)[2];
2235331Samw 		((uint8_t *)&temp)[2] = ((uint8_t *)&seqnum)[1];
2245331Samw 		((uint8_t *)&temp)[3] = ((uint8_t *)&seqnum)[0];
2255331Samw 
2265331Samw 		seq_buf[0] = temp;
2275331Samw 	}
2285331Samw #else
2295331Samw 	seq_buf[0] = seqnum;
2305331Samw #endif
2315331Samw 
2325331Samw 	/* Digest the MACKey */
2335331Samw 	data.cd_raw.iov_base = (char *)sign->mackey;
2345331Samw 	data.cd_raw.iov_len = sign->mackey_len;
2356600Sas200622 	data.cd_length = sign->mackey_len;
2366600Sas200622 	status = crypto_digest_update(crypto_ctx, &data, 0);
2376600Sas200622 	if (status != CRYPTO_SUCCESS)
2386600Sas200622 		goto error;
2395331Samw 
2405331Samw 	/* Find start of data in chain */
2415331Samw 	while (offset >= mbuf->m_len) {
2425331Samw 		offset -= mbuf->m_len;
2435331Samw 		mbuf = mbuf->m_next;
2445331Samw 	}
2455331Samw 
2465331Samw 	/* Digest the SMB packet up to the signature field */
2475331Samw 	size = SMB_SIG_OFFS;
2485331Samw 	while (size >= mbuf->m_len - offset) {
2495331Samw 		data.cd_raw.iov_base = &mbuf->m_data[offset];
2505331Samw 		data.cd_raw.iov_len = mbuf->m_len - offset;
2516600Sas200622 		data.cd_length = mbuf->m_len - offset;
2526600Sas200622 		status = crypto_digest_update(crypto_ctx, &data, 0);
2536600Sas200622 		if (status != CRYPTO_SUCCESS)
2546600Sas200622 			goto error;
2555331Samw 
2565331Samw 		size -= mbuf->m_len - offset;
2575331Samw 		mbuf = mbuf->m_next;
2585331Samw 		offset = 0;
2595331Samw 	}
2605331Samw 	if (size > 0) {
2615331Samw 		data.cd_raw.iov_base = &mbuf->m_data[offset];
2625331Samw 		data.cd_raw.iov_len = size;
2636600Sas200622 		data.cd_length = size;
2646600Sas200622 		status = crypto_digest_update(crypto_ctx, &data, 0);
2656600Sas200622 		if (status != CRYPTO_SUCCESS)
2666600Sas200622 			goto error;
2675331Samw 		offset += size;
2685331Samw 	}
2695331Samw 
2705331Samw 	/*
2715331Samw 	 * Digest in the seq_buf instead of the signature
2725331Samw 	 * which has the sequence number
2735331Samw 	 */
2745331Samw 
2755331Samw 	data.cd_raw.iov_base = (char *)seq_buf;
2765331Samw 	data.cd_raw.iov_len = SMB_SIG_SIZE;
2776600Sas200622 	data.cd_length = SMB_SIG_SIZE;
2786600Sas200622 	status = crypto_digest_update(crypto_ctx, &data, 0);
2796600Sas200622 	if (status != CRYPTO_SUCCESS)
2806600Sas200622 		goto error;
2815331Samw 
2825331Samw 	/* Find the end of the signature field  */
2835331Samw 	offset += SMB_SIG_SIZE;
2845331Samw 	while (offset >= mbuf->m_len) {
2855331Samw 		offset -= mbuf->m_len;
2865331Samw 		mbuf = mbuf->m_next;
2875331Samw 	}
2885331Samw 	/* Digest the rest of the SMB packet */
2895331Samw 	while (mbuf) {
2905331Samw 		data.cd_raw.iov_base = &mbuf->m_data[offset];
2915331Samw 		data.cd_raw.iov_len = mbuf->m_len - offset;
2926600Sas200622 		data.cd_length = mbuf->m_len - offset;
2936600Sas200622 		status = crypto_digest_update(crypto_ctx, &data, 0);
2946600Sas200622 		if (status != CRYPTO_SUCCESS)
2956600Sas200622 			goto error;
2965331Samw 		mbuf = mbuf->m_next;
2975331Samw 		offset = 0;
2985331Samw 	}
2996600Sas200622 	digest.cd_length = SMBAUTH_SESSION_KEY_SZ;
3006600Sas200622 	status = crypto_digest_final(crypto_ctx, &digest, 0);
3016600Sas200622 	if (status != CRYPTO_SUCCESS)
3026600Sas200622 		goto error;
3035331Samw 	bcopy(mac, mac_sign, SMB_SIG_SIZE);
3045331Samw 	return (0);
3055331Samw error:
3065331Samw 	cmn_err(CE_WARN, "SmbSignCalc: crypto error %d", status);
3075331Samw 	return (-1);
3085331Samw 
3095331Samw }
3105331Samw 
3115331Samw 
3125331Samw /*
3135331Samw  * smb_sign_check_request
3145331Samw  *
3155331Samw  * Calculates MAC signature for the request mbuf chain
3165331Samw  * using the next expected sequence number and compares
3175331Samw  * it to the given signature.
3185331Samw  *
3195331Samw  * Note it does not check the signature for secondary transactions
3205331Samw  * as their sequence number is the same as the original request.
3215331Samw  *
3225331Samw  * Return 0 if the signature verifies, otherwise, returns -1;
3235331Samw  *
3245331Samw  */
3255331Samw int
3266139Sjb150015 smb_sign_check_request(smb_request_t *sr)
3275331Samw {
3286139Sjb150015 	struct mbuf_chain command = sr->command;
3295331Samw 	unsigned char mac_sig[SMB_SIG_SIZE];
3306139Sjb150015 	struct smb_sign *sign = &sr->session->signing;
3315331Samw 	int rtn = 0;
332*7348SJose.Borrego@Sun.COM 	boolean_t found = B_TRUE;
3335331Samw 	/*
3345331Samw 	 * Don't check secondary transactions - we dont know the sequence
3355331Samw 	 * number.
3365331Samw 	 */
3376139Sjb150015 	if (sr->smb_com == SMB_COM_TRANSACTION_SECONDARY ||
3386139Sjb150015 	    sr->smb_com == SMB_COM_TRANSACTION2_SECONDARY ||
3396139Sjb150015 	    sr->smb_com == SMB_COM_NT_TRANSACT_SECONDARY)
3405331Samw 		return (0);
3415331Samw 
342*7348SJose.Borrego@Sun.COM 	/* Reset the offset to begining of header */
343*7348SJose.Borrego@Sun.COM 	command.chain_offset = sr->orig_request_hdr;
3445331Samw 
345*7348SJose.Borrego@Sun.COM 	/* calculate mac signature */
346*7348SJose.Borrego@Sun.COM 	if (smb_sign_calc(&command, sign, sign->seqnum, mac_sig) != 0)
347*7348SJose.Borrego@Sun.COM 		return (-1);
3485331Samw 
349*7348SJose.Borrego@Sun.COM 	/* compare the signatures */
350*7348SJose.Borrego@Sun.COM 	if (memcmp(mac_sig, sr->smb_sig, SMB_SIG_SIZE) != 0) {
351*7348SJose.Borrego@Sun.COM 		DTRACE_PROBE2(smb__signing__req, smb_request_t, sr,
352*7348SJose.Borrego@Sun.COM 		    smb_sign_t *, sr->smb_sig);
353*7348SJose.Borrego@Sun.COM 		cmn_err(CE_NOTE, "message signing: bad signature");
354*7348SJose.Borrego@Sun.COM 		/*
355*7348SJose.Borrego@Sun.COM 		 * check nearby sequence numbers in debug mode
356*7348SJose.Borrego@Sun.COM 		 */
357*7348SJose.Borrego@Sun.COM 		SMB_CHECK_SEQNUM(sign, &command, mac_sig, sr->smb_sig, &found);
358*7348SJose.Borrego@Sun.COM 		if (found == B_FALSE)
3595331Samw 			rtn = -1;
3605331Samw 	}
3615331Samw 	/*
362*7348SJose.Borrego@Sun.COM 	 * Increment the sequence number for the reply, save the reply
3635331Samw 	 * and set it for the next expect command.
364*7348SJose.Borrego@Sun.COM 	 * There is no reply for NT Cancel so just increment it for the
3655331Samw 	 * next expected command.
3665331Samw 	 */
3675331Samw 	sign->seqnum++;
3685331Samw 
3696139Sjb150015 	if (sr->smb_com == SMB_COM_NT_CANCEL)
3706139Sjb150015 		sr->reply_seqnum = 0;
3715331Samw 	else
3726139Sjb150015 		sr->reply_seqnum = sign->seqnum++;
3735331Samw 
3745331Samw 	return (rtn);
3755331Samw }
3765331Samw 
3775331Samw /*
3785331Samw  * smb_sign_check_secondary
3795331Samw  *
3805331Samw  * Calculates MAC signature for the secondary transaction mbuf chain
3815331Samw  * and compares it to the given signature.
3825331Samw  * Return 0 if the signature verifies, otherwise, returns -1;
3835331Samw  *
3845331Samw  */
3855331Samw int
3866139Sjb150015 smb_sign_check_secondary(smb_request_t *sr, unsigned int reply_seqnum)
3875331Samw {
3886139Sjb150015 	struct mbuf_chain command = sr->command;
3895331Samw 	unsigned char mac_sig[SMB_SIG_SIZE];
3906139Sjb150015 	struct smb_sign *sign = &sr->session->signing;
3915331Samw 	int rtn = 0;
3925331Samw 
393*7348SJose.Borrego@Sun.COM 	/* Reset the offset to begining of header */
394*7348SJose.Borrego@Sun.COM 	command.chain_offset = sr->orig_request_hdr;
3955331Samw 
396*7348SJose.Borrego@Sun.COM 	/* calculate mac signature */
397*7348SJose.Borrego@Sun.COM 	if (smb_sign_calc(&command, sign, reply_seqnum - 1,
398*7348SJose.Borrego@Sun.COM 	    mac_sig) != 0)
399*7348SJose.Borrego@Sun.COM 		return (-1);
4005331Samw 
4015331Samw 
402*7348SJose.Borrego@Sun.COM 	/* compare the signatures */
403*7348SJose.Borrego@Sun.COM 	if (memcmp(mac_sig, sr->smb_sig, SMB_SIG_SIZE) != 0) {
404*7348SJose.Borrego@Sun.COM 		cmn_err(CE_WARN, "SmbSignCheckSecond: bad signature");
405*7348SJose.Borrego@Sun.COM 		rtn = -1;
4065331Samw 	}
4075331Samw 	/* Save the reply sequence number */
4086139Sjb150015 	sr->reply_seqnum = reply_seqnum;
4095331Samw 
4105331Samw 	return (rtn);
4115331Samw }
4125331Samw 
4135331Samw 
4145331Samw 
4155331Samw 
4165331Samw /*
4175331Samw  * smb_sign_reply
4185331Samw  *
4195331Samw  * Calculates MAC signature for the given mbuf chain,
4205331Samw  * and write it to the signature field in the mbuf.
4215331Samw  *
4225331Samw  */
4235331Samw void
4246139Sjb150015 smb_sign_reply(smb_request_t *sr, struct mbuf_chain *reply)
4255331Samw {
4265331Samw 	struct mbuf_chain resp;
4276139Sjb150015 	struct smb_sign *sign = &sr->session->signing;
4285331Samw 	unsigned char signature[SMB_SIG_SIZE];
4295331Samw 	struct mbuf *mbuf;
4305331Samw 	int size = SMB_SIG_SIZE;
4315331Samw 	unsigned char *sig_ptr = signature;
4325331Samw 	int offset = 0;
4335331Samw 
4345331Samw 	if (reply)
4355331Samw 		resp = *reply;
4365331Samw 	else
4376139Sjb150015 		resp = sr->reply;
4385331Samw 
4395331Samw 	/* Reset offset to start of reply */
4405331Samw 	resp.chain_offset = 0;
4415331Samw 	mbuf = resp.chain;
4425331Samw 
4435331Samw 	/*
4445331Samw 	 * Calculate MAC signature
4455331Samw 	 */
4466139Sjb150015 	if (smb_sign_calc(&resp, sign, sr->reply_seqnum, signature) != 0)
4475331Samw 		return;
4485331Samw 
4495331Samw 	/*
4505331Samw 	 * Put signature in the response
4515331Samw 	 *
4525331Samw 	 * First find start of signature in chain (offset + signature offset)
4535331Samw 	 */
4545331Samw 	offset += SMB_SIG_OFFS;
4555331Samw 	while (offset >= mbuf->m_len) {
4565331Samw 		offset -= mbuf->m_len;
4575331Samw 		mbuf = mbuf->m_next;
4585331Samw 	}
4595331Samw 
4605331Samw 	while (size >= mbuf->m_len - offset) {
4615331Samw 		(void) memcpy(&mbuf->m_data[offset],
4625331Samw 		    sig_ptr, mbuf->m_len - offset);
4635331Samw 		offset = 0;
4645331Samw 		sig_ptr += mbuf->m_len - offset;
4655331Samw 		size -= mbuf->m_len - offset;
4665331Samw 		mbuf = mbuf->m_next;
4675331Samw 	}
4685331Samw 	if (size > 0) {
4695331Samw 		(void) memcpy(&mbuf->m_data[offset], sig_ptr, size);
4705331Samw 	}
4715331Samw }
472