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 #include "smb_common.h"
22 #ifdef HAVE_KRB5
23 #include "lib/krb5_wrap/krb5_samba.h"
24 #endif
25 #include "auth/gensec/gensec.h"
26 #include "libcli/smb/smb_seal.h"
27 
28 #undef malloc
29 
30 /******************************************************************************
31  Pull out the encryption context for this packet. 0 means global context.
32 ******************************************************************************/
33 
get_enc_ctx_num(const uint8_t * buf,uint16_t * p_enc_ctx_num)34 NTSTATUS get_enc_ctx_num(const uint8_t *buf, uint16_t *p_enc_ctx_num)
35 {
36 	if (smb_len_nbt(buf) < 8) {
37 		return NT_STATUS_INVALID_BUFFER_SIZE;
38 	}
39 
40 	if (buf[4] == 0xFF) {
41 		if (buf[5] == 'S' && buf [6] == 'M' && buf[7] == 'B') {
42 			/* Not an encrypted buffer. */
43 			return NT_STATUS_NOT_FOUND;
44 		}
45 		if (buf[5] == 'E') {
46 			*p_enc_ctx_num = SVAL(buf,6);
47 			return NT_STATUS_OK;
48 		}
49 	}
50 	return NT_STATUS_INVALID_NETWORK_RESPONSE;
51 }
52 
53 /*******************************************************************
54  Set the length and marker of an encrypted smb packet.
55 ********************************************************************/
56 
smb_set_enclen(char * buf,int len,uint16_t enc_ctx_num)57 static void smb_set_enclen(char *buf,int len,uint16_t enc_ctx_num)
58 {
59 	_smb_setlen_tcp(buf,len);
60 
61 	SCVAL(buf,4,0xFF);
62 	SCVAL(buf,5,'E');
63 	SSVAL(buf,6,enc_ctx_num);
64 }
65 
66 /******************************************************************************
67  Generic code for client and server.
68  Is encryption turned on ?
69 ******************************************************************************/
70 
common_encryption_on(struct smb_trans_enc_state * es)71 bool common_encryption_on(struct smb_trans_enc_state *es)
72 {
73 	return ((es != NULL) && es->enc_on);
74 }
75 
76 /******************************************************************************
77  Generic code for client and server.
78  GENSEC decrypt an incoming buffer.
79 ******************************************************************************/
80 
common_gensec_decrypt_buffer(struct gensec_security * gensec,char * buf)81 static NTSTATUS common_gensec_decrypt_buffer(struct gensec_security *gensec,
82 					     char *buf)
83 {
84 	NTSTATUS status;
85 	size_t buf_len = smb_len_nbt(buf) + 4; /* Don't forget the 4 length bytes. */
86 	DATA_BLOB in_buf, out_buf;
87 	TALLOC_CTX *frame;
88 
89 	if (buf_len < 8) {
90 		return NT_STATUS_BUFFER_TOO_SMALL;
91 	}
92 
93 	frame = talloc_stackframe();
94 
95 	in_buf = data_blob_const(buf + 8, buf_len - 8);
96 
97 	status = gensec_unwrap(gensec, frame, &in_buf, &out_buf);
98 
99 	if (!NT_STATUS_IS_OK(status)) {
100 		DEBUG(0,("common_gensec_decrypt_buffer: gensec_unwrap failed. Error %s\n",
101 			 nt_errstr(status)));
102 		TALLOC_FREE(frame);
103 		return status;
104 	}
105 
106 	if (out_buf.length > in_buf.length) {
107 		DEBUG(0,("common_gensec_decrypt_buffer: gensec_unwrap size (%u) too large (%u) !\n",
108 			(unsigned int)out_buf.length,
109 			(unsigned int)in_buf.length ));
110 		TALLOC_FREE(frame);
111 		return NT_STATUS_INVALID_PARAMETER;
112 	}
113 
114 	memcpy(buf + 8, out_buf.data, out_buf.length);
115 
116 	/* Reset the length and overwrite the header. */
117 	smb_setlen_nbt(buf, out_buf.length + 4);
118 
119 	TALLOC_FREE(frame);
120 
121 	return NT_STATUS_OK;
122 }
123 
124 /******************************************************************************
125  Generic code for client and server.
126  NTLM encrypt an outgoing buffer. Return the encrypted pointer in ppbuf_out.
127 ******************************************************************************/
128 
common_gensec_encrypt_buffer(struct gensec_security * gensec,uint16_t enc_ctx_num,char * buf,char ** ppbuf_out)129 static NTSTATUS common_gensec_encrypt_buffer(struct gensec_security *gensec,
130 				      uint16_t enc_ctx_num,
131 				      char *buf,
132 				      char **ppbuf_out)
133 {
134 	NTSTATUS status;
135 	DATA_BLOB in_buf, out_buf;
136 	size_t buf_len = smb_len_nbt(buf) + 4; /* Don't forget the 4 length bytes. */
137 	TALLOC_CTX *frame;
138 
139 	*ppbuf_out = NULL;
140 
141 	if (buf_len < 8) {
142 		return NT_STATUS_BUFFER_TOO_SMALL;
143 	}
144 	in_buf = data_blob_const(buf + 8, buf_len - 8);
145 
146 	frame = talloc_stackframe();
147 
148 	status = gensec_wrap(gensec, frame, &in_buf, &out_buf);
149 	if (!NT_STATUS_IS_OK(status)) {
150 		DEBUG(0,("common_gensec_encrypt_buffer: gensec_wrap failed. Error %s\n",
151 			 nt_errstr(status)));
152 		TALLOC_FREE(frame);
153 		return status;
154 	}
155 
156 	*ppbuf_out = (char *)malloc(out_buf.length + 8); /* We know this can't wrap. */
157 	if (!*ppbuf_out) {
158 		TALLOC_FREE(frame);
159 		return NT_STATUS_NO_MEMORY;
160 	}
161 
162 	memcpy(*ppbuf_out+8, out_buf.data, out_buf.length);
163 	smb_set_enclen(*ppbuf_out, out_buf.length + 4, enc_ctx_num);
164 
165 	TALLOC_FREE(frame);
166 
167 	return NT_STATUS_OK;
168 }
169 
170 /******************************************************************************
171  Generic code for client and server.
172  Encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
173 ******************************************************************************/
174 
common_encrypt_buffer(struct smb_trans_enc_state * es,char * buffer,char ** buf_out)175 NTSTATUS common_encrypt_buffer(struct smb_trans_enc_state *es, char *buffer, char **buf_out)
176 {
177 	if (!common_encryption_on(es)) {
178 		/* Not encrypting. */
179 		*buf_out = buffer;
180 		return NT_STATUS_OK;
181 	}
182 
183 	return common_gensec_encrypt_buffer(es->gensec_security, es->enc_ctx_num, buffer, buf_out);
184 }
185 
186 /******************************************************************************
187  Generic code for client and server.
188  Decrypt an incoming SMB buffer. Replaces the data within it.
189  New data must be less than or equal to the current length.
190 ******************************************************************************/
191 
common_decrypt_buffer(struct smb_trans_enc_state * es,char * buf)192 NTSTATUS common_decrypt_buffer(struct smb_trans_enc_state *es, char *buf)
193 {
194 	if (!common_encryption_on(es)) {
195 		/* Not decrypting. */
196 		return NT_STATUS_OK;
197 	}
198 
199 	return common_gensec_decrypt_buffer(es->gensec_security, buf);
200 }
201 
202 /******************************************************************************
203  Free an encryption-allocated buffer.
204 ******************************************************************************/
205 
common_free_enc_buffer(struct smb_trans_enc_state * es,char * buf)206 void common_free_enc_buffer(struct smb_trans_enc_state *es, char *buf)
207 {
208 	uint16_t enc_ctx_num;
209 
210 	if (!common_encryption_on(es)) {
211 		return;
212 	}
213 
214 	if (!NT_STATUS_IS_OK(get_enc_ctx_num((const uint8_t *)buf,
215 			&enc_ctx_num))) {
216 		return;
217 	}
218 
219 	SAFE_FREE(buf);
220 }
221