r21912: There's no point checksumming the packet length
[samba.git] / source / libsmb / smb_seal.c
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 2 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, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22
23 /******************************************************************************
24  Generic code for client and server.
25  Is encryption turned on ?
26 ******************************************************************************/
27
28 BOOL common_encryption_on(struct smb_trans_enc_state *es)
29 {
30         return ((es != NULL) && es->enc_on);
31 }
32
33 /******************************************************************************
34  Generic code for client and server.
35  NTLM decrypt an incoming buffer.
36 ******************************************************************************/
37
38 NTSTATUS common_ntlm_decrypt_buffer(NTLMSSP_STATE *ntlmssp_state, char *buf)
39 {
40         NTSTATUS status;
41         size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */
42         DATA_BLOB sig;
43
44         if (buf_len < 8 + NTLMSSP_SIG_SIZE) {
45                 return NT_STATUS_BUFFER_TOO_SMALL;
46         }
47
48         /* Adjust for the signature. */
49         buf_len -= NTLMSSP_SIG_SIZE;
50
51         /* Save off the signature. */
52         sig = data_blob(buf+buf_len, NTLMSSP_SIG_SIZE);
53
54         status = ntlmssp_unseal_packet(ntlmssp_state,
55                 (unsigned char *)buf + 8, /* 4 byte len + 0xFF 'S' 'M' 'B' */
56                 buf_len - 8,
57                 (unsigned char *)buf + 8,
58                 buf_len - 8,
59                 &sig);
60
61         if (!NT_STATUS_IS_OK(status)) {
62                 data_blob_free(&sig);
63                 return status;
64         }
65
66         /* Reset the length. */
67         smb_setlen(buf, smb_len(buf) - NTLMSSP_SIG_SIZE);
68         return NT_STATUS_OK;
69 }
70
71 /******************************************************************************
72  Generic code for client and server.
73  NTLM encrypt an outgoing buffer. Return the encrypted pointer in ppbuf_out.
74 ******************************************************************************/
75
76 NTSTATUS common_ntlm_encrypt_buffer(NTLMSSP_STATE *ntlmssp_state, char *buf, char **ppbuf_out)
77 {
78         NTSTATUS status;
79         char *buf_out;
80         size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */
81         DATA_BLOB sig;
82
83         *ppbuf_out = NULL;
84
85         if (buf_len < 8) {
86                 return NT_STATUS_BUFFER_TOO_SMALL;
87         }
88
89         /* 
90          * We know smb_len can't return a value > 128k, so no int overflow
91          * check needed.
92          */
93
94         /* Copy the original buffer. */
95
96         buf_out = SMB_XMALLOC_ARRAY(char, buf_len + NTLMSSP_SIG_SIZE);
97         memcpy(buf_out, buf, buf_len);
98         /* Last 16 bytes undefined here... */
99
100         smb_setlen(buf_out, smb_len(buf) + NTLMSSP_SIG_SIZE);
101
102         sig = data_blob(NULL, NTLMSSP_SIG_SIZE);
103
104         status = ntlmssp_seal_packet(ntlmssp_state,
105                 (unsigned char *)buf_out + 8, /* 4 byte len + 0xFF 'S' 'M' 'B' */
106                 buf_len - 8,
107                 (unsigned char *)buf_out + 8,
108                 buf_len - 8,
109                 &sig);
110
111         if (!NT_STATUS_IS_OK(status)) {
112                 data_blob_free(&sig);
113                 SAFE_FREE(buf_out);
114                 return status;
115         }
116
117         memcpy(buf_out+buf_len, sig.data, NTLMSSP_SIG_SIZE);
118         *ppbuf_out = buf_out;
119         return NT_STATUS_OK;
120 }
121
122 /******************************************************************************
123  Generic code for client and server.
124  gss-api decrypt an incoming buffer.
125 ******************************************************************************/
126
127 #if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5)
128  NTSTATUS common_gss_decrypt_buffer(gss_ctx_id_t context_handle, char *buf)
129 {
130         return NT_STATUS_NOT_SUPPORTED;
131 }
132 #endif
133
134 /******************************************************************************
135  Generic code for client and server.
136  gss-api encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
137 ******************************************************************************/
138
139 #if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5)
140  NTSTATUS common_gss_encrypt_buffer(gss_ctx_id_t context_handle, char *buf, char **buf_out)
141 {
142         return NT_STATUS_NOT_SUPPORTED;
143 }
144 #endif
145
146 /******************************************************************************
147  Generic code for client and server.
148  Encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
149 ******************************************************************************/
150
151 NTSTATUS common_encrypt_buffer(struct smb_trans_enc_state *es, char *buffer, char **buf_out)
152 {
153         if (!common_encryption_on(es)) {
154                 /* Not encrypting. */
155                 *buf_out = buffer;
156                 return NT_STATUS_OK;
157         }
158
159         /* Ignore session keepalives. */
160         if(CVAL(buffer,0) == SMBkeepalive) {
161                 *buf_out = buffer;
162                 return NT_STATUS_OK;
163         }
164
165         if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
166                 return common_ntlm_encrypt_buffer(es->ntlmssp_state, buffer, buf_out);
167         } else {
168 #if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5)
169                 return common_gss_encrypt_buffer(es->context_handle, buffer, buf_out);
170 #else
171                 return NT_STATUS_NOT_SUPPORTED;
172 #endif
173         }
174 }
175
176 /******************************************************************************
177  Generic code for client and server.
178  Decrypt an incoming SMB buffer. Replaces the data within it.
179  New data must be less than or equal to the current length.
180 ******************************************************************************/
181
182 NTSTATUS common_decrypt_buffer(struct smb_trans_enc_state *es, char *buf)
183 {
184         if (!common_encryption_on(es)) {
185                 /* Not decrypting. */
186                 return NT_STATUS_OK;
187         }
188
189         /* Ignore session keepalives. */
190         if(CVAL(buf,0) == SMBkeepalive) {
191                 return NT_STATUS_OK;
192         }
193
194         if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
195                 return common_ntlm_decrypt_buffer(es->ntlmssp_state, buf);
196         } else {
197 #if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5)
198                 return common_gss_decrypt_buffer(es->context_handle, buf);
199 #else
200                 return NT_STATUS_NOT_SUPPORTED;
201 #endif
202         }
203 }
204
205 /******************************************************************************
206  Shutdown an encryption state.
207 ******************************************************************************/
208
209 void common_free_encryption_state(struct smb_trans_enc_state **pp_es)
210 {
211         struct smb_trans_enc_state *es = *pp_es;
212
213         if (es == NULL) {
214                 return;
215         }
216
217         if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
218                 if (es->ntlmssp_state) {
219                         ntlmssp_end(&es->ntlmssp_state);
220                 }
221         }
222 #if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5)
223         if (es->smb_enc_type == SMB_TRANS_ENC_GSS) {
224                 /* Free the gss context handle. */
225         }
226 #endif
227         SAFE_FREE(es);
228         *pp_es = NULL;
229 }
230
231 /******************************************************************************
232  Free an encryption-allocated buffer.
233 ******************************************************************************/
234
235 void common_free_enc_buffer(struct smb_trans_enc_state *es, char *buf)
236 {
237         if (!common_encryption_on(es)) {
238                 return;
239         }
240
241         if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
242                 SAFE_FREE(buf);
243                 return;
244         }
245
246 #if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5)
247         /* gss-api free buffer.... */
248 #endif
249 }
250
251 /******************************************************************************
252  Client side encryption.
253 ******************************************************************************/
254
255 /******************************************************************************
256  Is client encryption on ?
257 ******************************************************************************/
258
259 BOOL cli_encryption_on(struct cli_state *cli)
260 {
261         return common_encryption_on(cli->trans_enc_state);
262 }
263
264 /******************************************************************************
265  Shutdown a client encryption state.
266 ******************************************************************************/
267
268 void cli_free_encryption_context(struct cli_state *cli)
269 {
270         return common_free_encryption_state(&cli->trans_enc_state);
271 }
272
273 /******************************************************************************
274  Free an encryption-allocated buffer.
275 ******************************************************************************/
276
277 void cli_free_enc_buffer(struct cli_state *cli, char *buf)
278 {
279         return common_free_enc_buffer(cli->trans_enc_state, buf);
280 }
281
282 /******************************************************************************
283  Decrypt an incoming buffer.
284 ******************************************************************************/
285
286 NTSTATUS cli_decrypt_message(struct cli_state *cli)
287 {
288         return common_decrypt_buffer(cli->trans_enc_state, cli->inbuf);
289 }
290
291 /******************************************************************************
292  Encrypt an outgoing buffer. Return the encrypted pointer in buf_out.
293 ******************************************************************************/
294
295 NTSTATUS cli_encrypt_message(struct cli_state *cli, char **buf_out)
296 {
297         return common_encrypt_buffer(cli->trans_enc_state, cli->outbuf, buf_out);
298 }