source: trunk/server/source3/smbd/signing.c@ 745

Last change on this file since 745 was 745, checked in by Silvan Scherrer, 13 years ago

Samba Server: updated trunk to 3.6.0

File size: 7.1 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 "smb_signing.h"
26
27/***********************************************************
28 Called to validate an incoming packet from the client.
29************************************************************/
30
31bool srv_check_sign_mac(struct smbd_server_connection *conn,
32 const char *inbuf, uint32_t *seqnum,
33 bool trusted_channel)
34{
35 /* Check if it's a non-session message. */
36 if(CVAL(inbuf,0)) {
37 return true;
38 }
39
40 if (trusted_channel) {
41 NTSTATUS status;
42
43 if (smb_len(inbuf) < (smb_ss_field + 8 - 4)) {
44 DEBUG(1,("smb_signing_check_pdu: Can't check signature "
45 "on short packet! smb_len = %u\n",
46 smb_len(inbuf)));
47 return false;
48 }
49
50 status = NT_STATUS(IVAL(inbuf, smb_ss_field + 4));
51 if (!NT_STATUS_IS_OK(status)) {
52 DEBUG(1,("smb_signing_check_pdu: trusted channel passed %s\n",
53 nt_errstr(status)));
54 return false;
55 }
56
57 *seqnum = IVAL(inbuf, smb_ss_field);
58 return true;
59 }
60
61 *seqnum = smb_signing_next_seqnum(conn->smb1.signing_state, false);
62 return smb_signing_check_pdu(conn->smb1.signing_state,
63 (const uint8_t *)inbuf,
64 *seqnum);
65}
66
67/***********************************************************
68 Called to sign an outgoing packet to the client.
69************************************************************/
70
71void srv_calculate_sign_mac(struct smbd_server_connection *conn,
72 char *outbuf, uint32_t seqnum)
73{
74 /* Check if it's a non-session message. */
75 if(CVAL(outbuf,0)) {
76 return;
77 }
78
79 smb_signing_sign_pdu(conn->smb1.signing_state, (uint8_t *)outbuf, seqnum);
80}
81
82
83/***********************************************************
84 Called to indicate a oneway request
85************************************************************/
86void srv_cancel_sign_response(struct smbd_server_connection *conn)
87{
88 smb_signing_cancel_reply(conn->smb1.signing_state, true);
89}
90
91struct smbd_shm_signing {
92 size_t shm_size;
93 uint8_t *shm_pointer;
94
95 /* we know the signing engine will only allocate 2 chunks */
96 uint8_t *ptr1;
97 size_t len1;
98 uint8_t *ptr2;
99 size_t len2;
100};
101
102static int smbd_shm_signing_destructor(struct smbd_shm_signing *s)
103{
104 anonymous_shared_free(s->shm_pointer);
105 return 0;
106}
107
108static void *smbd_shm_signing_alloc(TALLOC_CTX *mem_ctx, size_t len)
109{
110 struct smbd_shm_signing *s = talloc_get_type_abort(mem_ctx,
111 struct smbd_shm_signing);
112
113 if (s->ptr1 == NULL) {
114 s->len1 = len;
115 if (len % 8) {
116 s->len1 += (8 - (len % 8));
117 }
118 if (s->len1 > s->shm_size) {
119 s->len1 = 0;
120 errno = ENOMEM;
121 return NULL;
122 }
123 s->ptr1 = s->shm_pointer;
124 return s->ptr1;
125 }
126
127 if (s->ptr2 == NULL) {
128 s->len2 = len;
129 if (s->len2 > (s->shm_size - s->len1)) {
130 s->len2 = 0;
131 errno = ENOMEM;
132 return NULL;
133 }
134 s->ptr2 = s->shm_pointer + s->len1;
135 return s->ptr2;
136 }
137
138 errno = ENOMEM;
139 return NULL;
140}
141
142static void smbd_shm_signing_free(TALLOC_CTX *mem_ctx, void *ptr)
143{
144 struct smbd_shm_signing *s = talloc_get_type_abort(mem_ctx,
145 struct smbd_shm_signing);
146
147 if (s->ptr2 == ptr) {
148 s->ptr2 = NULL;
149 s->len2 = 0;
150 }
151}
152
153/***********************************************************
154 Called by server negprot when signing has been negotiated.
155************************************************************/
156
157bool srv_init_signing(struct smbd_server_connection *conn)
158{
159 bool allowed = true;
160 bool mandatory = false;
161
162 switch (lp_server_signing()) {
163 case Required:
164 mandatory = true;
165 break;
166 case Auto:
167 break;
168 case True:
169 break;
170 case False:
171 allowed = false;
172 break;
173 }
174
175 if (lp_async_smb_echo_handler()) {
176 struct smbd_shm_signing *s;
177
178 /* setup the signing state in shared memory */
179 s = talloc_zero(smbd_event_context(), struct smbd_shm_signing);
180 if (s == NULL) {
181 return false;
182 }
183 s->shm_size = 4096;
184 s->shm_pointer =
185 (uint8_t *)anonymous_shared_allocate(s->shm_size);
186 if (s->shm_pointer == NULL) {
187 talloc_free(s);
188 return false;
189 }
190 talloc_set_destructor(s, smbd_shm_signing_destructor);
191 conn->smb1.signing_state = smb_signing_init_ex(s,
192 allowed, mandatory,
193 smbd_shm_signing_alloc,
194 smbd_shm_signing_free);
195 if (!conn->smb1.signing_state) {
196 return false;
197 }
198 return true;
199 }
200
201 conn->smb1.signing_state = smb_signing_init(smbd_event_context(),
202 allowed, mandatory);
203 if (!conn->smb1.signing_state) {
204 return false;
205 }
206
207 return true;
208}
209
210void srv_set_signing_negotiated(struct smbd_server_connection *conn)
211{
212 smb_signing_set_negotiated(conn->smb1.signing_state);
213}
214
215/***********************************************************
216 Returns whether signing is active. We can't use sendfile or raw
217 reads/writes if it is.
218************************************************************/
219
220bool srv_is_signing_active(struct smbd_server_connection *conn)
221{
222 return smb_signing_is_active(conn->smb1.signing_state);
223}
224
225
226/***********************************************************
227 Returns whether signing is negotiated. We can't use it unless it was
228 in the negprot.
229************************************************************/
230
231bool srv_is_signing_negotiated(struct smbd_server_connection *conn)
232{
233 return smb_signing_is_negotiated(conn->smb1.signing_state);
234}
235
236/***********************************************************
237 Turn on signing from this packet onwards.
238************************************************************/
239
240void srv_set_signing(struct smbd_server_connection *conn,
241 const DATA_BLOB user_session_key,
242 const DATA_BLOB response)
243{
244 bool negotiated;
245 bool mandatory;
246
247 if (!user_session_key.length)
248 return;
249
250 negotiated = smb_signing_is_negotiated(conn->smb1.signing_state);
251 mandatory = smb_signing_is_mandatory(conn->smb1.signing_state);
252
253 if (!negotiated && !mandatory) {
254 DEBUG(5,("srv_set_signing: signing negotiated = %u, "
255 "mandatory_signing = %u. Not allowing smb signing.\n",
256 negotiated, mandatory));
257 return;
258 }
259
260 if (!smb_signing_activate(conn->smb1.signing_state,
261 user_session_key, response)) {
262 return;
263 }
264
265 DEBUG(3,("srv_set_signing: turning on SMB signing: "
266 "signing negotiated = %u, mandatory_signing = %u.\n",
267 negotiated, mandatory));
268}
269
Note: See TracBrowser for help on using the repository browser.