source: vendor/current/source3/smbd/signing.c

Last change on this file was 988, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.3

File size: 7.5 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 SMB Signing Code
4 Copyright (C) Jeremy Allison 2003.
5 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003
6 Copyright (C) Stefan Metzmacher 2009
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20*/
21
22#include "includes.h"
23#include "smbd/smbd.h"
24#include "smbd/globals.h"
25#include "../libcli/smb/smb_signing.h"
26#include "lib/param/param.h"
27
28/***********************************************************
29 Called to validate an incoming packet from the client.
30************************************************************/
31
32bool srv_check_sign_mac(struct smbXsrv_connection *conn,
33 const char *inbuf, uint32_t *seqnum,
34 bool trusted_channel)
35{
36 const uint8_t *inhdr;
37 size_t len;
38
39 /* Check if it's a non-session message. */
40 if(CVAL(inbuf,0)) {
41 return true;
42 }
43
44 len = smb_len(inbuf);
45 inhdr = (const uint8_t *)inbuf + NBT_HDR_SIZE;
46
47 if (trusted_channel) {
48 NTSTATUS status;
49
50 if (len < (HDR_SS_FIELD + 8)) {
51 DEBUG(1,("smb_signing_check_pdu: Can't check signature "
52 "on short packet! smb_len = %u\n",
53 (unsigned)len));
54 return false;
55 }
56
57 status = NT_STATUS(IVAL(inhdr, HDR_SS_FIELD + 4));
58 if (!NT_STATUS_IS_OK(status)) {
59 DEBUG(1,("smb_signing_check_pdu: trusted channel passed %s\n",
60 nt_errstr(status)));
61 return false;
62 }
63
64 *seqnum = IVAL(inhdr, HDR_SS_FIELD);
65 return true;
66 }
67
68 *seqnum = smb_signing_next_seqnum(conn->smb1.signing_state, false);
69 return smb_signing_check_pdu(conn->smb1.signing_state,
70 inhdr, len,
71 *seqnum);
72}
73
74/***********************************************************
75 Called to sign an outgoing packet to the client.
76************************************************************/
77
78void srv_calculate_sign_mac(struct smbXsrv_connection *conn,
79 char *outbuf, uint32_t seqnum)
80{
81 uint8_t *outhdr;
82 size_t len;
83
84 /* Check if it's a non-session message. */
85 if(CVAL(outbuf,0)) {
86 return;
87 }
88
89 len = smb_len(outbuf);
90 outhdr = (uint8_t *)outbuf + NBT_HDR_SIZE;
91
92 smb_signing_sign_pdu(conn->smb1.signing_state, outhdr, len, seqnum);
93}
94
95
96/***********************************************************
97 Called to indicate a oneway request
98************************************************************/
99void srv_cancel_sign_response(struct smbXsrv_connection *conn)
100{
101 smb_signing_cancel_reply(conn->smb1.signing_state, true);
102}
103
104struct smbd_shm_signing {
105 size_t shm_size;
106 uint8_t *shm_pointer;
107
108 /* we know the signing engine will only allocate 2 chunks */
109 uint8_t *ptr1;
110 size_t len1;
111 uint8_t *ptr2;
112 size_t len2;
113};
114
115static int smbd_shm_signing_destructor(struct smbd_shm_signing *s)
116{
117 anonymous_shared_free(s->shm_pointer);
118 return 0;
119}
120
121static void *smbd_shm_signing_alloc(TALLOC_CTX *mem_ctx, size_t len)
122{
123 struct smbd_shm_signing *s = talloc_get_type_abort(mem_ctx,
124 struct smbd_shm_signing);
125
126 if (s->ptr1 == NULL) {
127 s->len1 = len;
128 if (len % 8) {
129 s->len1 += (8 - (len % 8));
130 }
131 if (s->len1 > s->shm_size) {
132 s->len1 = 0;
133 errno = ENOMEM;
134 return NULL;
135 }
136 s->ptr1 = s->shm_pointer;
137 return s->ptr1;
138 }
139
140 if (s->ptr2 == NULL) {
141 s->len2 = len;
142 if (s->len2 > (s->shm_size - s->len1)) {
143 s->len2 = 0;
144 errno = ENOMEM;
145 return NULL;
146 }
147 s->ptr2 = s->shm_pointer + s->len1;
148 return s->ptr2;
149 }
150
151 errno = ENOMEM;
152 return NULL;
153}
154
155static void smbd_shm_signing_free(TALLOC_CTX *mem_ctx, void *ptr)
156{
157 struct smbd_shm_signing *s = talloc_get_type_abort(mem_ctx,
158 struct smbd_shm_signing);
159
160 if (s->ptr2 == ptr) {
161 s->ptr2 = NULL;
162 s->len2 = 0;
163 }
164}
165
166/***********************************************************
167 Called by server negprot when signing has been negotiated.
168************************************************************/
169
170bool srv_init_signing(struct smbXsrv_connection *conn)
171{
172 bool allowed = true;
173 bool desired;
174 bool mandatory = false;
175
176 struct loadparm_context *lp_ctx = loadparm_init_s3(conn, loadparm_s3_helpers());
177 if (lp_ctx == NULL) {
178 DEBUG(10, ("loadparm_init_s3 failed\n"));
179 return false;
180 }
181
182 /*
183 * if the client and server allow signing,
184 * we desire to use it.
185 *
186 * This matches Windows behavior and is needed
187 * because not every client that requires signing
188 * sends FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED.
189 *
190 * Note that we'll always allow signing if the client
191 * does send FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED.
192 */
193
194 desired = lpcfg_server_signing_allowed(lp_ctx, &mandatory);
195 talloc_unlink(conn, lp_ctx);
196
197 if (lp_async_smb_echo_handler()) {
198 struct smbd_shm_signing *s;
199
200 /* setup the signing state in shared memory */
201 s = talloc_zero(conn, struct smbd_shm_signing);
202 if (s == NULL) {
203 return false;
204 }
205 s->shm_size = 4096;
206 s->shm_pointer =
207 (uint8_t *)anonymous_shared_allocate(s->shm_size);
208 if (s->shm_pointer == NULL) {
209 talloc_free(s);
210 return false;
211 }
212 talloc_set_destructor(s, smbd_shm_signing_destructor);
213 conn->smb1.signing_state = smb_signing_init_ex(s,
214 allowed, desired, mandatory,
215 smbd_shm_signing_alloc,
216 smbd_shm_signing_free);
217 if (!conn->smb1.signing_state) {
218 return false;
219 }
220 return true;
221 }
222
223 conn->smb1.signing_state = smb_signing_init(conn,
224 allowed, desired, mandatory);
225 if (!conn->smb1.signing_state) {
226 return false;
227 }
228
229 return true;
230}
231
232void srv_set_signing_negotiated(struct smbXsrv_connection *conn,
233 bool allowed, bool mandatory)
234{
235 smb_signing_set_negotiated(conn->smb1.signing_state,
236 allowed, mandatory);
237}
238
239/***********************************************************
240 Returns whether signing is active. We can't use sendfile or raw
241 reads/writes if it is.
242************************************************************/
243
244bool srv_is_signing_active(struct smbXsrv_connection *conn)
245{
246 return smb_signing_is_active(conn->smb1.signing_state);
247}
248
249
250/***********************************************************
251 Returns whether signing is negotiated. We can't use it unless it was
252 in the negprot.
253************************************************************/
254
255bool srv_is_signing_negotiated(struct smbXsrv_connection *conn)
256{
257 return smb_signing_is_negotiated(conn->smb1.signing_state);
258}
259
260/***********************************************************
261 Turn on signing from this packet onwards.
262************************************************************/
263
264void srv_set_signing(struct smbXsrv_connection *conn,
265 const DATA_BLOB user_session_key,
266 const DATA_BLOB response)
267{
268 bool negotiated;
269 bool mandatory;
270
271 if (!user_session_key.length)
272 return;
273
274 negotiated = smb_signing_is_negotiated(conn->smb1.signing_state);
275 mandatory = smb_signing_is_mandatory(conn->smb1.signing_state);
276
277 if (!negotiated && !mandatory) {
278 DEBUG(5,("srv_set_signing: signing negotiated = %u, "
279 "mandatory_signing = %u. Not allowing smb signing.\n",
280 negotiated, mandatory));
281 return;
282 }
283
284 if (!smb_signing_activate(conn->smb1.signing_state,
285 user_session_key, response)) {
286 return;
287 }
288
289 DEBUG(3,("srv_set_signing: turning on SMB signing: "
290 "signing negotiated = %u, mandatory_signing = %u.\n",
291 negotiated, mandatory));
292}
293
Note: See TracBrowser for help on using the repository browser.