diff options
author | Stefan Metzmacher <metze@samba.org> | 2009-05-14 15:32:02 +0200 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2009-05-20 15:42:59 +0200 |
commit | 3ef6a5ae9ebefb18755337a83ba5488e8b8edd6e (patch) | |
tree | 07234d3910e256f457ba263ecbd7d152c83e900e /source3/smbd/smb2_negprot.c | |
parent | c14dd15c6a802729f46857630b1df83987d9a11c (diff) | |
download | samba-3ef6a5ae9ebefb18755337a83ba5488e8b8edd6e.tar.gz |
s3:smbd: add support for SMB2 Negotiate
This is not complete, but a start that makes the
samba4 smb2 client happy.
metze
Diffstat (limited to 'source3/smbd/smb2_negprot.c')
-rw-r--r-- | source3/smbd/smb2_negprot.c | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/source3/smbd/smb2_negprot.c b/source3/smbd/smb2_negprot.c new file mode 100644 index 00000000000..d82d04885df --- /dev/null +++ b/source3/smbd/smb2_negprot.c @@ -0,0 +1,127 @@ +/* + Unix SMB/CIFS implementation. + Core SMB2 server + + Copyright (C) Stefan Metzmacher 2009 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "smbd/globals.h" +#include "../source4/libcli/smb2/smb2_constants.h" + +extern enum protocol_types Protocol; + +NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) +{ + const uint8_t *inbody; + const uint8_t *indyn = NULL; + int i = req->current_idx; + DATA_BLOB outbody; + DATA_BLOB outdyn; + DATA_BLOB negprot_spnego_blob; + uint16_t security_offset; + DATA_BLOB security_buffer; + size_t expected_body_size = 0x24; + size_t body_size; + size_t expected_dyn_size = 0; + size_t c; + uint16_t dialect_count; + uint16_t dialect; + +/* TODO: drop the connection with INVALI_PARAMETER */ + + if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) { + return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); + } + + inbody = (const uint8_t *)req->in.vector[i+1].iov_base; + + body_size = SVAL(inbody, 0x00); + if (body_size != expected_body_size) { + return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); + } + + dialect_count = SVAL(inbody, 0x02); + if (dialect_count == 0) { + return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); + } + + expected_dyn_size = dialect_count * 2; + if (req->in.vector[i+2].iov_len < expected_dyn_size) { + return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); + } + indyn = (const uint8_t *)req->in.vector[i+2].iov_base; + + for (c=0; c < dialect_count; c++) { + dialect = SVAL(indyn, c*2); + if (dialect == 0x0202) { + break; + } + } + + if (dialect != 0x0202) { + return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); + } + + Protocol = PROTOCOL_SMB2; + + if (get_remote_arch() != RA_SAMBA) { + set_remote_arch(RA_VISTA); + } + + /* negprot_spnego() returns a the server guid in the first 16 bytes */ + negprot_spnego_blob = negprot_spnego(); + if (negprot_spnego_blob.data == NULL) { + return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY); + } + talloc_steal(req, negprot_spnego_blob.data); + + if (negprot_spnego_blob.length < 16) { + return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR); + } + + security_offset = SMB2_HDR_BODY + 0x40; + security_buffer = data_blob_const(negprot_spnego_blob.data + 16, + negprot_spnego_blob.length - 16); + + outbody = data_blob_talloc(req->out.vector, NULL, 0x40); + if (outbody.data == NULL) { + return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY); + } + + SSVAL(outbody.data, 0x00, 0x40 + 1); /* struct size */ +/*TODO: indicate signing enabled */ + SSVAL(outbody.data, 0x02, 0); /* security mode */ + SSVAL(outbody.data, 0x04, dialect); /* dialect revision */ + SSVAL(outbody.data, 0x06, 0); /* reserved */ + memcpy(outbody.data + 0x08, + negprot_spnego_blob.data, 16); /* server guid */ + SIVAL(outbody.data, 0x18, 0); /* capabilities */ + SIVAL(outbody.data, 0x1C, 0x00010000); /* max transact size */ + SIVAL(outbody.data, 0x20, 0x00010000); /* max read size */ + SIVAL(outbody.data, 0x24, 0x00010000); /* max write size */ + SBVAL(outbody.data, 0x28, 0); /* system time */ + SBVAL(outbody.data, 0x30, 0); /* server start time */ + SSVAL(outbody.data, 0x38, + security_offset); /* security buffer offset */ + SSVAL(outbody.data, 0x3A, + security_buffer.length); /* security buffer length */ + SIVAL(outbody.data, 0x3C, 0); /* reserved */ + + outdyn = security_buffer; + + return smbd_smb2_request_done(req, outbody, &outdyn); +} |