Line data Source code
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 :
32 654040 : bool smb1_srv_check_sign_mac(struct smbXsrv_connection *conn,
33 : const char *inbuf, uint32_t *seqnum,
34 : bool trusted_channel)
35 : {
36 7859 : const uint8_t *inhdr;
37 7859 : size_t len;
38 :
39 : /* Check if it's a non-session message. */
40 654040 : if(CVAL(inbuf,0)) {
41 175 : return true;
42 : }
43 :
44 653865 : len = smb_len(inbuf);
45 653865 : inhdr = (const uint8_t *)inbuf + NBT_HDR_SIZE;
46 :
47 653865 : if (trusted_channel) {
48 0 : NTSTATUS status;
49 :
50 0 : if (len < (HDR_SS_FIELD + 8)) {
51 0 : DBG_WARNING("Can't check signature "
52 : "on short packet! smb_len = %u\n",
53 : (unsigned)len);
54 0 : return false;
55 : }
56 :
57 0 : status = NT_STATUS(IVAL(inhdr, HDR_SS_FIELD + 4));
58 0 : if (!NT_STATUS_IS_OK(status)) {
59 0 : DBG_WARNING("trusted channel passed %s\n",
60 : nt_errstr(status));
61 0 : return false;
62 : }
63 :
64 0 : *seqnum = IVAL(inhdr, HDR_SS_FIELD);
65 0 : return true;
66 : }
67 :
68 653865 : *seqnum = smb1_signing_next_seqnum(conn->smb1.signing_state, false);
69 653865 : return smb1_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 :
78 652227 : NTSTATUS smb1_srv_calculate_sign_mac(struct smbXsrv_connection *conn,
79 : char *outbuf, uint32_t seqnum)
80 : {
81 7851 : uint8_t *outhdr;
82 7851 : size_t len;
83 :
84 : /* Check if it's a non-session message. */
85 652227 : if(CVAL(outbuf,0)) {
86 0 : return NT_STATUS_OK;;
87 : }
88 :
89 652227 : len = smb_len(outbuf);
90 652227 : outhdr = (uint8_t *)outbuf + NBT_HDR_SIZE;
91 :
92 652227 : return smb1_signing_sign_pdu(conn->smb1.signing_state,
93 : outhdr,
94 : len,
95 : seqnum);
96 : }
97 :
98 :
99 : /***********************************************************
100 : Called to indicate a oneway request
101 : ************************************************************/
102 989 : void smb1_srv_cancel_sign_response(struct smbXsrv_connection *conn)
103 : {
104 989 : smb1_signing_cancel_reply(conn->smb1.signing_state, true);
105 989 : }
106 :
107 : struct smbd_shm_signing {
108 : size_t shm_size;
109 : uint8_t *shm_pointer;
110 :
111 : /* we know the signing engine will only allocate 2 chunks */
112 : uint8_t *ptr1;
113 : size_t len1;
114 : uint8_t *ptr2;
115 : size_t len2;
116 : };
117 :
118 0 : static int smbd_shm_signing_destructor(struct smbd_shm_signing *s)
119 : {
120 0 : anonymous_shared_free(s->shm_pointer);
121 0 : return 0;
122 : }
123 :
124 0 : static void *smbd_shm_signing_alloc(TALLOC_CTX *mem_ctx, size_t len)
125 : {
126 0 : struct smbd_shm_signing *s = talloc_get_type_abort(mem_ctx,
127 : struct smbd_shm_signing);
128 :
129 0 : if (s->ptr1 == NULL) {
130 0 : s->len1 = len;
131 0 : if (len % 8) {
132 0 : s->len1 += (8 - (len % 8));
133 : }
134 0 : if (s->len1 > s->shm_size) {
135 0 : s->len1 = 0;
136 0 : errno = ENOMEM;
137 0 : return NULL;
138 : }
139 0 : s->ptr1 = s->shm_pointer;
140 0 : return s->ptr1;
141 : }
142 :
143 0 : if (s->ptr2 == NULL) {
144 0 : s->len2 = len;
145 0 : if (s->len2 > (s->shm_size - s->len1)) {
146 0 : s->len2 = 0;
147 0 : errno = ENOMEM;
148 0 : return NULL;
149 : }
150 0 : s->ptr2 = s->shm_pointer + s->len1;
151 0 : return s->ptr2;
152 : }
153 :
154 0 : errno = ENOMEM;
155 0 : return NULL;
156 : }
157 :
158 0 : static void smbd_shm_signing_free(TALLOC_CTX *mem_ctx, void *ptr)
159 : {
160 0 : struct smbd_shm_signing *s = talloc_get_type_abort(mem_ctx,
161 : struct smbd_shm_signing);
162 :
163 0 : if (s->ptr2 == ptr) {
164 0 : s->ptr2 = NULL;
165 0 : s->len2 = 0;
166 : }
167 0 : }
168 :
169 : /***********************************************************
170 : Called by server negprot when signing has been negotiated.
171 : ************************************************************/
172 :
173 32669 : bool smb1_srv_init_signing(struct loadparm_context *lp_ctx,
174 : struct smbXsrv_connection *conn)
175 : {
176 32669 : bool allowed = true;
177 894 : bool desired;
178 32669 : bool mandatory = false;
179 :
180 : /*
181 : * if the client and server allow signing,
182 : * we desire to use it.
183 : *
184 : * This matches Windows behavior and is needed
185 : * because not every client that requires signing
186 : * sends FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED.
187 : *
188 : * Note that we'll always allow signing if the client
189 : * does send FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED.
190 : */
191 :
192 32669 : desired = lpcfg_server_signing_allowed(lp_ctx, &mandatory);
193 :
194 32669 : if (lp_async_smb_echo_handler()) {
195 0 : struct smbd_shm_signing *s;
196 :
197 : /* setup the signing state in shared memory */
198 0 : s = talloc_zero(conn, struct smbd_shm_signing);
199 0 : if (s == NULL) {
200 0 : return false;
201 : }
202 0 : s->shm_size = 4096;
203 0 : s->shm_pointer =
204 0 : (uint8_t *)anonymous_shared_allocate(s->shm_size);
205 0 : if (s->shm_pointer == NULL) {
206 0 : talloc_free(s);
207 0 : return false;
208 : }
209 0 : talloc_set_destructor(s, smbd_shm_signing_destructor);
210 0 : conn->smb1.signing_state = smb1_signing_init_ex(s,
211 : allowed, desired, mandatory,
212 : smbd_shm_signing_alloc,
213 : smbd_shm_signing_free);
214 0 : if (!conn->smb1.signing_state) {
215 0 : return false;
216 : }
217 0 : return true;
218 : }
219 :
220 32669 : conn->smb1.signing_state = smb1_signing_init(conn,
221 : allowed, desired, mandatory);
222 32669 : if (!conn->smb1.signing_state) {
223 0 : return false;
224 : }
225 :
226 31775 : return true;
227 : }
228 :
229 13319 : void smb1_srv_set_signing_negotiated(struct smbXsrv_connection *conn,
230 : bool allowed, bool mandatory)
231 : {
232 13319 : smb1_signing_set_negotiated(conn->smb1.signing_state,
233 : allowed, mandatory);
234 13319 : }
235 :
236 : /***********************************************************
237 : Returns whether signing is active. We can't use sendfile or raw
238 : reads/writes if it is.
239 : ************************************************************/
240 :
241 652078 : bool smb1_srv_is_signing_active(struct smbXsrv_connection *conn)
242 : {
243 652078 : return smb1_signing_is_active(conn->smb1.signing_state);
244 : }
245 :
246 :
247 : /***********************************************************
248 : Returns whether signing is negotiated. We can't use it unless it was
249 : in the negprot.
250 : ************************************************************/
251 :
252 5747 : bool smb1_srv_is_signing_negotiated(struct smbXsrv_connection *conn)
253 : {
254 5747 : return smb1_signing_is_negotiated(conn->smb1.signing_state);
255 : }
256 :
257 : /***********************************************************
258 : Turn on signing from this packet onwards.
259 : ************************************************************/
260 :
261 1061 : void smb1_srv_set_signing(struct smbXsrv_connection *conn,
262 : const DATA_BLOB user_session_key,
263 : const DATA_BLOB response)
264 : {
265 133 : bool negotiated;
266 133 : bool mandatory;
267 :
268 1061 : if (!user_session_key.length)
269 0 : return;
270 :
271 1061 : negotiated = smb1_signing_is_negotiated(conn->smb1.signing_state);
272 1061 : mandatory = smb1_signing_is_mandatory(conn->smb1.signing_state);
273 :
274 1061 : if (!negotiated && !mandatory) {
275 0 : DBG_INFO("signing negotiated = %u, "
276 : "mandatory_signing = %u. Not allowing smb signing.\n",
277 : negotiated, mandatory);
278 0 : return;
279 : }
280 :
281 1061 : if (!smb1_signing_activate(conn->smb1.signing_state,
282 : user_session_key, response)) {
283 2 : return;
284 : }
285 :
286 1059 : DBG_NOTICE("turning on SMB signing: "
287 : "signing negotiated = %u, mandatory_signing = %u.\n",
288 : negotiated, mandatory);
289 : }
290 :
|