s3-waf: Set HAVE_GSSAPI if gssapi libs were found
[Samba/gebeck_regimport.git] / source3 / libsmb / smb_seal.c
blobec879db5b42cb4b65f2585cf21fd18106f4d264a
1 /*
2 Unix SMB/CIFS implementation.
3 SMB Transport encryption (sealing) code.
4 Copyright (C) Jeremy Allison 2007.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include "ntlmssp.h"
23 /******************************************************************************
24 Pull out the encryption context for this packet. 0 means global context.
25 ******************************************************************************/
27 NTSTATUS get_enc_ctx_num(const uint8_t *buf, uint16 *p_enc_ctx_num)
29 if (smb_len(buf) < 8) {
30 return NT_STATUS_INVALID_BUFFER_SIZE;
33 if (buf[4] == 0xFF) {
34 if (buf[5] == 'S' && buf [6] == 'M' && buf[7] == 'B') {
35 /* Not an encrypted buffer. */
36 return NT_STATUS_NOT_FOUND;
38 if (buf[5] == 'E') {
39 *p_enc_ctx_num = SVAL(buf,6);
40 return NT_STATUS_OK;
43 return NT_STATUS_INVALID_NETWORK_RESPONSE;
46 /******************************************************************************
47 Generic code for client and server.
48 Is encryption turned on ?
49 ******************************************************************************/
51 bool common_encryption_on(struct smb_trans_enc_state *es)
53 return ((es != NULL) && es->enc_on);
56 /******************************************************************************
57 Generic code for client and server.
58 NTLM decrypt an incoming buffer.
59 Abartlett tells me that SSPI puts the signature first before the encrypted
60 output, so cope with the same for compatibility.
61 ******************************************************************************/
63 NTSTATUS common_ntlm_decrypt_buffer(struct ntlmssp_state *ntlmssp_state, char *buf)
65 NTSTATUS status;
66 size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */
67 size_t data_len;
68 char *inbuf;
69 DATA_BLOB sig;
71 if (buf_len < 8 + NTLMSSP_SIG_SIZE) {
72 return NT_STATUS_BUFFER_TOO_SMALL;
75 inbuf = (char *)smb_xmemdup(buf, buf_len);
77 /* Adjust for the signature. */
78 data_len = buf_len - 8 - NTLMSSP_SIG_SIZE;
80 /* Point at the signature. */
81 sig = data_blob_const(inbuf+8, NTLMSSP_SIG_SIZE);
83 status = ntlmssp_unseal_packet(ntlmssp_state,
84 (unsigned char *)inbuf + 8 + NTLMSSP_SIG_SIZE, /* 4 byte len + 0xFF 'E' <enc> <ctx> */
85 data_len,
86 (unsigned char *)inbuf + 8 + NTLMSSP_SIG_SIZE,
87 data_len,
88 &sig);
90 if (!NT_STATUS_IS_OK(status)) {
91 SAFE_FREE(inbuf);
92 return status;
95 memcpy(buf + 8, inbuf + 8 + NTLMSSP_SIG_SIZE, data_len);
97 /* Reset the length and overwrite the header. */
98 smb_setlen(buf,data_len + 4);
100 SAFE_FREE(inbuf);
101 return NT_STATUS_OK;
104 /******************************************************************************
105 Generic code for client and server.
106 NTLM encrypt an outgoing buffer. Return the encrypted pointer in ppbuf_out.
107 Abartlett tells me that SSPI puts the signature first before the encrypted
108 output, so do the same for compatibility.
109 ******************************************************************************/
111 NTSTATUS common_ntlm_encrypt_buffer(struct ntlmssp_state *ntlmssp_state,
112 uint16 enc_ctx_num,
113 char *buf,
114 char **ppbuf_out)
116 NTSTATUS status;
117 char *buf_out;
118 size_t data_len = smb_len(buf) - 4; /* Ignore the 0xFF SMB bytes. */
119 DATA_BLOB sig;
121 *ppbuf_out = NULL;
123 if (data_len == 0) {
124 return NT_STATUS_BUFFER_TOO_SMALL;
128 * We know smb_len can't return a value > 128k, so no int overflow
129 * check needed.
132 buf_out = SMB_XMALLOC_ARRAY(char, 8 + NTLMSSP_SIG_SIZE + data_len);
134 /* Copy the data from the original buffer. */
136 memcpy(buf_out + 8 + NTLMSSP_SIG_SIZE, buf + 8, data_len);
138 smb_set_enclen(buf_out, smb_len(buf) + NTLMSSP_SIG_SIZE, enc_ctx_num);
140 ZERO_STRUCT(sig);
142 status = ntlmssp_seal_packet(ntlmssp_state,
143 (unsigned char *)buf_out + 8 + NTLMSSP_SIG_SIZE, /* 4 byte len + 0xFF 'S' <enc> <ctx> */
144 data_len,
145 (unsigned char *)buf_out + 8 + NTLMSSP_SIG_SIZE,
146 data_len,
147 &sig);
149 if (!NT_STATUS_IS_OK(status)) {
150 data_blob_free(&sig);
151 SAFE_FREE(buf_out);
152 return status;
155 /* First 16 data bytes are signature for SSPI compatibility. */
156 memcpy(buf_out + 8, sig.data, NTLMSSP_SIG_SIZE);
157 data_blob_free(&sig);
158 *ppbuf_out = buf_out;
159 return NT_STATUS_OK;
162 /******************************************************************************
163 Generic code for client and server.
164 gss-api decrypt an incoming buffer. We insist that the size of the
165 unwrapped buffer must be smaller or identical to the incoming buffer.
166 ******************************************************************************/
168 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
169 static NTSTATUS common_gss_decrypt_buffer(struct smb_tran_enc_state_gss *gss_state, char *buf)
171 gss_ctx_id_t gss_ctx = gss_state->gss_ctx;
172 OM_uint32 ret = 0;
173 OM_uint32 minor = 0;
174 int flags_got = 0;
175 gss_buffer_desc in_buf, out_buf;
176 size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */
178 if (buf_len < 8) {
179 return NT_STATUS_BUFFER_TOO_SMALL;
182 in_buf.value = buf + 8;
183 in_buf.length = buf_len - 8;
185 ret = gss_unwrap(&minor,
186 gss_ctx,
187 &in_buf,
188 &out_buf,
189 &flags_got, /* did we get sign+seal ? */
190 (gss_qop_t *) NULL);
192 if (ret != GSS_S_COMPLETE) {
193 ADS_STATUS adss = ADS_ERROR_GSS(ret, minor);
194 DEBUG(0,("common_gss_encrypt_buffer: gss_unwrap failed. Error %s\n",
195 ads_errstr(adss) ));
196 return map_nt_error_from_gss(ret, minor);
199 if (out_buf.length > in_buf.length) {
200 DEBUG(0,("common_gss_encrypt_buffer: gss_unwrap size (%u) too large (%u) !\n",
201 (unsigned int)out_buf.length,
202 (unsigned int)in_buf.length ));
203 gss_release_buffer(&minor, &out_buf);
204 return NT_STATUS_INVALID_PARAMETER;
207 memcpy(buf + 8, out_buf.value, out_buf.length);
208 /* Reset the length and overwrite the header. */
209 smb_setlen(buf, out_buf.length + 4);
211 gss_release_buffer(&minor, &out_buf);
212 return NT_STATUS_OK;
215 /******************************************************************************
216 Generic code for client and server.
217 gss-api encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
218 ******************************************************************************/
220 static NTSTATUS common_gss_encrypt_buffer(struct smb_tran_enc_state_gss *gss_state,
221 uint16 enc_ctx_num,
222 char *buf,
223 char **ppbuf_out)
225 gss_ctx_id_t gss_ctx = gss_state->gss_ctx;
226 OM_uint32 ret = 0;
227 OM_uint32 minor = 0;
228 int flags_got = 0;
229 gss_buffer_desc in_buf, out_buf;
230 size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */
232 *ppbuf_out = NULL;
234 if (buf_len < 8) {
235 return NT_STATUS_BUFFER_TOO_SMALL;
238 in_buf.value = buf + 8;
239 in_buf.length = buf_len - 8;
241 ret = gss_wrap(&minor,
242 gss_ctx,
243 true, /* we want sign+seal. */
244 GSS_C_QOP_DEFAULT,
245 &in_buf,
246 &flags_got, /* did we get sign+seal ? */
247 &out_buf);
249 if (ret != GSS_S_COMPLETE) {
250 ADS_STATUS adss = ADS_ERROR_GSS(ret, minor);
251 DEBUG(0,("common_gss_encrypt_buffer: gss_wrap failed. Error %s\n",
252 ads_errstr(adss) ));
253 return map_nt_error_from_gss(ret, minor);
256 if (!flags_got) {
257 /* Sign+seal not supported. */
258 gss_release_buffer(&minor, &out_buf);
259 return NT_STATUS_NOT_SUPPORTED;
262 /* Ya see - this is why I *hate* gss-api. I don't
263 * want to have to malloc another buffer of the
264 * same size + 8 bytes just to get a continuous
265 * header + buffer, but gss won't let me pass in
266 * a pre-allocated buffer. Bastards (and you know
267 * who you are....). I might fix this by
268 * going to "encrypt_and_send" passing in a file
269 * descriptor and doing scatter-gather write with
270 * TCP cork on Linux. But I shouldn't have to
271 * bother :-*(. JRA.
274 *ppbuf_out = (char *)SMB_MALLOC(out_buf.length + 8); /* We know this can't wrap. */
275 if (!*ppbuf_out) {
276 gss_release_buffer(&minor, &out_buf);
277 return NT_STATUS_NO_MEMORY;
280 memcpy(*ppbuf_out+8, out_buf.value, out_buf.length);
281 smb_set_enclen(*ppbuf_out, out_buf.length + 4, enc_ctx_num);
283 gss_release_buffer(&minor, &out_buf);
284 return NT_STATUS_OK;
286 #endif
288 /******************************************************************************
289 Generic code for client and server.
290 Encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
291 ******************************************************************************/
293 NTSTATUS common_encrypt_buffer(struct smb_trans_enc_state *es, char *buffer, char **buf_out)
295 if (!common_encryption_on(es)) {
296 /* Not encrypting. */
297 *buf_out = buffer;
298 return NT_STATUS_OK;
301 switch (es->smb_enc_type) {
302 case SMB_TRANS_ENC_NTLM:
303 return common_ntlm_encrypt_buffer(es->s.ntlmssp_state, es->enc_ctx_num, buffer, buf_out);
304 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
305 case SMB_TRANS_ENC_GSS:
306 return common_gss_encrypt_buffer(es->s.gss_state, es->enc_ctx_num, buffer, buf_out);
307 #endif
308 default:
309 return NT_STATUS_NOT_SUPPORTED;
313 /******************************************************************************
314 Generic code for client and server.
315 Decrypt an incoming SMB buffer. Replaces the data within it.
316 New data must be less than or equal to the current length.
317 ******************************************************************************/
319 NTSTATUS common_decrypt_buffer(struct smb_trans_enc_state *es, char *buf)
321 if (!common_encryption_on(es)) {
322 /* Not decrypting. */
323 return NT_STATUS_OK;
326 switch (es->smb_enc_type) {
327 case SMB_TRANS_ENC_NTLM:
328 return common_ntlm_decrypt_buffer(es->s.ntlmssp_state, buf);
329 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
330 case SMB_TRANS_ENC_GSS:
331 return common_gss_decrypt_buffer(es->s.gss_state, buf);
332 #endif
333 default:
334 return NT_STATUS_NOT_SUPPORTED;
338 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
339 /******************************************************************************
340 Shutdown a gss encryption state.
341 ******************************************************************************/
343 static void common_free_gss_state(struct smb_tran_enc_state_gss **pp_gss_state)
345 OM_uint32 minor = 0;
346 struct smb_tran_enc_state_gss *gss_state = *pp_gss_state;
348 if (gss_state->creds != GSS_C_NO_CREDENTIAL) {
349 gss_release_cred(&minor, &gss_state->creds);
351 if (gss_state->gss_ctx != GSS_C_NO_CONTEXT) {
352 gss_delete_sec_context(&minor, &gss_state->gss_ctx, NULL);
354 SAFE_FREE(*pp_gss_state);
356 #endif
358 /******************************************************************************
359 Shutdown an encryption state.
360 ******************************************************************************/
362 void common_free_encryption_state(struct smb_trans_enc_state **pp_es)
364 struct smb_trans_enc_state *es = *pp_es;
366 if (es == NULL) {
367 return;
370 if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
371 if (es->s.ntlmssp_state) {
372 ntlmssp_end(&es->s.ntlmssp_state);
375 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
376 if (es->smb_enc_type == SMB_TRANS_ENC_GSS) {
377 /* Free the gss context handle. */
378 if (es->s.gss_state) {
379 common_free_gss_state(&es->s.gss_state);
382 #endif
383 SAFE_FREE(es);
384 *pp_es = NULL;
387 /******************************************************************************
388 Free an encryption-allocated buffer.
389 ******************************************************************************/
391 void common_free_enc_buffer(struct smb_trans_enc_state *es, char *buf)
393 uint16_t enc_ctx_num;
395 if (!common_encryption_on(es)) {
396 return;
399 if (!NT_STATUS_IS_OK(get_enc_ctx_num((const uint8_t *)buf,
400 &enc_ctx_num))) {
401 return;
404 if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
405 SAFE_FREE(buf);
406 return;
409 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
410 if (es->smb_enc_type == SMB_TRANS_ENC_GSS) {
411 OM_uint32 min;
412 gss_buffer_desc rel_buf;
413 rel_buf.value = buf;
414 rel_buf.length = smb_len(buf) + 4;
415 gss_release_buffer(&min, &rel_buf);
417 #endif
420 /******************************************************************************
421 Client side encryption.
422 ******************************************************************************/
424 /******************************************************************************
425 Is client encryption on ?
426 ******************************************************************************/
428 bool cli_encryption_on(struct cli_state *cli)
430 /* If we supported multiple encrytion contexts
431 * here we'd look up based on tid.
433 return common_encryption_on(cli->trans_enc_state);
436 /******************************************************************************
437 Shutdown a client encryption state.
438 ******************************************************************************/
440 void cli_free_encryption_context(struct cli_state *cli)
442 common_free_encryption_state(&cli->trans_enc_state);
445 /******************************************************************************
446 Free an encryption-allocated buffer.
447 ******************************************************************************/
449 void cli_free_enc_buffer(struct cli_state *cli, char *buf)
451 /* We know this is an smb buffer, and we
452 * didn't malloc, only copy, for a keepalive,
453 * so ignore non-session messages. */
455 if(CVAL(buf,0)) {
456 return;
459 /* If we supported multiple encrytion contexts
460 * here we'd look up based on tid.
462 common_free_enc_buffer(cli->trans_enc_state, buf);
465 /******************************************************************************
466 Decrypt an incoming buffer.
467 ******************************************************************************/
469 NTSTATUS cli_decrypt_message(struct cli_state *cli)
471 NTSTATUS status;
472 uint16 enc_ctx_num;
474 /* Ignore non-session messages. */
475 if(CVAL(cli->inbuf,0)) {
476 return NT_STATUS_OK;
479 status = get_enc_ctx_num((const uint8_t *)cli->inbuf, &enc_ctx_num);
480 if (!NT_STATUS_IS_OK(status)) {
481 return status;
484 if (enc_ctx_num != cli->trans_enc_state->enc_ctx_num) {
485 return NT_STATUS_INVALID_HANDLE;
488 return common_decrypt_buffer(cli->trans_enc_state, cli->inbuf);
491 /******************************************************************************
492 Encrypt an outgoing buffer. Return the encrypted pointer in buf_out.
493 ******************************************************************************/
495 NTSTATUS cli_encrypt_message(struct cli_state *cli, char *buf, char **buf_out)
497 /* Ignore non-session messages. */
498 if (CVAL(buf,0)) {
499 return NT_STATUS_OK;
502 /* If we supported multiple encrytion contexts
503 * here we'd look up based on tid.
505 return common_encrypt_buffer(cli->trans_enc_state, buf, buf_out);