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/>.
21 #include "../auth/ntlmssp/ntlmssp.h"
22 #include "smb_crypt.h"
23 #include "libsmb/libsmb.h"
24 #include "ntlmssp_wrap.h"
27 /******************************************************************************
28 Pull out the encryption context for this packet. 0 means global context.
29 ******************************************************************************/
31 NTSTATUS get_enc_ctx_num(const uint8_t *buf, uint16 *p_enc_ctx_num)
33 if (smb_len(buf) < 8) {
34 return NT_STATUS_INVALID_BUFFER_SIZE;
38 if (buf[5] == 'S' && buf [6] == 'M' && buf[7] == 'B') {
39 /* Not an encrypted buffer. */
40 return NT_STATUS_NOT_FOUND;
43 *p_enc_ctx_num = SVAL(buf,6);
47 return NT_STATUS_INVALID_NETWORK_RESPONSE;
50 /******************************************************************************
51 Generic code for client and server.
52 Is encryption turned on ?
53 ******************************************************************************/
55 bool common_encryption_on(struct smb_trans_enc_state *es)
57 return ((es != NULL) && es->enc_on);
60 /******************************************************************************
61 Generic code for client and server.
62 NTLM decrypt an incoming buffer.
63 Abartlett tells me that SSPI puts the signature first before the encrypted
64 output, so cope with the same for compatibility.
65 ******************************************************************************/
67 NTSTATUS common_ntlm_decrypt_buffer(struct auth_ntlmssp_state *auth_ntlmssp_state, char *buf)
70 size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */
75 if (buf_len < 8 + NTLMSSP_SIG_SIZE) {
76 return NT_STATUS_BUFFER_TOO_SMALL;
79 inbuf = (char *)smb_xmemdup(buf, buf_len);
81 /* Adjust for the signature. */
82 data_len = buf_len - 8 - NTLMSSP_SIG_SIZE;
84 /* Point at the signature. */
85 sig = data_blob_const(inbuf+8, NTLMSSP_SIG_SIZE);
87 status = auth_ntlmssp_unseal_packet(auth_ntlmssp_state,
88 (unsigned char *)inbuf + 8 + NTLMSSP_SIG_SIZE, /* 4 byte len + 0xFF 'E' <enc> <ctx> */
90 (unsigned char *)inbuf + 8 + NTLMSSP_SIG_SIZE,
94 if (!NT_STATUS_IS_OK(status)) {
99 memcpy(buf + 8, inbuf + 8 + NTLMSSP_SIG_SIZE, data_len);
101 /* Reset the length and overwrite the header. */
102 smb_setlen(buf,data_len + 4);
108 /******************************************************************************
109 Generic code for client and server.
110 NTLM encrypt an outgoing buffer. Return the encrypted pointer in ppbuf_out.
111 Abartlett tells me that SSPI puts the signature first before the encrypted
112 output, so do the same for compatibility.
113 ******************************************************************************/
115 NTSTATUS common_ntlm_encrypt_buffer(struct auth_ntlmssp_state *auth_ntlmssp_state,
122 size_t data_len = smb_len(buf) - 4; /* Ignore the 0xFF SMB bytes. */
128 return NT_STATUS_BUFFER_TOO_SMALL;
131 frame = talloc_stackframe();
133 * We know smb_len can't return a value > 128k, so no int overflow
137 buf_out = SMB_XMALLOC_ARRAY(char, 8 + NTLMSSP_SIG_SIZE + data_len);
139 /* Copy the data from the original buffer. */
141 memcpy(buf_out + 8 + NTLMSSP_SIG_SIZE, buf + 8, data_len);
143 smb_set_enclen(buf_out, smb_len(buf) + NTLMSSP_SIG_SIZE, enc_ctx_num);
147 status = auth_ntlmssp_seal_packet(auth_ntlmssp_state,
149 (unsigned char *)buf_out + 8 + NTLMSSP_SIG_SIZE, /* 4 byte len + 0xFF 'S' <enc> <ctx> */
151 (unsigned char *)buf_out + 8 + NTLMSSP_SIG_SIZE,
155 if (!NT_STATUS_IS_OK(status)) {
161 /* First 16 data bytes are signature for SSPI compatibility. */
162 memcpy(buf_out + 8, sig.data, NTLMSSP_SIG_SIZE);
164 *ppbuf_out = buf_out;
168 /******************************************************************************
169 Generic code for client and server.
170 gss-api decrypt an incoming buffer. We insist that the size of the
171 unwrapped buffer must be smaller or identical to the incoming buffer.
172 ******************************************************************************/
174 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
175 static NTSTATUS common_gss_decrypt_buffer(struct smb_tran_enc_state_gss *gss_state, char *buf)
177 gss_ctx_id_t gss_ctx = gss_state->gss_ctx;
181 gss_buffer_desc in_buf, out_buf;
182 size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */
185 return NT_STATUS_BUFFER_TOO_SMALL;
188 in_buf.value = buf + 8;
189 in_buf.length = buf_len - 8;
191 ret = gss_unwrap(&minor,
195 &flags_got, /* did we get sign+seal ? */
198 if (ret != GSS_S_COMPLETE) {
199 ADS_STATUS adss = ADS_ERROR_GSS(ret, minor);
200 DEBUG(0,("common_gss_encrypt_buffer: gss_unwrap failed. Error %s\n",
202 return map_nt_error_from_gss(ret, minor);
205 if (out_buf.length > in_buf.length) {
206 DEBUG(0,("common_gss_encrypt_buffer: gss_unwrap size (%u) too large (%u) !\n",
207 (unsigned int)out_buf.length,
208 (unsigned int)in_buf.length ));
209 gss_release_buffer(&minor, &out_buf);
210 return NT_STATUS_INVALID_PARAMETER;
213 memcpy(buf + 8, out_buf.value, out_buf.length);
214 /* Reset the length and overwrite the header. */
215 smb_setlen(buf, out_buf.length + 4);
217 gss_release_buffer(&minor, &out_buf);
221 /******************************************************************************
222 Generic code for client and server.
223 gss-api encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
224 ******************************************************************************/
226 static NTSTATUS common_gss_encrypt_buffer(struct smb_tran_enc_state_gss *gss_state,
231 gss_ctx_id_t gss_ctx = gss_state->gss_ctx;
235 gss_buffer_desc in_buf, out_buf;
236 size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */
241 return NT_STATUS_BUFFER_TOO_SMALL;
244 in_buf.value = buf + 8;
245 in_buf.length = buf_len - 8;
247 ret = gss_wrap(&minor,
249 true, /* we want sign+seal. */
252 &flags_got, /* did we get sign+seal ? */
255 if (ret != GSS_S_COMPLETE) {
256 ADS_STATUS adss = ADS_ERROR_GSS(ret, minor);
257 DEBUG(0,("common_gss_encrypt_buffer: gss_wrap failed. Error %s\n",
259 return map_nt_error_from_gss(ret, minor);
263 /* Sign+seal not supported. */
264 gss_release_buffer(&minor, &out_buf);
265 return NT_STATUS_NOT_SUPPORTED;
268 /* Ya see - this is why I *hate* gss-api. I don't
269 * want to have to malloc another buffer of the
270 * same size + 8 bytes just to get a continuous
271 * header + buffer, but gss won't let me pass in
272 * a pre-allocated buffer. Bastards (and you know
273 * who you are....). I might fix this by
274 * going to "encrypt_and_send" passing in a file
275 * descriptor and doing scatter-gather write with
276 * TCP cork on Linux. But I shouldn't have to
280 *ppbuf_out = (char *)SMB_MALLOC(out_buf.length + 8); /* We know this can't wrap. */
282 gss_release_buffer(&minor, &out_buf);
283 return NT_STATUS_NO_MEMORY;
286 memcpy(*ppbuf_out+8, out_buf.value, out_buf.length);
287 smb_set_enclen(*ppbuf_out, out_buf.length + 4, enc_ctx_num);
289 gss_release_buffer(&minor, &out_buf);
294 /******************************************************************************
295 Generic code for client and server.
296 Encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
297 ******************************************************************************/
299 NTSTATUS common_encrypt_buffer(struct smb_trans_enc_state *es, char *buffer, char **buf_out)
301 if (!common_encryption_on(es)) {
302 /* Not encrypting. */
307 switch (es->smb_enc_type) {
308 case SMB_TRANS_ENC_NTLM:
309 return common_ntlm_encrypt_buffer(es->s.auth_ntlmssp_state, es->enc_ctx_num, buffer, buf_out);
310 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
311 case SMB_TRANS_ENC_GSS:
312 return common_gss_encrypt_buffer(es->s.gss_state, es->enc_ctx_num, buffer, buf_out);
315 return NT_STATUS_NOT_SUPPORTED;
319 /******************************************************************************
320 Generic code for client and server.
321 Decrypt an incoming SMB buffer. Replaces the data within it.
322 New data must be less than or equal to the current length.
323 ******************************************************************************/
325 NTSTATUS common_decrypt_buffer(struct smb_trans_enc_state *es, char *buf)
327 if (!common_encryption_on(es)) {
328 /* Not decrypting. */
332 switch (es->smb_enc_type) {
333 case SMB_TRANS_ENC_NTLM:
334 return common_ntlm_decrypt_buffer(es->s.auth_ntlmssp_state, buf);
335 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
336 case SMB_TRANS_ENC_GSS:
337 return common_gss_decrypt_buffer(es->s.gss_state, buf);
340 return NT_STATUS_NOT_SUPPORTED;
344 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
345 /******************************************************************************
346 Shutdown a gss encryption state.
347 ******************************************************************************/
349 static void common_free_gss_state(struct smb_tran_enc_state_gss **pp_gss_state)
352 struct smb_tran_enc_state_gss *gss_state = *pp_gss_state;
354 if (gss_state->creds != GSS_C_NO_CREDENTIAL) {
355 gss_release_cred(&minor, &gss_state->creds);
357 if (gss_state->gss_ctx != GSS_C_NO_CONTEXT) {
358 gss_delete_sec_context(&minor, &gss_state->gss_ctx, NULL);
360 SAFE_FREE(*pp_gss_state);
364 /******************************************************************************
365 Shutdown an encryption state.
366 ******************************************************************************/
368 void common_free_encryption_state(struct smb_trans_enc_state **pp_es)
370 struct smb_trans_enc_state *es = *pp_es;
376 if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
377 if (es->s.auth_ntlmssp_state) {
378 TALLOC_FREE(es->s.auth_ntlmssp_state);
381 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
382 if (es->smb_enc_type == SMB_TRANS_ENC_GSS) {
383 /* Free the gss context handle. */
384 if (es->s.gss_state) {
385 common_free_gss_state(&es->s.gss_state);
393 /******************************************************************************
394 Free an encryption-allocated buffer.
395 ******************************************************************************/
397 void common_free_enc_buffer(struct smb_trans_enc_state *es, char *buf)
399 uint16_t enc_ctx_num;
401 if (!common_encryption_on(es)) {
405 if (!NT_STATUS_IS_OK(get_enc_ctx_num((const uint8_t *)buf,
410 if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
415 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
416 if (es->smb_enc_type == SMB_TRANS_ENC_GSS) {
418 gss_buffer_desc rel_buf;
420 rel_buf.length = smb_len(buf) + 4;
421 gss_release_buffer(&min, &rel_buf);