1/*
2   Unix SMB/CIFS implementation.
3   SMB Transport encryption (sealing) code.
4   Copyright (C) Jeremy Allison 2007.
5
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.
10
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.
15
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/>.
18*/
19
20#include "includes.h"
21
22/******************************************************************************
23 Pull out the encryption context for this packet. 0 means global context.
24******************************************************************************/
25
26NTSTATUS get_enc_ctx_num(const uint8_t *buf, uint16 *p_enc_ctx_num)
27{
28	if (smb_len(buf) < 8) {
29		return NT_STATUS_INVALID_BUFFER_SIZE;
30	}
31
32	if (buf[4] == 0xFF) {
33		if (buf[5] == 'S' && buf [6] == 'M' && buf[7] == 'B') {
34			/* Not an encrypted buffer. */
35			return NT_STATUS_NOT_FOUND;
36		}
37		if (buf[5] == 'E') {
38			*p_enc_ctx_num = SVAL(buf,6);
39			return NT_STATUS_OK;
40		}
41	}
42	return NT_STATUS_INVALID_NETWORK_RESPONSE;
43}
44
45/******************************************************************************
46 Generic code for client and server.
47 Is encryption turned on ?
48******************************************************************************/
49
50bool common_encryption_on(struct smb_trans_enc_state *es)
51{
52	return ((es != NULL) && es->enc_on);
53}
54
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******************************************************************************/
61
62NTSTATUS common_ntlm_decrypt_buffer(NTLMSSP_STATE *ntlmssp_state, char *buf)
63{
64	NTSTATUS status;
65	size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */
66	size_t data_len;
67	char *inbuf;
68	DATA_BLOB sig;
69
70	if (buf_len < 8 + NTLMSSP_SIG_SIZE) {
71		return NT_STATUS_BUFFER_TOO_SMALL;
72	}
73
74	inbuf = (char *)smb_xmemdup(buf, buf_len);
75
76	/* Adjust for the signature. */
77	data_len = buf_len - 8 - NTLMSSP_SIG_SIZE;
78
79	/* Point at the signature. */
80	sig = data_blob_const(inbuf+8, NTLMSSP_SIG_SIZE);
81
82	status = ntlmssp_unseal_packet(ntlmssp_state,
83		(unsigned char *)inbuf + 8 + NTLMSSP_SIG_SIZE, /* 4 byte len + 0xFF 'E' <enc> <ctx> */
84		data_len,
85		(unsigned char *)inbuf + 8 + NTLMSSP_SIG_SIZE,
86		data_len,
87		&sig);
88
89	if (!NT_STATUS_IS_OK(status)) {
90		SAFE_FREE(inbuf);
91		return status;
92	}
93
94	memcpy(buf + 8, inbuf + 8 + NTLMSSP_SIG_SIZE, data_len);
95
96	/* Reset the length and overwrite the header. */
97	smb_setlen(buf,data_len + 4);
98
99	SAFE_FREE(inbuf);
100	return NT_STATUS_OK;
101}
102
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******************************************************************************/
109
110NTSTATUS common_ntlm_encrypt_buffer(NTLMSSP_STATE *ntlmssp_state,
111				uint16 enc_ctx_num,
112				char *buf,
113				char **ppbuf_out)
114{
115	NTSTATUS status;
116	char *buf_out;
117	size_t data_len = smb_len(buf) - 4; /* Ignore the 0xFF SMB bytes. */
118	DATA_BLOB sig;
119
120	*ppbuf_out = NULL;
121
122	if (data_len == 0) {
123		return NT_STATUS_BUFFER_TOO_SMALL;
124	}
125
126	/*
127	 * We know smb_len can't return a value > 128k, so no int overflow
128	 * check needed.
129	 */
130
131	buf_out = SMB_XMALLOC_ARRAY(char, 8 + NTLMSSP_SIG_SIZE + data_len);
132
133	/* Copy the data from the original buffer. */
134
135	memcpy(buf_out + 8 + NTLMSSP_SIG_SIZE, buf + 8, data_len);
136
137	smb_set_enclen(buf_out, smb_len(buf) + NTLMSSP_SIG_SIZE, enc_ctx_num);
138
139	ZERO_STRUCT(sig);
140
141	status = ntlmssp_seal_packet(ntlmssp_state,
142		(unsigned char *)buf_out + 8 + NTLMSSP_SIG_SIZE, /* 4 byte len + 0xFF 'S' <enc> <ctx> */
143		data_len,
144		(unsigned char *)buf_out + 8 + NTLMSSP_SIG_SIZE,
145		data_len,
146		&sig);
147
148	if (!NT_STATUS_IS_OK(status)) {
149		data_blob_free(&sig);
150		SAFE_FREE(buf_out);
151		return status;
152	}
153
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;
158	return NT_STATUS_OK;
159}
160
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******************************************************************************/
166
167#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
168static NTSTATUS common_gss_decrypt_buffer(struct smb_tran_enc_state_gss *gss_state, char *buf)
169{
170	gss_ctx_id_t gss_ctx = gss_state->gss_ctx;
171	OM_uint32 ret = 0;
172	OM_uint32 minor = 0;
173	int flags_got = 0;
174	gss_buffer_desc in_buf, out_buf;
175	size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */
176
177	if (buf_len < 8) {
178		return NT_STATUS_BUFFER_TOO_SMALL;
179	}
180
181	in_buf.value = buf + 8;
182	in_buf.length = buf_len - 8;
183
184	ret = gss_unwrap(&minor,
185			gss_ctx,
186			&in_buf,
187			&out_buf,
188			&flags_got,		/* did we get sign+seal ? */
189			(gss_qop_t *) NULL);
190
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",
194			ads_errstr(adss) ));
195		return map_nt_error_from_gss(ret, minor);
196	}
197
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;
204	}
205
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);
209
210	gss_release_buffer(&minor, &out_buf);
211	return NT_STATUS_OK;
212}
213
214/******************************************************************************
215 Generic code for client and server.
216 gss-api encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
217******************************************************************************/
218
219static NTSTATUS common_gss_encrypt_buffer(struct smb_tran_enc_state_gss *gss_state,
220					uint16 enc_ctx_num,
221		 			char *buf,
222					char **ppbuf_out)
223{
224	gss_ctx_id_t gss_ctx = gss_state->gss_ctx;
225	OM_uint32 ret = 0;
226	OM_uint32 minor = 0;
227	int flags_got = 0;
228	gss_buffer_desc in_buf, out_buf;
229	size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */
230
231	*ppbuf_out = NULL;
232
233	if (buf_len < 8) {
234		return NT_STATUS_BUFFER_TOO_SMALL;
235	}
236
237	in_buf.value = buf + 8;
238	in_buf.length = buf_len - 8;
239
240	ret = gss_wrap(&minor,
241			gss_ctx,
242			true,			/* we want sign+seal. */
243			GSS_C_QOP_DEFAULT,
244			&in_buf,
245			&flags_got,		/* did we get sign+seal ? */
246			&out_buf);
247
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",
251			ads_errstr(adss) ));
252		return map_nt_error_from_gss(ret, minor);
253	}
254
255	if (!flags_got) {
256		/* Sign+seal not supported. */
257		gss_release_buffer(&minor, &out_buf);
258		return NT_STATUS_NOT_SUPPORTED;
259	}
260
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
270	 * bother :-*(. JRA.
271	 */
272
273	*ppbuf_out = (char *)SMB_MALLOC(out_buf.length + 8); /* We know this can't wrap. */
274	if (!*ppbuf_out) {
275		gss_release_buffer(&minor, &out_buf);
276		return NT_STATUS_NO_MEMORY;
277	}
278
279	memcpy(*ppbuf_out+8, out_buf.value, out_buf.length);
280	smb_set_enclen(*ppbuf_out, out_buf.length + 4, enc_ctx_num);
281
282	gss_release_buffer(&minor, &out_buf);
283	return NT_STATUS_OK;
284}
285#endif
286
287/******************************************************************************
288 Generic code for client and server.
289 Encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
290******************************************************************************/
291
292NTSTATUS common_encrypt_buffer(struct smb_trans_enc_state *es, char *buffer, char **buf_out)
293{
294	if (!common_encryption_on(es)) {
295		/* Not encrypting. */
296		*buf_out = buffer;
297		return NT_STATUS_OK;
298	}
299
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);
306#endif
307		default:
308			return NT_STATUS_NOT_SUPPORTED;
309	}
310}
311
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******************************************************************************/
317
318NTSTATUS common_decrypt_buffer(struct smb_trans_enc_state *es, char *buf)
319{
320	if (!common_encryption_on(es)) {
321		/* Not decrypting. */
322		return NT_STATUS_OK;
323	}
324
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);
331#endif
332		default:
333			return NT_STATUS_NOT_SUPPORTED;
334	}
335}
336
337#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
338/******************************************************************************
339 Shutdown a gss encryption state.
340******************************************************************************/
341
342static void common_free_gss_state(struct smb_tran_enc_state_gss **pp_gss_state)
343{
344	OM_uint32 minor = 0;
345	struct smb_tran_enc_state_gss *gss_state = *pp_gss_state;
346
347	if (gss_state->creds != GSS_C_NO_CREDENTIAL) {
348		gss_release_cred(&minor, &gss_state->creds);
349	}
350	if (gss_state->gss_ctx != GSS_C_NO_CONTEXT) {
351		gss_delete_sec_context(&minor, &gss_state->gss_ctx, NULL);
352	}
353	SAFE_FREE(*pp_gss_state);
354}
355#endif
356
357/******************************************************************************
358 Shutdown an encryption state.
359******************************************************************************/
360
361void common_free_encryption_state(struct smb_trans_enc_state **pp_es)
362{
363	struct smb_trans_enc_state *es = *pp_es;
364
365	if (es == NULL) {
366		return;
367	}
368
369	if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
370		if (es->s.ntlmssp_state) {
371			ntlmssp_end(&es->s.ntlmssp_state);
372		}
373	}
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);
379		}
380	}
381#endif
382	SAFE_FREE(es);
383	*pp_es = NULL;
384}
385
386/******************************************************************************
387 Free an encryption-allocated buffer.
388******************************************************************************/
389
390void common_free_enc_buffer(struct smb_trans_enc_state *es, char *buf)
391{
392	uint16_t enc_ctx_num;
393
394	if (!common_encryption_on(es)) {
395		return;
396	}
397
398	if (!NT_STATUS_IS_OK(get_enc_ctx_num((const uint8_t *)buf,
399			&enc_ctx_num))) {
400		return;
401	}
402
403	if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
404		SAFE_FREE(buf);
405		return;
406	}
407
408#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
409	if (es->smb_enc_type == SMB_TRANS_ENC_GSS) {
410		OM_uint32 min;
411		gss_buffer_desc rel_buf;
412		rel_buf.value = buf;
413		rel_buf.length = smb_len(buf) + 4;
414		gss_release_buffer(&min, &rel_buf);
415	}
416#endif
417}
418
419/******************************************************************************
420 Client side encryption.
421******************************************************************************/
422
423/******************************************************************************
424 Is client encryption on ?
425******************************************************************************/
426
427bool cli_encryption_on(struct cli_state *cli)
428{
429	/* If we supported multiple encrytion contexts
430	 * here we'd look up based on tid.
431	 */
432	return common_encryption_on(cli->trans_enc_state);
433}
434
435/******************************************************************************
436 Shutdown a client encryption state.
437******************************************************************************/
438
439void cli_free_encryption_context(struct cli_state *cli)
440{
441	common_free_encryption_state(&cli->trans_enc_state);
442}
443
444/******************************************************************************
445 Free an encryption-allocated buffer.
446******************************************************************************/
447
448void cli_free_enc_buffer(struct cli_state *cli, char *buf)
449{
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. */
453
454	if(CVAL(buf,0)) {
455		return;
456	}
457
458	/* If we supported multiple encrytion contexts
459	 * here we'd look up based on tid.
460	 */
461	common_free_enc_buffer(cli->trans_enc_state, buf);
462}
463
464/******************************************************************************
465 Decrypt an incoming buffer.
466******************************************************************************/
467
468NTSTATUS cli_decrypt_message(struct cli_state *cli)
469{
470	NTSTATUS status;
471	uint16 enc_ctx_num;
472
473	/* Ignore non-session messages. */
474	if(CVAL(cli->inbuf,0)) {
475		return NT_STATUS_OK;
476	}
477
478	status = get_enc_ctx_num((const uint8_t *)cli->inbuf, &enc_ctx_num);
479	if (!NT_STATUS_IS_OK(status)) {
480		return status;
481	}
482
483	if (enc_ctx_num != cli->trans_enc_state->enc_ctx_num) {
484		return NT_STATUS_INVALID_HANDLE;
485	}
486
487	return common_decrypt_buffer(cli->trans_enc_state, cli->inbuf);
488}
489
490/******************************************************************************
491 Encrypt an outgoing buffer. Return the encrypted pointer in buf_out.
492******************************************************************************/
493
494NTSTATUS cli_encrypt_message(struct cli_state *cli, char *buf, char **buf_out)
495{
496	/* Ignore non-session messages. */
497	if (CVAL(buf,0)) {
498		return NT_STATUS_OK;
499	}
500
501	/* If we supported multiple encrytion contexts
502	 * here we'd look up based on tid.
503	 */
504	return common_encrypt_buffer(cli->trans_enc_state, buf, buf_out);
505}
506