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