Line data Source code
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 :
34 521299 : NTSTATUS get_enc_ctx_num(const uint8_t *buf, uint16_t *p_enc_ctx_num)
35 : {
36 521299 : if (smb_len_nbt(buf) < 8) {
37 0 : return NT_STATUS_INVALID_BUFFER_SIZE;
38 : }
39 :
40 521299 : if (buf[4] == 0xFF) {
41 521299 : if (buf[5] == 'S' && buf [6] == 'M' && buf[7] == 'B') {
42 : /* Not an encrypted buffer. */
43 0 : return NT_STATUS_NOT_FOUND;
44 : }
45 521299 : if (buf[5] == 'E') {
46 521299 : *p_enc_ctx_num = SVAL(buf,6);
47 521299 : return NT_STATUS_OK;
48 : }
49 : }
50 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
51 : }
52 :
53 : /*******************************************************************
54 : Set the length and marker of an encrypted smb packet.
55 : ********************************************************************/
56 :
57 335416 : static void smb_set_enclen(char *buf,int len,uint16_t enc_ctx_num)
58 : {
59 335416 : _smb_setlen_tcp(buf,len);
60 :
61 335416 : SCVAL(buf,4,0xFF);
62 335416 : SCVAL(buf,5,'E');
63 335416 : SSVAL(buf,6,enc_ctx_num);
64 335416 : }
65 :
66 : /******************************************************************************
67 : Generic code for client and server.
68 : Is encryption turned on ?
69 : ******************************************************************************/
70 :
71 2749386 : bool common_encryption_on(struct smb_trans_enc_state *es)
72 : {
73 2749386 : return ((es != NULL) && es->enc_on);
74 : }
75 :
76 : /******************************************************************************
77 : Generic code for client and server.
78 : GENSEC decrypt an incoming buffer.
79 : ******************************************************************************/
80 :
81 335416 : static NTSTATUS common_gensec_decrypt_buffer(struct gensec_security *gensec,
82 : char *buf)
83 : {
84 0 : NTSTATUS status;
85 335416 : size_t buf_len = smb_len_nbt(buf) + 4; /* Don't forget the 4 length bytes. */
86 0 : DATA_BLOB in_buf, out_buf;
87 0 : TALLOC_CTX *frame;
88 :
89 335416 : if (buf_len < 8) {
90 0 : return NT_STATUS_BUFFER_TOO_SMALL;
91 : }
92 :
93 335416 : frame = talloc_stackframe();
94 :
95 335416 : in_buf = data_blob_const(buf + 8, buf_len - 8);
96 :
97 335416 : status = gensec_unwrap(gensec, frame, &in_buf, &out_buf);
98 :
99 335416 : if (!NT_STATUS_IS_OK(status)) {
100 0 : DEBUG(0,("common_gensec_decrypt_buffer: gensec_unwrap failed. Error %s\n",
101 : nt_errstr(status)));
102 0 : TALLOC_FREE(frame);
103 0 : return status;
104 : }
105 :
106 335416 : if (out_buf.length > in_buf.length) {
107 0 : 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 0 : TALLOC_FREE(frame);
111 0 : return NT_STATUS_INVALID_PARAMETER;
112 : }
113 :
114 335416 : memcpy(buf + 8, out_buf.data, out_buf.length);
115 :
116 : /* Reset the length and overwrite the header. */
117 335416 : smb_setlen_nbt(buf, out_buf.length + 4);
118 :
119 335416 : TALLOC_FREE(frame);
120 :
121 335416 : 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 :
129 335416 : 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 0 : NTSTATUS status;
135 0 : DATA_BLOB in_buf, out_buf;
136 335416 : size_t buf_len = smb_len_nbt(buf) + 4; /* Don't forget the 4 length bytes. */
137 0 : TALLOC_CTX *frame;
138 :
139 335416 : *ppbuf_out = NULL;
140 :
141 335416 : if (buf_len < 8) {
142 0 : return NT_STATUS_BUFFER_TOO_SMALL;
143 : }
144 335416 : in_buf = data_blob_const(buf + 8, buf_len - 8);
145 :
146 335416 : frame = talloc_stackframe();
147 :
148 335416 : status = gensec_wrap(gensec, frame, &in_buf, &out_buf);
149 335416 : if (!NT_STATUS_IS_OK(status)) {
150 0 : DEBUG(0,("common_gensec_encrypt_buffer: gensec_wrap failed. Error %s\n",
151 : nt_errstr(status)));
152 0 : TALLOC_FREE(frame);
153 0 : return status;
154 : }
155 :
156 335416 : *ppbuf_out = (char *)malloc(out_buf.length + 8); /* We know this can't wrap. */
157 335416 : if (!*ppbuf_out) {
158 0 : TALLOC_FREE(frame);
159 0 : return NT_STATUS_NO_MEMORY;
160 : }
161 :
162 335416 : memcpy(*ppbuf_out+8, out_buf.data, out_buf.length);
163 335416 : smb_set_enclen(*ppbuf_out, out_buf.length + 4, enc_ctx_num);
164 :
165 335416 : TALLOC_FREE(frame);
166 :
167 335416 : 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 :
175 335416 : NTSTATUS common_encrypt_buffer(struct smb_trans_enc_state *es, char *buffer, char **buf_out)
176 : {
177 335416 : if (!common_encryption_on(es)) {
178 : /* Not encrypting. */
179 0 : *buf_out = buffer;
180 0 : return NT_STATUS_OK;
181 : }
182 :
183 335416 : 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 :
192 335416 : NTSTATUS common_decrypt_buffer(struct smb_trans_enc_state *es, char *buf)
193 : {
194 335416 : if (!common_encryption_on(es)) {
195 : /* Not decrypting. */
196 0 : return NT_STATUS_OK;
197 : }
198 :
199 335416 : return common_gensec_decrypt_buffer(es->gensec_security, buf);
200 : }
201 :
202 : /******************************************************************************
203 : Free an encryption-allocated buffer.
204 : ******************************************************************************/
205 :
206 185883 : void common_free_enc_buffer(struct smb_trans_enc_state *es, char *buf)
207 : {
208 0 : uint16_t enc_ctx_num;
209 :
210 185883 : if (!common_encryption_on(es)) {
211 0 : return;
212 : }
213 :
214 185883 : if (!NT_STATUS_IS_OK(get_enc_ctx_num((const uint8_t *)buf,
215 : &enc_ctx_num))) {
216 0 : return;
217 : }
218 :
219 185883 : SAFE_FREE(buf);
220 : }
|