r21916: Fix couple of "return" calls on void functions.
[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         /* We know this is an smb buffer, and we
242          * didn't malloc, only copy, for a keepalive,
243          * so ignore session keepalives. */
244
245         if(CVAL(buf,0) == SMBkeepalive) {
246                 return;
247         }
248
249         if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
250                 SAFE_FREE(buf);
251                 return;
252         }
253
254 #if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5)
255         /* gss-api free buffer.... */
256 #endif
257 }
258
259 /******************************************************************************
260  Client side encryption.
261 ******************************************************************************/
262
263 /******************************************************************************
264  Is client encryption on ?
265 ******************************************************************************/
266
267 BOOL cli_encryption_on(struct cli_state *cli)
268 {
269         return common_encryption_on(cli->trans_enc_state);
270 }
271
272 /******************************************************************************
273  Shutdown a client encryption state.
274 ******************************************************************************/
275
276 void cli_free_encryption_context(struct cli_state *cli)
277 {
278         common_free_encryption_state(&cli->trans_enc_state);
279 }
280
281 /******************************************************************************
282  Free an encryption-allocated buffer.
283 ******************************************************************************/
284
285 void cli_free_enc_buffer(struct cli_state *cli, char *buf)
286 {
287         common_free_enc_buffer(cli->trans_enc_state, buf);
288 }
289
290 /******************************************************************************
291  Decrypt an incoming buffer.
292 ******************************************************************************/
293
294 NTSTATUS cli_decrypt_message(struct cli_state *cli)
295 {
296         return common_decrypt_buffer(cli->trans_enc_state, cli->inbuf);
297 }
298
299 /******************************************************************************
300  Encrypt an outgoing buffer. Return the encrypted pointer in buf_out.
301 ******************************************************************************/
302
303 NTSTATUS cli_encrypt_message(struct cli_state *cli, char **buf_out)
304 {
305         return common_encrypt_buffer(cli->trans_enc_state, cli->outbuf, buf_out);
306 }