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.
23b819cea2SGordon 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>
43b819cea2SGordon Ross #include <smbsrv/smb_signing.h>
44b819cea2SGordon Ross #include <sys/isa_defs.h>
45b819cea2SGordon Ross #include <sys/byteorder.h>
46da6c28aaSamw
47da6c28aaSamw #define SMB_SIG_SIZE 8
48da6c28aaSamw #define SMB_SIG_OFFS 14
49b819cea2SGordon Ross #define SMB_HDRLEN 32
50b819cea2SGordon Ross
51b819cea2SGordon Ross #ifdef _LITTLE_ENDIAN
52b819cea2SGordon Ross #define htolel(x) ((uint32_t)(x))
53b819cea2SGordon Ross #else
54b819cea2SGordon Ross #define htolel(x) BSWAP_32(x)
55b819cea2SGordon Ross #endif
56da6c28aaSamw
57*12b65585SGordon Ross static int
58*12b65585SGordon Ross smb_sign_calc(smb_request_t *sr, struct mbuf_chain *mbc,
59*12b65585SGordon Ross uint32_t seqnum, unsigned char *sig);
60c8ec8eeaSjose borrego
61c8ec8eeaSjose borrego #ifdef DEBUG
62*12b65585SGordon Ross uint32_t smb_sign_debug_search = 10;
63c8ec8eeaSjose borrego
64*12b65585SGordon Ross /*
65*12b65585SGordon Ross * Debug code to search +/- for the correct sequence number.
66*12b65585SGordon Ross * If found, correct sign->seqnum and return 0, else return -1
67*12b65585SGordon Ross */
68*12b65585SGordon Ross static int
smb_sign_find_seqnum(smb_request_t * sr,struct mbuf_chain * mbc,unsigned char * mac_sig,unsigned char * sr_sig)69*12b65585SGordon Ross smb_sign_find_seqnum(
70*12b65585SGordon Ross smb_request_t *sr,
71*12b65585SGordon Ross struct mbuf_chain *mbc,
72*12b65585SGordon Ross unsigned char *mac_sig,
73*12b65585SGordon Ross unsigned char *sr_sig)
74*12b65585SGordon Ross {
75*12b65585SGordon Ross struct smb_sign *sign = &sr->session->signing;
76*12b65585SGordon Ross uint32_t i, t;
77*12b65585SGordon Ross
78*12b65585SGordon Ross for (i = 1; i < smb_sign_debug_search; i++) {
79*12b65585SGordon Ross t = sr->sr_seqnum + i;
80*12b65585SGordon Ross (void) smb_sign_calc(sr, mbc, t, mac_sig);
81c8ec8eeaSjose borrego if (memcmp(mac_sig, sr_sig, SMB_SIG_SIZE) == 0) {
82*12b65585SGordon Ross goto found;
83c8ec8eeaSjose borrego }
84*12b65585SGordon Ross t = sr->sr_seqnum - i;
85*12b65585SGordon Ross (void) smb_sign_calc(sr, mbc, t, mac_sig);
86*12b65585SGordon Ross if (memcmp(mac_sig, sr_sig, SMB_SIG_SIZE) == 0) {
87*12b65585SGordon Ross goto found;
88c8ec8eeaSjose borrego }
89*12b65585SGordon Ross }
90*12b65585SGordon Ross cmn_err(CE_WARN, "smb_sign_find_seqnum: failed after %d", i);
91*12b65585SGordon Ross return (-1);
92*12b65585SGordon Ross
93*12b65585SGordon Ross found:
94*12b65585SGordon Ross cmn_err(CE_WARN, "smb_sign_find_seqnum: found! %d <- %d",
95*12b65585SGordon Ross sign->seqnum, t);
96*12b65585SGordon Ross sign->seqnum = t;
97*12b65585SGordon Ross return (0);
98c8ec8eeaSjose borrego }
99c8ec8eeaSjose borrego #endif
100148c5f43SAlan Wright
1018622ec45SGordon Ross /*
102b819cea2SGordon Ross * Called during session destroy.
1038622ec45SGordon Ross */
104b819cea2SGordon Ross static void
smb_sign_fini(smb_session_t * s)105b819cea2SGordon Ross smb_sign_fini(smb_session_t *s)
106b819cea2SGordon Ross {
107b819cea2SGordon Ross smb_sign_mech_t *mech;
108b819cea2SGordon Ross
109*12b65585SGordon Ross if ((mech = s->sign_mech) != NULL) {
110b819cea2SGordon Ross kmem_free(mech, sizeof (*mech));
111*12b65585SGordon Ross s->sign_mech = NULL;
1128622ec45SGordon Ross }
1138622ec45SGordon Ross }
1148622ec45SGordon Ross
115da6c28aaSamw /*
116b819cea2SGordon Ross * smb_sign_begin
117da6c28aaSamw *
118da6c28aaSamw * Intializes MAC key based on the user session key and
119da6c28aaSamw * NTLM response and store it in the signing structure.
120b819cea2SGordon Ross * This is what begins SMB signing.
121da6c28aaSamw */
122b819cea2SGordon Ross int
smb_sign_begin(smb_request_t * sr,smb_token_t * token)123b819cea2SGordon Ross smb_sign_begin(smb_request_t *sr, smb_token_t *token)
124da6c28aaSamw {
125b819cea2SGordon Ross smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup;
126b819cea2SGordon Ross smb_session_t *session = sr->session;
127b819cea2SGordon Ross struct smb_sign *sign = &session->signing;
128b819cea2SGordon Ross smb_sign_mech_t *mech;
129b819cea2SGordon Ross int rc;
130da6c28aaSamw
131da6c28aaSamw /*
132*12b65585SGordon Ross * We should normally have a session key here because
133*12b65585SGordon Ross * our caller filters out Anonymous and Guest logons.
134*12b65585SGordon Ross * However, buggy clients could get us here without a
135*12b65585SGordon Ross * session key, in which case: just don't sign.
136*12b65585SGordon Ross */
137*12b65585SGordon Ross if (token->tkn_ssnkey.val == NULL || token->tkn_ssnkey.len == 0)
138*12b65585SGordon Ross return (0);
139*12b65585SGordon Ross
140*12b65585SGordon Ross /*
141b819cea2SGordon Ross * Session-level initialization (once per session)
142da6c28aaSamw */
143b819cea2SGordon Ross smb_rwx_rwenter(&session->s_lock, RW_WRITER);
144b819cea2SGordon Ross
145b819cea2SGordon Ross /*
146b819cea2SGordon Ross * Signing may already have been setup by a prior logon,
147b819cea2SGordon Ross * in which case we're done here.
148b819cea2SGordon Ross */
149b819cea2SGordon Ross if (sign->mackey != NULL) {
150b819cea2SGordon Ross smb_rwx_rwexit(&session->s_lock);
151b819cea2SGordon Ross return (0);
152da6c28aaSamw }
153da6c28aaSamw
154b819cea2SGordon Ross /*
155b819cea2SGordon Ross * Get the mech handle
156b819cea2SGordon Ross */
157*12b65585SGordon Ross if (session->sign_mech == NULL) {
158b819cea2SGordon Ross mech = kmem_zalloc(sizeof (*mech), KM_SLEEP);
159b819cea2SGordon Ross rc = smb_md5_getmech(mech);
160b819cea2SGordon Ross if (rc != 0) {
161b819cea2SGordon Ross kmem_free(mech, sizeof (*mech));
162b819cea2SGordon Ross smb_rwx_rwexit(&session->s_lock);
163b819cea2SGordon Ross return (rc);
164b819cea2SGordon Ross }
165*12b65585SGordon Ross session->sign_mech = mech;
166b819cea2SGordon Ross session->sign_fini = smb_sign_fini;
167b819cea2SGordon Ross }
168da6c28aaSamw
169b819cea2SGordon Ross /*
170b819cea2SGordon Ross * Compute and store the signing (MAC) key.
171b819cea2SGordon Ross *
172b819cea2SGordon Ross * With extended security, the MAC key is the same as the
173*12b65585SGordon Ross * session key (and we'll have sinfo->ssi_ntpwlen == 0).
174b819cea2SGordon Ross * With non-extended security, it's the concatenation of
175b819cea2SGordon Ross * the session key and the "NT response" we received.
176b819cea2SGordon Ross */
177*12b65585SGordon Ross sign->mackey_len = token->tkn_ssnkey.len + sinfo->ssi_ntpwlen;
178b819cea2SGordon Ross sign->mackey = kmem_alloc(sign->mackey_len, KM_SLEEP);
179*12b65585SGordon Ross bcopy(token->tkn_ssnkey.val, sign->mackey, token->tkn_ssnkey.len);
180*12b65585SGordon Ross if (sinfo->ssi_ntpwlen > 0) {
181*12b65585SGordon Ross bcopy(sinfo->ssi_ntpwd, sign->mackey + token->tkn_ssnkey.len,
182*12b65585SGordon Ross sinfo->ssi_ntpwlen);
183b819cea2SGordon Ross }
184da6c28aaSamw
185b819cea2SGordon Ross session->signing.seqnum = 0;
186148c5f43SAlan Wright sr->sr_seqnum = 2;
187faa1795aSjb150015 sr->reply_seqnum = 1;
188b819cea2SGordon Ross sign->flags = 0;
189b819cea2SGordon Ross
190b819cea2SGordon Ross if (session->secmode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
191b819cea2SGordon Ross sign->flags |= SMB_SIGNING_ENABLED;
192b819cea2SGordon Ross if (session->secmode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED)
193b819cea2SGordon Ross sign->flags |= SMB_SIGNING_CHECK;
194b819cea2SGordon Ross }
195b819cea2SGordon Ross
196b819cea2SGordon Ross smb_rwx_rwexit(&session->s_lock);
197b819cea2SGordon Ross return (0);
198da6c28aaSamw }
199da6c28aaSamw
200da6c28aaSamw /*
201da6c28aaSamw * smb_sign_calc
202da6c28aaSamw *
203da6c28aaSamw * Calculates MAC signature for the given buffer and returns
204da6c28aaSamw * it in the mac_sign parameter.
205da6c28aaSamw *
206da6c28aaSamw * The sequence number is placed in the first four bytes of the signature
207da6c28aaSamw * field of the signature and the other 4 bytes are zeroed.
208da6c28aaSamw * The signature is the first 8 bytes of the MD5 result of the
209da6c28aaSamw * concatenated MAC key and the SMB message.
210da6c28aaSamw *
211da6c28aaSamw * MACsig = head(MD5(concat(MACKey, SMBMsg)), 8)
212da6c28aaSamw *
213da6c28aaSamw * where
214da6c28aaSamw *
215da6c28aaSamw * MACKey = concat( UserSessionKey, NTLMResp )
216da6c28aaSamw *
217da6c28aaSamw * and
218da6c28aaSamw *
219da6c28aaSamw * SMBMsg is the SMB message containing the sequence number.
220da6c28aaSamw *
221b819cea2SGordon Ross * Return 0 if success
222da6c28aaSamw *
223da6c28aaSamw */
224*12b65585SGordon Ross static int
smb_sign_calc(smb_request_t * sr,struct mbuf_chain * mbc,uint32_t seqnum,unsigned char * mac_sign)225*12b65585SGordon Ross smb_sign_calc(smb_request_t *sr, struct mbuf_chain *mbc,
226*12b65585SGordon Ross uint32_t seqnum, unsigned char *mac_sign)
227da6c28aaSamw {
228*12b65585SGordon Ross smb_session_t *s = sr->session;
229*12b65585SGordon Ross struct smb_sign *sign = &s->signing;
230b819cea2SGordon Ross smb_sign_ctx_t ctx = 0;
231b819cea2SGordon Ross uchar_t digest[MD5_DIGEST_LENGTH];
232b819cea2SGordon Ross uchar_t *hdrp;
233da6c28aaSamw struct mbuf *mbuf = mbc->chain;
234da6c28aaSamw int offset = mbc->chain_offset;
235da6c28aaSamw int size;
236b819cea2SGordon Ross int rc;
237da6c28aaSamw
238da6c28aaSamw /*
239b819cea2SGordon Ross * This union is a little bit of trickery to:
240b819cea2SGordon Ross * (1) get the sequence number int aligned, and
241b819cea2SGordon Ross * (2) reduce the number of digest calls, at the
242b819cea2SGordon Ross * cost of a copying 32 bytes instead of 8.
243b819cea2SGordon Ross * Both sides of this union are 2+32 bytes.
244da6c28aaSamw */
245b819cea2SGordon Ross union {
246b819cea2SGordon Ross struct {
247b819cea2SGordon Ross uint8_t skip[2]; /* not used - just alignment */
248b819cea2SGordon Ross uint8_t raw[SMB_HDRLEN]; /* header length (32) */
249b819cea2SGordon Ross } r;
250b819cea2SGordon Ross struct {
251b819cea2SGordon Ross uint8_t skip[2]; /* not used - just alignment */
252b819cea2SGordon Ross uint8_t hdr[SMB_SIG_OFFS]; /* sig. offset (14) */
253b819cea2SGordon Ross uint32_t sig[2]; /* MAC signature, aligned! */
254b819cea2SGordon Ross uint16_t ids[5]; /* pad, Tid, Pid, Uid, Mid */
255b819cea2SGordon Ross } s;
256b819cea2SGordon Ross } smbhdr;
257da6c28aaSamw
258*12b65585SGordon Ross if (s->sign_mech == NULL || sign->mackey == NULL)
259da6c28aaSamw return (-1);
260da6c28aaSamw
261*12b65585SGordon Ross if ((rc = smb_md5_init(&ctx, s->sign_mech)) != 0)
262b819cea2SGordon Ross return (rc);
263b819cea2SGordon Ross
264b819cea2SGordon Ross /* Digest the MAC Key */
265b819cea2SGordon Ross rc = smb_md5_update(ctx, sign->mackey, sign->mackey_len);
266b819cea2SGordon Ross if (rc != 0)
267b819cea2SGordon Ross return (rc);
268b819cea2SGordon Ross
269b819cea2SGordon Ross /*
270b819cea2SGordon Ross * Make an aligned copy of the SMB header,
271b819cea2SGordon Ross * fill in the sequence number, and digest.
272b819cea2SGordon Ross */
273b819cea2SGordon Ross hdrp = (unsigned char *)&smbhdr.r.raw;
274b819cea2SGordon Ross size = SMB_HDRLEN;
275b819cea2SGordon Ross if (smb_mbc_peek(mbc, offset, "#c", size, hdrp) != 0)
276b819cea2SGordon Ross return (-1);
277b819cea2SGordon Ross smbhdr.s.sig[0] = htolel(seqnum);
278b819cea2SGordon Ross smbhdr.s.sig[1] = 0;
279b819cea2SGordon Ross
280b819cea2SGordon Ross rc = smb_md5_update(ctx, &smbhdr.r.raw, size);
281b819cea2SGordon Ross if (rc != 0)
282b819cea2SGordon Ross return (rc);
283b819cea2SGordon Ross
284b819cea2SGordon Ross /*
285b819cea2SGordon Ross * Digest the rest of the SMB packet, starting at the data
286b819cea2SGordon Ross * just after the SMB header.
287b819cea2SGordon Ross */
288b819cea2SGordon Ross offset += size;
289b819cea2SGordon Ross while (mbuf != NULL && (offset >= mbuf->m_len)) {
290b819cea2SGordon Ross offset -= mbuf->m_len;
291b819cea2SGordon Ross mbuf = mbuf->m_next;
292b819cea2SGordon Ross }
293b819cea2SGordon Ross if (mbuf != NULL && (size = (mbuf->m_len - offset)) > 0) {
294b819cea2SGordon Ross rc = smb_md5_update(ctx, &mbuf->m_data[offset], size);
295b819cea2SGordon Ross if (rc != 0)
296b819cea2SGordon Ross return (rc);
297b819cea2SGordon Ross offset = 0;
298b819cea2SGordon Ross mbuf = mbuf->m_next;
299b819cea2SGordon Ross }
300b819cea2SGordon Ross while (mbuf != NULL) {
301b819cea2SGordon Ross rc = smb_md5_update(ctx, mbuf->m_data, mbuf->m_len);
302b819cea2SGordon Ross if (rc != 0)
303b819cea2SGordon Ross return (rc);
304b819cea2SGordon Ross mbuf = mbuf->m_next;
305b819cea2SGordon Ross }
306b819cea2SGordon Ross rc = smb_md5_final(ctx, digest);
307b819cea2SGordon Ross if (rc == 0)
308b819cea2SGordon Ross bcopy(digest, mac_sign, SMB_SIG_SIZE);
309b819cea2SGordon Ross
310b819cea2SGordon Ross return (rc);
311da6c28aaSamw }
312da6c28aaSamw
313da6c28aaSamw
314da6c28aaSamw /*
315da6c28aaSamw * smb_sign_check_request
316da6c28aaSamw *
317da6c28aaSamw * Calculates MAC signature for the request mbuf chain
318da6c28aaSamw * using the next expected sequence number and compares
319da6c28aaSamw * it to the given signature.
320da6c28aaSamw *
321da6c28aaSamw * Note it does not check the signature for secondary transactions
322da6c28aaSamw * as their sequence number is the same as the original request.
323da6c28aaSamw *
324da6c28aaSamw * Return 0 if the signature verifies, otherwise, returns -1;
325da6c28aaSamw *
326da6c28aaSamw */
327da6c28aaSamw int
smb_sign_check_request(smb_request_t * sr)328faa1795aSjb150015 smb_sign_check_request(smb_request_t *sr)
329da6c28aaSamw {
330*12b65585SGordon Ross struct mbuf_chain mbc = sr->command;
331da6c28aaSamw unsigned char mac_sig[SMB_SIG_SIZE];
332148c5f43SAlan Wright
333da6c28aaSamw /*
334da6c28aaSamw * Don't check secondary transactions - we dont know the sequence
335da6c28aaSamw * number.
336da6c28aaSamw */
337faa1795aSjb150015 if (sr->smb_com == SMB_COM_TRANSACTION_SECONDARY ||
338faa1795aSjb150015 sr->smb_com == SMB_COM_TRANSACTION2_SECONDARY ||
339faa1795aSjb150015 sr->smb_com == SMB_COM_NT_TRANSACT_SECONDARY)
340da6c28aaSamw return (0);
341da6c28aaSamw
342da6c28aaSamw /* Reset the offset to begining of header */
343*12b65585SGordon Ross mbc.chain_offset = sr->orig_request_hdr;
344da6c28aaSamw
345da6c28aaSamw /* calculate mac signature */
346*12b65585SGordon Ross if (smb_sign_calc(sr, &mbc, sr->sr_seqnum, mac_sig) != 0)
347da6c28aaSamw return (-1);
348da6c28aaSamw
349da6c28aaSamw /* compare the signatures */
350*12b65585SGordon Ross if (memcmp(mac_sig, sr->smb_sig, SMB_SIG_SIZE) == 0) {
351*12b65585SGordon Ross /* They match! OK, we're done. */
352*12b65585SGordon Ross return (0);
353*12b65585SGordon Ross }
354*12b65585SGordon Ross
355*12b65585SGordon Ross DTRACE_PROBE2(smb__signature__mismatch, smb_request_t, sr,
356*12b65585SGordon Ross unsigned char *, mac_sig);
357148c5f43SAlan Wright cmn_err(CE_NOTE, "smb_sign_check_request: bad signature");
358*12b65585SGordon Ross
359c8ec8eeaSjose borrego /*
360c8ec8eeaSjose borrego * check nearby sequence numbers in debug mode
361c8ec8eeaSjose borrego */
362b819cea2SGordon Ross #ifdef DEBUG
363*12b65585SGordon Ross if (smb_sign_debug) {
364*12b65585SGordon Ross return (smb_sign_find_seqnum(sr, &mbc, mac_sig, sr->smb_sig));
365da6c28aaSamw }
366*12b65585SGordon Ross #endif
367*12b65585SGordon Ross return (-1);
368da6c28aaSamw }
369da6c28aaSamw
370da6c28aaSamw /*
371da6c28aaSamw * smb_sign_check_secondary
372da6c28aaSamw *
373da6c28aaSamw * Calculates MAC signature for the secondary transaction mbuf chain
374da6c28aaSamw * and compares it to the given signature.
375da6c28aaSamw * Return 0 if the signature verifies, otherwise, returns -1;
376da6c28aaSamw *
377da6c28aaSamw */
378da6c28aaSamw int
smb_sign_check_secondary(smb_request_t * sr,unsigned int reply_seqnum)379faa1795aSjb150015 smb_sign_check_secondary(smb_request_t *sr, unsigned int reply_seqnum)
380da6c28aaSamw {
381*12b65585SGordon Ross struct mbuf_chain mbc = sr->command;
382da6c28aaSamw unsigned char mac_sig[SMB_SIG_SIZE];
383da6c28aaSamw int rtn = 0;
384da6c28aaSamw
385da6c28aaSamw /* Reset the offset to begining of header */
386*12b65585SGordon Ross mbc.chain_offset = sr->orig_request_hdr;
387da6c28aaSamw
388da6c28aaSamw /* calculate mac signature */
389*12b65585SGordon Ross if (smb_sign_calc(sr, &mbc, reply_seqnum - 1, mac_sig) != 0)
390da6c28aaSamw return (-1);
391da6c28aaSamw
392da6c28aaSamw
393da6c28aaSamw /* compare the signatures */
394faa1795aSjb150015 if (memcmp(mac_sig, sr->smb_sig, SMB_SIG_SIZE) != 0) {
395da6c28aaSamw cmn_err(CE_WARN, "SmbSignCheckSecond: bad signature");
396da6c28aaSamw rtn = -1;
397da6c28aaSamw }
398da6c28aaSamw /* Save the reply sequence number */
399faa1795aSjb150015 sr->reply_seqnum = reply_seqnum;
400da6c28aaSamw
401da6c28aaSamw return (rtn);
402da6c28aaSamw }
403da6c28aaSamw
404da6c28aaSamw /*
405da6c28aaSamw * smb_sign_reply
406da6c28aaSamw *
407da6c28aaSamw * Calculates MAC signature for the given mbuf chain,
408da6c28aaSamw * and write it to the signature field in the mbuf.
409da6c28aaSamw *
410da6c28aaSamw */
411da6c28aaSamw void
smb_sign_reply(smb_request_t * sr,struct mbuf_chain * reply)412faa1795aSjb150015 smb_sign_reply(smb_request_t *sr, struct mbuf_chain *reply)
413da6c28aaSamw {
414*12b65585SGordon Ross struct mbuf_chain mbc;
415*12b65585SGordon Ross unsigned char mac[SMB_SIG_SIZE];
416da6c28aaSamw
417da6c28aaSamw if (reply)
418*12b65585SGordon Ross mbc = *reply;
419da6c28aaSamw else
420*12b65585SGordon Ross mbc = sr->reply;
421da6c28aaSamw
422da6c28aaSamw /* Reset offset to start of reply */
423*12b65585SGordon Ross mbc.chain_offset = 0;
424da6c28aaSamw
425da6c28aaSamw /*
426da6c28aaSamw * Calculate MAC signature
427da6c28aaSamw */
428*12b65585SGordon Ross if (smb_sign_calc(sr, &mbc, sr->reply_seqnum, mac) != 0) {
429148c5f43SAlan Wright cmn_err(CE_WARN, "smb_sign_reply: error in smb_sign_calc");
430da6c28aaSamw return;
431148c5f43SAlan Wright }
432da6c28aaSamw
433da6c28aaSamw /*
434da6c28aaSamw * Put signature in the response
435da6c28aaSamw */
436*12b65585SGordon Ross (void) smb_mbc_poke(&mbc, SMB_SIG_OFFS, "#c",
437*12b65585SGordon Ross SMB_SIG_SIZE, mac);
438da6c28aaSamw }
439