docs: Document removal of the autoconf build system
[obnox/samba/samba-obnox.git] / source3 / smbd / signing.c
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
27 /***********************************************************
28  Called to validate an incoming packet from the client.
29 ************************************************************/
30
31 bool srv_check_sign_mac(struct smbd_server_connection *conn,
32                         const char *inbuf, uint32_t *seqnum,
33                         bool trusted_channel)
34 {
35         const uint8_t *inhdr;
36         size_t len;
37
38         /* Check if it's a non-session message. */
39         if(CVAL(inbuf,0)) {
40                 return true;
41         }
42
43         len = smb_len(inbuf);
44         inhdr = (const uint8_t *)inbuf + NBT_HDR_SIZE;
45
46         if (trusted_channel) {
47                 NTSTATUS status;
48
49                 if (len < (HDR_SS_FIELD + 8)) {
50                         DEBUG(1,("smb_signing_check_pdu: Can't check signature "
51                                  "on short packet! smb_len = %u\n",
52                                  (unsigned)len));
53                         return false;
54                 }
55
56                 status = NT_STATUS(IVAL(inhdr, HDR_SS_FIELD + 4));
57                 if (!NT_STATUS_IS_OK(status)) {
58                         DEBUG(1,("smb_signing_check_pdu: trusted channel passed %s\n",
59                                  nt_errstr(status)));
60                         return false;
61                 }
62
63                 *seqnum = IVAL(inhdr, HDR_SS_FIELD);
64                 return true;
65         }
66
67         *seqnum = smb_signing_next_seqnum(conn->smb1.signing_state, false);
68         return smb_signing_check_pdu(conn->smb1.signing_state,
69                                      inhdr, len,
70                                      *seqnum);
71 }
72
73 /***********************************************************
74  Called to sign an outgoing packet to the client.
75 ************************************************************/
76
77 void srv_calculate_sign_mac(struct smbd_server_connection *conn,
78                             char *outbuf, uint32_t seqnum)
79 {
80         uint8_t *outhdr;
81         size_t len;
82
83         /* Check if it's a non-session message. */
84         if(CVAL(outbuf,0)) {
85                 return;
86         }
87
88         len = smb_len(outbuf);
89         outhdr = (uint8_t *)outbuf + NBT_HDR_SIZE;
90
91         smb_signing_sign_pdu(conn->smb1.signing_state, outhdr, len, seqnum);
92 }
93
94
95 /***********************************************************
96  Called to indicate a oneway request
97 ************************************************************/
98 void srv_cancel_sign_response(struct smbd_server_connection *conn)
99 {
100         smb_signing_cancel_reply(conn->smb1.signing_state, true);
101 }
102
103 struct smbd_shm_signing {
104         size_t shm_size;
105         uint8_t *shm_pointer;
106
107         /* we know the signing engine will only allocate 2 chunks */
108         uint8_t *ptr1;
109         size_t len1;
110         uint8_t *ptr2;
111         size_t len2;
112 };
113
114 static int smbd_shm_signing_destructor(struct smbd_shm_signing *s)
115 {
116         anonymous_shared_free(s->shm_pointer);
117         return 0;
118 }
119
120 static void *smbd_shm_signing_alloc(TALLOC_CTX *mem_ctx, size_t len)
121 {
122         struct smbd_shm_signing *s = talloc_get_type_abort(mem_ctx,
123                                      struct smbd_shm_signing);
124
125         if (s->ptr1 == NULL) {
126                 s->len1 = len;
127                 if (len % 8) {
128                         s->len1 += (8 - (len % 8));
129                 }
130                 if (s->len1 > s->shm_size) {
131                         s->len1 = 0;
132                         errno = ENOMEM;
133                         return NULL;
134                 }
135                 s->ptr1 = s->shm_pointer;
136                 return s->ptr1;
137         }
138
139         if (s->ptr2 == NULL) {
140                 s->len2 = len;
141                 if (s->len2 > (s->shm_size - s->len1)) {
142                         s->len2 = 0;
143                         errno = ENOMEM;
144                         return NULL;
145                 }
146                 s->ptr2 = s->shm_pointer + s->len1;
147                 return s->ptr2;
148         }
149
150         errno = ENOMEM;
151         return NULL;
152 }
153
154 static void smbd_shm_signing_free(TALLOC_CTX *mem_ctx, void *ptr)
155 {
156         struct smbd_shm_signing *s = talloc_get_type_abort(mem_ctx,
157                                      struct smbd_shm_signing);
158
159         if (s->ptr2 == ptr) {
160                 s->ptr2 = NULL;
161                 s->len2 = 0;
162         }
163 }
164
165 /***********************************************************
166  Called by server negprot when signing has been negotiated.
167 ************************************************************/
168
169 bool srv_init_signing(struct smbd_server_connection *conn)
170 {
171         bool allowed = true;
172         bool desired;
173         bool mandatory = false;
174
175         switch (lp_server_signing()) {
176         case SMB_SIGNING_REQUIRED:
177                 mandatory = true;
178                 break;
179         case SMB_SIGNING_IF_REQUIRED:
180                 break;
181         case SMB_SIGNING_DEFAULT:
182         case SMB_SIGNING_OFF:
183                 allowed = false;
184                 break;
185         }
186
187         /*
188          * if the client and server allow signing,
189          * we desire to use it.
190          *
191          * This matches Windows behavior and is needed
192          * because not every client that requires signing
193          * sends FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED.
194          */
195         desired = allowed;
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
232 void srv_set_signing_negotiated(struct smbd_server_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
244 bool srv_is_signing_active(struct smbd_server_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
255 bool srv_is_signing_negotiated(struct smbd_server_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
264 void srv_set_signing(struct smbd_server_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