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/>.
22
/******************************************************************************
23
Pull out the encryption context for this packet. 0 means global context.
24
******************************************************************************/
26
NTSTATUS get_enc_ctx_num(const uint8_t *buf, uint16 *p_enc_ctx_num)
28
if (smb_len(buf) < 8) {
29
return NT_STATUS_INVALID_BUFFER_SIZE;
33
if (buf[5] == 'S' && buf [6] == 'M' && buf[7] == 'B') {
34
/* Not an encrypted buffer. */
35
return NT_STATUS_NOT_FOUND;
38
*p_enc_ctx_num = SVAL(buf,6);
42
return NT_STATUS_INVALID_NETWORK_RESPONSE;
45
/******************************************************************************
46
Generic code for client and server.
47
Is encryption turned on ?
48
******************************************************************************/
50
bool common_encryption_on(struct smb_trans_enc_state *es)
52
return ((es != NULL) && es->enc_on);
55
/******************************************************************************
56
Generic code for client and server.
57
NTLM decrypt an incoming buffer.
58
Abartlett tells me that SSPI puts the signature first before the encrypted
59
output, so cope with the same for compatibility.
60
******************************************************************************/
62
NTSTATUS common_ntlm_decrypt_buffer(NTLMSSP_STATE *ntlmssp_state, char *buf)
65
size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */
70
if (buf_len < 8 + NTLMSSP_SIG_SIZE) {
71
return NT_STATUS_BUFFER_TOO_SMALL;
74
inbuf = (char *)smb_xmemdup(buf, buf_len);
76
/* Adjust for the signature. */
77
data_len = buf_len - 8 - NTLMSSP_SIG_SIZE;
79
/* Point at the signature. */
80
sig = data_blob_const(inbuf+8, NTLMSSP_SIG_SIZE);
82
status = ntlmssp_unseal_packet(ntlmssp_state,
83
(unsigned char *)inbuf + 8 + NTLMSSP_SIG_SIZE, /* 4 byte len + 0xFF 'E' <enc> <ctx> */
85
(unsigned char *)inbuf + 8 + NTLMSSP_SIG_SIZE,
89
if (!NT_STATUS_IS_OK(status)) {
94
memcpy(buf + 8, inbuf + 8 + NTLMSSP_SIG_SIZE, data_len);
96
/* Reset the length and overwrite the header. */
97
smb_setlen(buf,data_len + 4);
103
/******************************************************************************
104
Generic code for client and server.
105
NTLM encrypt an outgoing buffer. Return the encrypted pointer in ppbuf_out.
106
Abartlett tells me that SSPI puts the signature first before the encrypted
107
output, so do the same for compatibility.
108
******************************************************************************/
110
NTSTATUS common_ntlm_encrypt_buffer(NTLMSSP_STATE *ntlmssp_state,
117
size_t data_len = smb_len(buf) - 4; /* Ignore the 0xFF SMB bytes. */
123
return NT_STATUS_BUFFER_TOO_SMALL;
127
* We know smb_len can't return a value > 128k, so no int overflow
131
buf_out = SMB_XMALLOC_ARRAY(char, 8 + NTLMSSP_SIG_SIZE + data_len);
133
/* Copy the data from the original buffer. */
135
memcpy(buf_out + 8 + NTLMSSP_SIG_SIZE, buf + 8, data_len);
137
smb_set_enclen(buf_out, smb_len(buf) + NTLMSSP_SIG_SIZE, enc_ctx_num);
141
status = ntlmssp_seal_packet(ntlmssp_state,
142
(unsigned char *)buf_out + 8 + NTLMSSP_SIG_SIZE, /* 4 byte len + 0xFF 'S' <enc> <ctx> */
144
(unsigned char *)buf_out + 8 + NTLMSSP_SIG_SIZE,
148
if (!NT_STATUS_IS_OK(status)) {
149
data_blob_free(&sig);
154
/* First 16 data bytes are signature for SSPI compatibility. */
155
memcpy(buf_out + 8, sig.data, NTLMSSP_SIG_SIZE);
156
data_blob_free(&sig);
157
*ppbuf_out = buf_out;
161
/******************************************************************************
162
Generic code for client and server.
163
gss-api decrypt an incoming buffer. We insist that the size of the
164
unwrapped buffer must be smaller or identical to the incoming buffer.
165
******************************************************************************/
167
#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
168
static NTSTATUS common_gss_decrypt_buffer(struct smb_tran_enc_state_gss *gss_state, char *buf)
170
gss_ctx_id_t gss_ctx = gss_state->gss_ctx;
174
gss_buffer_desc in_buf, out_buf;
175
size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */
178
return NT_STATUS_BUFFER_TOO_SMALL;
181
in_buf.value = buf + 8;
182
in_buf.length = buf_len - 8;
184
ret = gss_unwrap(&minor,
188
&flags_got, /* did we get sign+seal ? */
191
if (ret != GSS_S_COMPLETE) {
192
ADS_STATUS adss = ADS_ERROR_GSS(ret, minor);
193
DEBUG(0,("common_gss_encrypt_buffer: gss_unwrap failed. Error %s\n",
195
return map_nt_error_from_gss(ret, minor);
198
if (out_buf.length > in_buf.length) {
199
DEBUG(0,("common_gss_encrypt_buffer: gss_unwrap size (%u) too large (%u) !\n",
200
(unsigned int)out_buf.length,
201
(unsigned int)in_buf.length ));
202
gss_release_buffer(&minor, &out_buf);
203
return NT_STATUS_INVALID_PARAMETER;
206
memcpy(buf + 8, out_buf.value, out_buf.length);
207
/* Reset the length and overwrite the header. */
208
smb_setlen(buf, out_buf.length + 4);
210
gss_release_buffer(&minor, &out_buf);
214
/******************************************************************************
215
Generic code for client and server.
216
gss-api encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
217
******************************************************************************/
219
static NTSTATUS common_gss_encrypt_buffer(struct smb_tran_enc_state_gss *gss_state,
224
gss_ctx_id_t gss_ctx = gss_state->gss_ctx;
228
gss_buffer_desc in_buf, out_buf;
229
size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */
234
return NT_STATUS_BUFFER_TOO_SMALL;
237
in_buf.value = buf + 8;
238
in_buf.length = buf_len - 8;
240
ret = gss_wrap(&minor,
242
true, /* we want sign+seal. */
245
&flags_got, /* did we get sign+seal ? */
248
if (ret != GSS_S_COMPLETE) {
249
ADS_STATUS adss = ADS_ERROR_GSS(ret, minor);
250
DEBUG(0,("common_gss_encrypt_buffer: gss_wrap failed. Error %s\n",
252
return map_nt_error_from_gss(ret, minor);
256
/* Sign+seal not supported. */
257
gss_release_buffer(&minor, &out_buf);
258
return NT_STATUS_NOT_SUPPORTED;
261
/* Ya see - this is why I *hate* gss-api. I don't
262
* want to have to malloc another buffer of the
263
* same size + 8 bytes just to get a continuous
264
* header + buffer, but gss won't let me pass in
265
* a pre-allocated buffer. Bastards (and you know
266
* who you are....). I might fix this by
267
* going to "encrypt_and_send" passing in a file
268
* descriptor and doing scatter-gather write with
269
* TCP cork on Linux. But I shouldn't have to
273
*ppbuf_out = (char *)SMB_MALLOC(out_buf.length + 8); /* We know this can't wrap. */
275
gss_release_buffer(&minor, &out_buf);
276
return NT_STATUS_NO_MEMORY;
279
memcpy(*ppbuf_out+8, out_buf.value, out_buf.length);
280
smb_set_enclen(*ppbuf_out, out_buf.length + 4, enc_ctx_num);
282
gss_release_buffer(&minor, &out_buf);
287
/******************************************************************************
288
Generic code for client and server.
289
Encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
290
******************************************************************************/
292
NTSTATUS common_encrypt_buffer(struct smb_trans_enc_state *es, char *buffer, char **buf_out)
294
if (!common_encryption_on(es)) {
295
/* Not encrypting. */
300
switch (es->smb_enc_type) {
301
case SMB_TRANS_ENC_NTLM:
302
return common_ntlm_encrypt_buffer(es->s.ntlmssp_state, es->enc_ctx_num, buffer, buf_out);
303
#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
304
case SMB_TRANS_ENC_GSS:
305
return common_gss_encrypt_buffer(es->s.gss_state, es->enc_ctx_num, buffer, buf_out);
308
return NT_STATUS_NOT_SUPPORTED;
312
/******************************************************************************
313
Generic code for client and server.
314
Decrypt an incoming SMB buffer. Replaces the data within it.
315
New data must be less than or equal to the current length.
316
******************************************************************************/
318
NTSTATUS common_decrypt_buffer(struct smb_trans_enc_state *es, char *buf)
320
if (!common_encryption_on(es)) {
321
/* Not decrypting. */
325
switch (es->smb_enc_type) {
326
case SMB_TRANS_ENC_NTLM:
327
return common_ntlm_decrypt_buffer(es->s.ntlmssp_state, buf);
328
#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
329
case SMB_TRANS_ENC_GSS:
330
return common_gss_decrypt_buffer(es->s.gss_state, buf);
333
return NT_STATUS_NOT_SUPPORTED;
337
#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
338
/******************************************************************************
339
Shutdown a gss encryption state.
340
******************************************************************************/
342
static void common_free_gss_state(struct smb_tran_enc_state_gss **pp_gss_state)
345
struct smb_tran_enc_state_gss *gss_state = *pp_gss_state;
347
if (gss_state->creds != GSS_C_NO_CREDENTIAL) {
348
gss_release_cred(&minor, &gss_state->creds);
350
if (gss_state->gss_ctx != GSS_C_NO_CONTEXT) {
351
gss_delete_sec_context(&minor, &gss_state->gss_ctx, NULL);
353
SAFE_FREE(*pp_gss_state);
357
/******************************************************************************
358
Shutdown an encryption state.
359
******************************************************************************/
361
void common_free_encryption_state(struct smb_trans_enc_state **pp_es)
363
struct smb_trans_enc_state *es = *pp_es;
369
if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
370
if (es->s.ntlmssp_state) {
371
ntlmssp_end(&es->s.ntlmssp_state);
374
#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
375
if (es->smb_enc_type == SMB_TRANS_ENC_GSS) {
376
/* Free the gss context handle. */
377
if (es->s.gss_state) {
378
common_free_gss_state(&es->s.gss_state);
386
/******************************************************************************
387
Free an encryption-allocated buffer.
388
******************************************************************************/
390
void common_free_enc_buffer(struct smb_trans_enc_state *es, char *buf)
392
uint16_t enc_ctx_num;
394
if (!common_encryption_on(es)) {
398
if (!NT_STATUS_IS_OK(get_enc_ctx_num((const uint8_t *)buf,
403
if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
408
#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
409
if (es->smb_enc_type == SMB_TRANS_ENC_GSS) {
411
gss_buffer_desc rel_buf;
413
rel_buf.length = smb_len(buf) + 4;
414
gss_release_buffer(&min, &rel_buf);
419
/******************************************************************************
420
Client side encryption.
421
******************************************************************************/
423
/******************************************************************************
424
Is client encryption on ?
425
******************************************************************************/
427
bool cli_encryption_on(struct cli_state *cli)
429
/* If we supported multiple encrytion contexts
430
* here we'd look up based on tid.
432
return common_encryption_on(cli->trans_enc_state);
435
/******************************************************************************
436
Shutdown a client encryption state.
437
******************************************************************************/
439
void cli_free_encryption_context(struct cli_state *cli)
441
common_free_encryption_state(&cli->trans_enc_state);
444
/******************************************************************************
445
Free an encryption-allocated buffer.
446
******************************************************************************/
448
void cli_free_enc_buffer(struct cli_state *cli, char *buf)
450
/* We know this is an smb buffer, and we
451
* didn't malloc, only copy, for a keepalive,
452
* so ignore non-session messages. */
458
/* If we supported multiple encrytion contexts
459
* here we'd look up based on tid.
461
common_free_enc_buffer(cli->trans_enc_state, buf);
464
/******************************************************************************
465
Decrypt an incoming buffer.
466
******************************************************************************/
468
NTSTATUS cli_decrypt_message(struct cli_state *cli)
473
/* Ignore non-session messages. */
474
if(CVAL(cli->inbuf,0)) {
478
status = get_enc_ctx_num((const uint8_t *)cli->inbuf, &enc_ctx_num);
479
if (!NT_STATUS_IS_OK(status)) {
483
if (enc_ctx_num != cli->trans_enc_state->enc_ctx_num) {
484
return NT_STATUS_INVALID_HANDLE;
487
return common_decrypt_buffer(cli->trans_enc_state, cli->inbuf);
490
/******************************************************************************
491
Encrypt an outgoing buffer. Return the encrypted pointer in buf_out.
492
******************************************************************************/
494
NTSTATUS cli_encrypt_message(struct cli_state *cli, char *buf, char **buf_out)
496
/* Ignore non-session messages. */
501
/* If we supported multiple encrytion contexts
502
* here we'd look up based on tid.
504
return common_encrypt_buffer(cli->trans_enc_state, buf, buf_out);