1da6c28aaSamw /*
2da6c28aaSamw * CDDL HEADER START
3da6c28aaSamw *
4da6c28aaSamw * The contents of this file are subject to the terms of the
5da6c28aaSamw * Common Development and Distribution License (the "License").
6da6c28aaSamw * You may not use this file except in compliance with the License.
7da6c28aaSamw *
8da6c28aaSamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aaSamw * or http://www.opensolaris.org/os/licensing.
10da6c28aaSamw * See the License for the specific language governing permissions
11da6c28aaSamw * and limitations under the License.
12da6c28aaSamw *
13da6c28aaSamw * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aaSamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aaSamw * If applicable, add the following below this CDDL HEADER, with the
16da6c28aaSamw * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aaSamw * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aaSamw *
19da6c28aaSamw * CDDL HEADER END
20da6c28aaSamw */
21da6c28aaSamw /*
22148c5f43SAlan Wright * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23*b819cea2SGordon Ross * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
24da6c28aaSamw */
25da6c28aaSamw /*
26da6c28aaSamw * These routines provide the SMB MAC signing for the SMB server.
27da6c28aaSamw * The routines calculate the signature of a SMB message in an mbuf chain.
28da6c28aaSamw *
29c8ec8eeaSjose borrego * The following table describes the client server
30c8ec8eeaSjose borrego * signing registry relationship
31c8ec8eeaSjose borrego *
32c8ec8eeaSjose borrego * | Required | Enabled | Disabled
33c8ec8eeaSjose borrego * -------------+---------------+------------ +--------------
34c8ec8eeaSjose borrego * Required | Signed | Signed | Fail
35c8ec8eeaSjose borrego * -------------+---------------+-------------+-----------------
36c8ec8eeaSjose borrego * Enabled | Signed | Signed | Not Signed
37c8ec8eeaSjose borrego * -------------+---------------+-------------+----------------
38c8ec8eeaSjose borrego * Disabled | Fail | Not Signed | Not Signed
39da6c28aaSamw */
40da6c28aaSamw
41da6c28aaSamw #include <sys/uio.h>
42bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h>
43*b819cea2SGordon Ross #include <smbsrv/smb_signing.h>
44*b819cea2SGordon Ross #include <sys/isa_defs.h>
45*b819cea2SGordon Ross #include <sys/byteorder.h>
46da6c28aaSamw
47*b819cea2SGordon Ross #define SSN_KEY_LEN 16
48da6c28aaSamw #define SMB_SIG_SIZE 8
49da6c28aaSamw #define SMB_SIG_OFFS 14
50*b819cea2SGordon Ross #define SMB_HDRLEN 32
51*b819cea2SGordon Ross
52*b819cea2SGordon Ross #ifdef _LITTLE_ENDIAN
53*b819cea2SGordon Ross #define htolel(x) ((uint32_t)(x))
54*b819cea2SGordon Ross #else
55*b819cea2SGordon Ross #define htolel(x) BSWAP_32(x)
56*b819cea2SGordon Ross #endif
57da6c28aaSamw
58c8ec8eeaSjose borrego int
59c8ec8eeaSjose borrego smb_sign_calc(struct mbuf_chain *mbc,
60c8ec8eeaSjose borrego struct smb_sign *sign,
61c8ec8eeaSjose borrego uint32_t seqnum,
62c8ec8eeaSjose borrego unsigned char *mac_sign);
63c8ec8eeaSjose borrego
64c8ec8eeaSjose borrego #ifdef DEBUG
65*b819cea2SGordon Ross static void
smb_sign_find_seqnum(uint32_t seqnum,struct smb_sign * sign,struct mbuf_chain * command,unsigned char * mac_sig,unsigned char * sr_sig,boolean_t * found)66c8ec8eeaSjose borrego smb_sign_find_seqnum(
67148c5f43SAlan Wright uint32_t seqnum,
68c8ec8eeaSjose borrego struct smb_sign *sign,
69c8ec8eeaSjose borrego struct mbuf_chain *command,
70c8ec8eeaSjose borrego unsigned char *mac_sig,
71c8ec8eeaSjose borrego unsigned char *sr_sig,
72c8ec8eeaSjose borrego boolean_t *found)
73c8ec8eeaSjose borrego {
74c8ec8eeaSjose borrego int start_seqnum;
75c8ec8eeaSjose borrego int i;
76c8ec8eeaSjose borrego
77c8ec8eeaSjose borrego /* Debug code to hunt for the sequence number */
78c8ec8eeaSjose borrego *found = B_FALSE;
79148c5f43SAlan Wright start_seqnum = seqnum - 10;
80c8ec8eeaSjose borrego if (start_seqnum < 0)
81c8ec8eeaSjose borrego start_seqnum = 0;
82148c5f43SAlan Wright for (i = start_seqnum; i <= start_seqnum + 20; i++) {
83e8e4e80fSNick Todd (void) smb_sign_calc(command, sign, i, mac_sig);
84c8ec8eeaSjose borrego if (memcmp(mac_sig, sr_sig, SMB_SIG_SIZE) == 0) {
85c8ec8eeaSjose borrego sign->seqnum = i;
86c8ec8eeaSjose borrego *found = B_TRUE;
87c8ec8eeaSjose borrego break;
88c8ec8eeaSjose borrego }
89148c5f43SAlan Wright cmn_err(CE_WARN, "smb_sign_find_seqnum: seqnum:%d mismatch", i);
90c8ec8eeaSjose borrego }
91c8ec8eeaSjose borrego cmn_err(CE_WARN, "smb_sign_find_seqnum: found=%d", *found);
92c8ec8eeaSjose borrego }
93c8ec8eeaSjose borrego #endif
94148c5f43SAlan Wright
958622ec45SGordon Ross /*
96*b819cea2SGordon Ross * Called during session destroy.
978622ec45SGordon Ross */
98*b819cea2SGordon Ross static void
smb_sign_fini(smb_session_t * s)99*b819cea2SGordon Ross smb_sign_fini(smb_session_t *s)
100*b819cea2SGordon Ross {
101*b819cea2SGordon Ross smb_sign_mech_t *mech;
102*b819cea2SGordon Ross
103*b819cea2SGordon Ross if ((mech = s->signing.mech) != NULL) {
104*b819cea2SGordon Ross kmem_free(mech, sizeof (*mech));
105*b819cea2SGordon Ross s->signing.mech = NULL;
1068622ec45SGordon Ross }
1078622ec45SGordon Ross }
1088622ec45SGordon Ross
109da6c28aaSamw /*
110*b819cea2SGordon Ross * smb_sign_begin
111da6c28aaSamw *
112da6c28aaSamw * Intializes MAC key based on the user session key and
113da6c28aaSamw * NTLM response and store it in the signing structure.
114*b819cea2SGordon Ross * This is what begins SMB signing.
115da6c28aaSamw */
116*b819cea2SGordon Ross int
smb_sign_begin(smb_request_t * sr,smb_token_t * token)117*b819cea2SGordon Ross smb_sign_begin(smb_request_t *sr, smb_token_t *token)
118da6c28aaSamw {
119*b819cea2SGordon Ross smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup;
120*b819cea2SGordon Ross smb_session_t *session = sr->session;
121*b819cea2SGordon Ross struct smb_sign *sign = &session->signing;
122*b819cea2SGordon Ross smb_sign_mech_t *mech;
123*b819cea2SGordon Ross int rc;
124da6c28aaSamw
125da6c28aaSamw /*
126*b819cea2SGordon Ross * Session-level initialization (once per session)
127da6c28aaSamw */
128*b819cea2SGordon Ross smb_rwx_rwenter(&session->s_lock, RW_WRITER);
129*b819cea2SGordon Ross
130*b819cea2SGordon Ross /*
131*b819cea2SGordon Ross * Signing may already have been setup by a prior logon,
132*b819cea2SGordon Ross * in which case we're done here.
133*b819cea2SGordon Ross */
134*b819cea2SGordon Ross if (sign->mackey != NULL) {
135*b819cea2SGordon Ross smb_rwx_rwexit(&session->s_lock);
136*b819cea2SGordon Ross return (0);
137da6c28aaSamw }
138da6c28aaSamw
139*b819cea2SGordon Ross /*
140*b819cea2SGordon Ross * Get the mech handle
141*b819cea2SGordon Ross */
142*b819cea2SGordon Ross if (sign->mech == NULL) {
143*b819cea2SGordon Ross mech = kmem_zalloc(sizeof (*mech), KM_SLEEP);
144*b819cea2SGordon Ross rc = smb_md5_getmech(mech);
145*b819cea2SGordon Ross if (rc != 0) {
146*b819cea2SGordon Ross kmem_free(mech, sizeof (*mech));
147*b819cea2SGordon Ross smb_rwx_rwexit(&session->s_lock);
148*b819cea2SGordon Ross return (rc);
149*b819cea2SGordon Ross }
150*b819cea2SGordon Ross sign->mech = mech;
151*b819cea2SGordon Ross session->sign_fini = smb_sign_fini;
152*b819cea2SGordon Ross }
153da6c28aaSamw
154*b819cea2SGordon Ross /*
155*b819cea2SGordon Ross * Compute and store the signing (MAC) key.
156*b819cea2SGordon Ross *
157*b819cea2SGordon Ross * With extended security, the MAC key is the same as the
158*b819cea2SGordon Ross * session key (and we'll have sinfo->ssi_cspwlen == 0).
159*b819cea2SGordon Ross * With non-extended security, it's the concatenation of
160*b819cea2SGordon Ross * the session key and the "NT response" we received.
161*b819cea2SGordon Ross * (NB: no extended security yet)
162*b819cea2SGordon Ross */
163*b819cea2SGordon Ross sign->mackey_len = SSN_KEY_LEN + sinfo->ssi_cspwlen;
164*b819cea2SGordon Ross sign->mackey = kmem_alloc(sign->mackey_len, KM_SLEEP);
165*b819cea2SGordon Ross bcopy(token->tkn_session_key, sign->mackey, SSN_KEY_LEN);
166*b819cea2SGordon Ross if (sinfo->ssi_cspwlen > 0) {
167*b819cea2SGordon Ross bcopy(sinfo->ssi_cspwd, sign->mackey + SSN_KEY_LEN,
168*b819cea2SGordon Ross sinfo->ssi_cspwlen);
169*b819cea2SGordon Ross }
170da6c28aaSamw
171*b819cea2SGordon Ross session->signing.seqnum = 0;
172148c5f43SAlan Wright sr->sr_seqnum = 2;
173faa1795aSjb150015 sr->reply_seqnum = 1;
174*b819cea2SGordon Ross sign->flags = 0;
175*b819cea2SGordon Ross
176*b819cea2SGordon Ross if (session->secmode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
177*b819cea2SGordon Ross sign->flags |= SMB_SIGNING_ENABLED;
178*b819cea2SGordon Ross if (session->secmode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED)
179*b819cea2SGordon Ross sign->flags |= SMB_SIGNING_CHECK;
180*b819cea2SGordon Ross }
181*b819cea2SGordon Ross
182*b819cea2SGordon Ross smb_rwx_rwexit(&session->s_lock);
183*b819cea2SGordon Ross return (0);
184da6c28aaSamw }
185da6c28aaSamw
186da6c28aaSamw /*
187da6c28aaSamw * smb_sign_calc
188da6c28aaSamw *
189da6c28aaSamw * Calculates MAC signature for the given buffer and returns
190da6c28aaSamw * it in the mac_sign parameter.
191da6c28aaSamw *
192da6c28aaSamw * The sequence number is placed in the first four bytes of the signature
193da6c28aaSamw * field of the signature and the other 4 bytes are zeroed.
194da6c28aaSamw * The signature is the first 8 bytes of the MD5 result of the
195da6c28aaSamw * concatenated MAC key and the SMB message.
196da6c28aaSamw *
197da6c28aaSamw * MACsig = head(MD5(concat(MACKey, SMBMsg)), 8)
198da6c28aaSamw *
199da6c28aaSamw * where
200da6c28aaSamw *
201da6c28aaSamw * MACKey = concat( UserSessionKey, NTLMResp )
202da6c28aaSamw *
203da6c28aaSamw * and
204da6c28aaSamw *
205da6c28aaSamw * SMBMsg is the SMB message containing the sequence number.
206da6c28aaSamw *
207*b819cea2SGordon Ross * Return 0 if success
208da6c28aaSamw *
209da6c28aaSamw */
210c8ec8eeaSjose borrego int
smb_sign_calc(struct mbuf_chain * mbc,struct smb_sign * sign,uint32_t seqnum,unsigned char * mac_sign)211da6c28aaSamw smb_sign_calc(struct mbuf_chain *mbc,
212da6c28aaSamw struct smb_sign *sign,
213da6c28aaSamw uint32_t seqnum,
214da6c28aaSamw unsigned char *mac_sign)
215da6c28aaSamw {
216*b819cea2SGordon Ross smb_sign_ctx_t ctx = 0;
217*b819cea2SGordon Ross uchar_t digest[MD5_DIGEST_LENGTH];
218*b819cea2SGordon Ross uchar_t *hdrp;
219da6c28aaSamw struct mbuf *mbuf = mbc->chain;
220da6c28aaSamw int offset = mbc->chain_offset;
221da6c28aaSamw int size;
222*b819cea2SGordon Ross int rc;
223da6c28aaSamw
224da6c28aaSamw /*
225*b819cea2SGordon Ross * This union is a little bit of trickery to:
226*b819cea2SGordon Ross * (1) get the sequence number int aligned, and
227*b819cea2SGordon Ross * (2) reduce the number of digest calls, at the
228*b819cea2SGordon Ross * cost of a copying 32 bytes instead of 8.
229*b819cea2SGordon Ross * Both sides of this union are 2+32 bytes.
230da6c28aaSamw */
231*b819cea2SGordon Ross union {
232*b819cea2SGordon Ross struct {
233*b819cea2SGordon Ross uint8_t skip[2]; /* not used - just alignment */
234*b819cea2SGordon Ross uint8_t raw[SMB_HDRLEN]; /* header length (32) */
235*b819cea2SGordon Ross } r;
236*b819cea2SGordon Ross struct {
237*b819cea2SGordon Ross uint8_t skip[2]; /* not used - just alignment */
238*b819cea2SGordon Ross uint8_t hdr[SMB_SIG_OFFS]; /* sig. offset (14) */
239*b819cea2SGordon Ross uint32_t sig[2]; /* MAC signature, aligned! */
240*b819cea2SGordon Ross uint16_t ids[5]; /* pad, Tid, Pid, Uid, Mid */
241*b819cea2SGordon Ross } s;
242*b819cea2SGordon Ross } smbhdr;
243da6c28aaSamw
244*b819cea2SGordon Ross if (sign->mech == NULL || sign->mackey == NULL)
245da6c28aaSamw return (-1);
246da6c28aaSamw
247*b819cea2SGordon Ross if ((rc = smb_md5_init(&ctx, sign->mech)) != 0)
248*b819cea2SGordon Ross return (rc);
249*b819cea2SGordon Ross
250*b819cea2SGordon Ross /* Digest the MAC Key */
251*b819cea2SGordon Ross rc = smb_md5_update(ctx, sign->mackey, sign->mackey_len);
252*b819cea2SGordon Ross if (rc != 0)
253*b819cea2SGordon Ross return (rc);
254*b819cea2SGordon Ross
255*b819cea2SGordon Ross /*
256*b819cea2SGordon Ross * Make an aligned copy of the SMB header,
257*b819cea2SGordon Ross * fill in the sequence number, and digest.
258*b819cea2SGordon Ross */
259*b819cea2SGordon Ross hdrp = (unsigned char *)&smbhdr.r.raw;
260*b819cea2SGordon Ross size = SMB_HDRLEN;
261*b819cea2SGordon Ross if (smb_mbc_peek(mbc, offset, "#c", size, hdrp) != 0)
262*b819cea2SGordon Ross return (-1);
263*b819cea2SGordon Ross smbhdr.s.sig[0] = htolel(seqnum);
264*b819cea2SGordon Ross smbhdr.s.sig[1] = 0;
265*b819cea2SGordon Ross
266*b819cea2SGordon Ross rc = smb_md5_update(ctx, &smbhdr.r.raw, size);
267*b819cea2SGordon Ross if (rc != 0)
268*b819cea2SGordon Ross return (rc);
269*b819cea2SGordon Ross
270*b819cea2SGordon Ross /*
271*b819cea2SGordon Ross * Digest the rest of the SMB packet, starting at the data
272*b819cea2SGordon Ross * just after the SMB header.
273*b819cea2SGordon Ross */
274*b819cea2SGordon Ross offset += size;
275*b819cea2SGordon Ross while (mbuf != NULL && (offset >= mbuf->m_len)) {
276*b819cea2SGordon Ross offset -= mbuf->m_len;
277*b819cea2SGordon Ross mbuf = mbuf->m_next;
278*b819cea2SGordon Ross }
279*b819cea2SGordon Ross if (mbuf != NULL && (size = (mbuf->m_len - offset)) > 0) {
280*b819cea2SGordon Ross rc = smb_md5_update(ctx, &mbuf->m_data[offset], size);
281*b819cea2SGordon Ross if (rc != 0)
282*b819cea2SGordon Ross return (rc);
283*b819cea2SGordon Ross offset = 0;
284*b819cea2SGordon Ross mbuf = mbuf->m_next;
285*b819cea2SGordon Ross }
286*b819cea2SGordon Ross while (mbuf != NULL) {
287*b819cea2SGordon Ross rc = smb_md5_update(ctx, mbuf->m_data, mbuf->m_len);
288*b819cea2SGordon Ross if (rc != 0)
289*b819cea2SGordon Ross return (rc);
290*b819cea2SGordon Ross mbuf = mbuf->m_next;
291*b819cea2SGordon Ross }
292*b819cea2SGordon Ross rc = smb_md5_final(ctx, digest);
293*b819cea2SGordon Ross if (rc == 0)
294*b819cea2SGordon Ross bcopy(digest, mac_sign, SMB_SIG_SIZE);
295*b819cea2SGordon Ross
296*b819cea2SGordon Ross return (rc);
297da6c28aaSamw }
298da6c28aaSamw
299da6c28aaSamw
300da6c28aaSamw /*
301da6c28aaSamw * smb_sign_check_request
302da6c28aaSamw *
303da6c28aaSamw * Calculates MAC signature for the request mbuf chain
304da6c28aaSamw * using the next expected sequence number and compares
305da6c28aaSamw * it to the given signature.
306da6c28aaSamw *
307da6c28aaSamw * Note it does not check the signature for secondary transactions
308da6c28aaSamw * as their sequence number is the same as the original request.
309da6c28aaSamw *
310da6c28aaSamw * Return 0 if the signature verifies, otherwise, returns -1;
311da6c28aaSamw *
312da6c28aaSamw */
313da6c28aaSamw int
smb_sign_check_request(smb_request_t * sr)314faa1795aSjb150015 smb_sign_check_request(smb_request_t *sr)
315da6c28aaSamw {
316faa1795aSjb150015 struct mbuf_chain command = sr->command;
317da6c28aaSamw unsigned char mac_sig[SMB_SIG_SIZE];
318faa1795aSjb150015 struct smb_sign *sign = &sr->session->signing;
319da6c28aaSamw int rtn = 0;
320c8ec8eeaSjose borrego boolean_t found = B_TRUE;
321148c5f43SAlan Wright
322da6c28aaSamw /*
323da6c28aaSamw * Don't check secondary transactions - we dont know the sequence
324da6c28aaSamw * number.
325da6c28aaSamw */
326faa1795aSjb150015 if (sr->smb_com == SMB_COM_TRANSACTION_SECONDARY ||
327faa1795aSjb150015 sr->smb_com == SMB_COM_TRANSACTION2_SECONDARY ||
328faa1795aSjb150015 sr->smb_com == SMB_COM_NT_TRANSACT_SECONDARY)
329da6c28aaSamw return (0);
330da6c28aaSamw
331da6c28aaSamw /* Reset the offset to begining of header */
332faa1795aSjb150015 command.chain_offset = sr->orig_request_hdr;
333da6c28aaSamw
334da6c28aaSamw /* calculate mac signature */
335148c5f43SAlan Wright if (smb_sign_calc(&command, sign, sr->sr_seqnum, mac_sig) != 0)
336da6c28aaSamw return (-1);
337da6c28aaSamw
338da6c28aaSamw /* compare the signatures */
339faa1795aSjb150015 if (memcmp(mac_sig, sr->smb_sig, SMB_SIG_SIZE) != 0) {
340c8ec8eeaSjose borrego DTRACE_PROBE2(smb__signing__req, smb_request_t, sr,
341c8ec8eeaSjose borrego smb_sign_t *, sr->smb_sig);
342148c5f43SAlan Wright cmn_err(CE_NOTE, "smb_sign_check_request: bad signature");
343c8ec8eeaSjose borrego /*
344c8ec8eeaSjose borrego * check nearby sequence numbers in debug mode
345c8ec8eeaSjose borrego */
346*b819cea2SGordon Ross #ifdef DEBUG
347*b819cea2SGordon Ross if (smb_sign_debug)
348*b819cea2SGordon Ross smb_sign_find_seqnum(sr->sr_seqnum, sign,
349*b819cea2SGordon Ross &command, mac_sig, sr->smb_sig, &found);
350*b819cea2SGordon Ross else
351*b819cea2SGordon Ross #endif
352*b819cea2SGordon Ross found = B_FALSE;
353*b819cea2SGordon Ross
354c8ec8eeaSjose borrego if (found == B_FALSE)
355da6c28aaSamw rtn = -1;
356da6c28aaSamw }
357da6c28aaSamw return (rtn);
358da6c28aaSamw }
359da6c28aaSamw
360da6c28aaSamw /*
361da6c28aaSamw * smb_sign_check_secondary
362da6c28aaSamw *
363da6c28aaSamw * Calculates MAC signature for the secondary transaction mbuf chain
364da6c28aaSamw * and compares it to the given signature.
365da6c28aaSamw * Return 0 if the signature verifies, otherwise, returns -1;
366da6c28aaSamw *
367da6c28aaSamw */
368da6c28aaSamw int
smb_sign_check_secondary(smb_request_t * sr,unsigned int reply_seqnum)369faa1795aSjb150015 smb_sign_check_secondary(smb_request_t *sr, unsigned int reply_seqnum)
370da6c28aaSamw {
371faa1795aSjb150015 struct mbuf_chain command = sr->command;
372da6c28aaSamw unsigned char mac_sig[SMB_SIG_SIZE];
373faa1795aSjb150015 struct smb_sign *sign = &sr->session->signing;
374da6c28aaSamw int rtn = 0;
375da6c28aaSamw
376da6c28aaSamw /* Reset the offset to begining of header */
377faa1795aSjb150015 command.chain_offset = sr->orig_request_hdr;
378da6c28aaSamw
379da6c28aaSamw /* calculate mac signature */
380da6c28aaSamw if (smb_sign_calc(&command, sign, reply_seqnum - 1,
381da6c28aaSamw mac_sig) != 0)
382da6c28aaSamw return (-1);
383da6c28aaSamw
384da6c28aaSamw
385da6c28aaSamw /* compare the signatures */
386faa1795aSjb150015 if (memcmp(mac_sig, sr->smb_sig, SMB_SIG_SIZE) != 0) {
387da6c28aaSamw cmn_err(CE_WARN, "SmbSignCheckSecond: bad signature");
388da6c28aaSamw rtn = -1;
389da6c28aaSamw }
390da6c28aaSamw /* Save the reply sequence number */
391faa1795aSjb150015 sr->reply_seqnum = reply_seqnum;
392da6c28aaSamw
393da6c28aaSamw return (rtn);
394da6c28aaSamw }
395da6c28aaSamw
396da6c28aaSamw /*
397da6c28aaSamw * smb_sign_reply
398da6c28aaSamw *
399da6c28aaSamw * Calculates MAC signature for the given mbuf chain,
400da6c28aaSamw * and write it to the signature field in the mbuf.
401da6c28aaSamw *
402da6c28aaSamw */
403da6c28aaSamw void
smb_sign_reply(smb_request_t * sr,struct mbuf_chain * reply)404faa1795aSjb150015 smb_sign_reply(smb_request_t *sr, struct mbuf_chain *reply)
405da6c28aaSamw {
406da6c28aaSamw struct mbuf_chain resp;
407faa1795aSjb150015 struct smb_sign *sign = &sr->session->signing;
408da6c28aaSamw unsigned char signature[SMB_SIG_SIZE];
409da6c28aaSamw
410da6c28aaSamw if (reply)
411da6c28aaSamw resp = *reply;
412da6c28aaSamw else
413faa1795aSjb150015 resp = sr->reply;
414da6c28aaSamw
415da6c28aaSamw /* Reset offset to start of reply */
416da6c28aaSamw resp.chain_offset = 0;
417da6c28aaSamw
418da6c28aaSamw /*
419da6c28aaSamw * Calculate MAC signature
420da6c28aaSamw */
421148c5f43SAlan Wright if (smb_sign_calc(&resp, sign, sr->reply_seqnum, signature) != 0) {
422148c5f43SAlan Wright cmn_err(CE_WARN, "smb_sign_reply: error in smb_sign_calc");
423da6c28aaSamw return;
424148c5f43SAlan Wright }
425da6c28aaSamw
426da6c28aaSamw /*
427da6c28aaSamw * Put signature in the response
428da6c28aaSamw */
429*b819cea2SGordon Ross (void) smb_mbc_poke(&resp, SMB_SIG_OFFS, "#c",
430*b819cea2SGordon Ross SMB_SIG_SIZE, signature);
431da6c28aaSamw }
432