s4-winbind: Use winbindd in the AD DC for fl2003dc and plugin_s4_dc
[Samba/wip.git] / libcli / smb / smb_seal.c
blobf4f804c94738b84970c6eb25a30bc5936306ce89
1 /*
2 Unix SMB/CIFS implementation.
3 SMB Transport encryption (sealing) code.
4 Copyright (C) Jeremy Allison 2007.
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.
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.
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/>.
20 #include "includes.h"
21 #include "smb_common.h"
22 #if 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"
28 #undef malloc
30 /******************************************************************************
31 Pull out the encryption context for this packet. 0 means global context.
32 ******************************************************************************/
34 NTSTATUS get_enc_ctx_num(const uint8_t *buf, uint16_t *p_enc_ctx_num)
36 if (smb_len_nbt(buf) < 8) {
37 return NT_STATUS_INVALID_BUFFER_SIZE;
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;
45 if (buf[5] == 'E') {
46 *p_enc_ctx_num = SVAL(buf,6);
47 return NT_STATUS_OK;
50 return NT_STATUS_INVALID_NETWORK_RESPONSE;
53 /*******************************************************************
54 Set the length and marker of an encrypted smb packet.
55 ********************************************************************/
57 static void smb_set_enclen(char *buf,int len,uint16_t enc_ctx_num)
59 _smb_setlen_tcp(buf,len);
61 SCVAL(buf,4,0xFF);
62 SCVAL(buf,5,'E');
63 SSVAL(buf,6,enc_ctx_num);
66 /******************************************************************************
67 Generic code for client and server.
68 Is encryption turned on ?
69 ******************************************************************************/
71 bool common_encryption_on(struct smb_trans_enc_state *es)
73 return ((es != NULL) && es->enc_on);
76 /******************************************************************************
77 Generic code for client and server.
78 GENSEC decrypt an incoming buffer.
79 ******************************************************************************/
81 static NTSTATUS common_gensec_decrypt_buffer(struct gensec_security *gensec,
82 char *buf)
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;
89 if (buf_len < 8) {
90 return NT_STATUS_BUFFER_TOO_SMALL;
93 frame = talloc_stackframe();
95 in_buf = data_blob_const(buf + 8, buf_len - 8);
97 status = gensec_unwrap(gensec, frame, &in_buf, &out_buf);
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;
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;
114 memcpy(buf + 8, out_buf.data, out_buf.length);
116 /* Reset the length and overwrite the header. */
117 smb_setlen_nbt(buf, out_buf.length + 4);
119 TALLOC_FREE(frame);
121 return NT_STATUS_OK;
124 /******************************************************************************
125 Generic code for client and server.
126 NTLM encrypt an outgoing buffer. Return the encrypted pointer in ppbuf_out.
127 ******************************************************************************/
129 static NTSTATUS common_gensec_encrypt_buffer(struct gensec_security *gensec,
130 uint16_t enc_ctx_num,
131 char *buf,
132 char **ppbuf_out)
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;
139 *ppbuf_out = NULL;
141 if (buf_len < 8) {
142 return NT_STATUS_BUFFER_TOO_SMALL;
144 in_buf = data_blob_const(buf + 8, buf_len - 8);
146 frame = talloc_stackframe();
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;
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;
162 memcpy(*ppbuf_out+8, out_buf.data, out_buf.length);
163 smb_set_enclen(*ppbuf_out, out_buf.length + 4, enc_ctx_num);
165 TALLOC_FREE(frame);
167 return NT_STATUS_OK;
170 /******************************************************************************
171 Generic code for client and server.
172 Encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
173 ******************************************************************************/
175 NTSTATUS common_encrypt_buffer(struct smb_trans_enc_state *es, char *buffer, char **buf_out)
177 if (!common_encryption_on(es)) {
178 /* Not encrypting. */
179 *buf_out = buffer;
180 return NT_STATUS_OK;
183 return common_gensec_encrypt_buffer(es->gensec_security, es->enc_ctx_num, buffer, buf_out);
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 ******************************************************************************/
192 NTSTATUS common_decrypt_buffer(struct smb_trans_enc_state *es, char *buf)
194 if (!common_encryption_on(es)) {
195 /* Not decrypting. */
196 return NT_STATUS_OK;
199 return common_gensec_decrypt_buffer(es->gensec_security, buf);
202 /******************************************************************************
203 Free an encryption-allocated buffer.
204 ******************************************************************************/
206 void common_free_enc_buffer(struct smb_trans_enc_state *es, char *buf)
208 uint16_t enc_ctx_num;
210 if (!common_encryption_on(es)) {
211 return;
214 if (!NT_STATUS_IS_OK(get_enc_ctx_num((const uint8_t *)buf,
215 &enc_ctx_num))) {
216 return;
219 SAFE_FREE(buf);