X-Git-Url: http://git.samba.org/samba.git/?p=kai%2Fsamba-autobuild%2F.git;a=blobdiff_plain;f=source4%2Fsmb_server%2Fsmb2%2Fnegprot.c;h=addd278eb4c2068a3448274139975a564abbc0b2;hp=49a2d12ef47073bdb166e2bb7bab64811ef6b97a;hb=b720575f16d8a2006d10eb8a94c7134a30d5309d;hpb=eb5b3f50d17dfca198304d636033ad93410d570f diff --git a/source4/smb_server/smb2/negprot.c b/source4/smb_server/smb2/negprot.c index 49a2d12ef47..addd278eb4c 100644 --- a/source4/smb_server/smb2/negprot.c +++ b/source4/smb_server/smb2/negprot.c @@ -20,17 +20,16 @@ #include "includes.h" #include "auth/credentials/credentials.h" +#include "auth/auth.h" #include "auth/gensec/gensec.h" #include "libcli/raw/libcliraw.h" #include "libcli/raw/raw_proto.h" #include "libcli/smb2/smb2.h" #include "libcli/smb2/smb2_calls.h" #include "smb_server/smb_server.h" -#include "smb_server/service_smb_proto.h" #include "smb_server/smb2/smb2_server.h" #include "smbd/service_stream.h" #include "param/param.h" -#include "librpc/ndr/libndr.h" static NTSTATUS smb2srv_negprot_secblob(struct smb2srv_request *req, DATA_BLOB *_blob) { @@ -40,17 +39,6 @@ static NTSTATUS smb2srv_negprot_secblob(struct smb2srv_request *req, DATA_BLOB * NTSTATUS nt_status; struct cli_credentials *server_credentials; - nt_status = gensec_server_start(req, - req->smb_conn->connection->event.ctx, - req->smb_conn->lp_ctx, - req->smb_conn->connection->msg_ctx, - &gensec_security); - if (!NT_STATUS_IS_OK(nt_status)) { - DEBUG(0, ("Failed to start GENSEC: %s\n", nt_errstr(nt_status))); - smbsrv_terminate_connection(req->smb_conn, "Failed to start GENSEC\n"); - return nt_status; - } - server_credentials = cli_credentials_init(req); if (!server_credentials) { smbsrv_terminate_connection(req->smb_conn, "Failed to init server credentials\n"); @@ -61,12 +49,27 @@ static NTSTATUS smb2srv_negprot_secblob(struct smb2srv_request *req, DATA_BLOB * nt_status = cli_credentials_set_machine_account(server_credentials, req->smb_conn->lp_ctx); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(10, ("Failed to obtain server credentials, perhaps a standalone server?: %s\n", nt_errstr(nt_status))); - talloc_free(server_credentials); - server_credentials = NULL; + /* + * We keep the server_credentials as anonymous + * this is required for the spoolss.notify test + */ } req->smb_conn->negotiate.server_credentials = talloc_steal(req->smb_conn, server_credentials); + nt_status = samba_server_gensec_start(req, + req->smb_conn->connection->event.ctx, + req->smb_conn->connection->msg_ctx, + req->smb_conn->lp_ctx, + server_credentials, + "cifs", + &gensec_security); + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(0, ("Failed to start GENSEC: %s\n", nt_errstr(nt_status))); + smbsrv_terminate_connection(req->smb_conn, "Failed to start GENSEC\n"); + return nt_status; + } + gensec_set_target_service(gensec_security, "cifs"); gensec_set_credentials(gensec_security, server_credentials); @@ -78,7 +81,7 @@ static NTSTATUS smb2srv_negprot_secblob(struct smb2srv_request *req, DATA_BLOB * return nt_status; } - nt_status = gensec_update(gensec_security, req, null_data_blob, &blob); + nt_status = gensec_update_ev(gensec_security, req, req->smb_conn->connection->event.ctx, null_data_blob, &blob); if (!NT_STATUS_IS_OK(nt_status) && !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { DEBUG(0, ("Failed to get SPNEGO to give us the first token: %s\n", nt_errstr(nt_status))); smbsrv_terminate_connection(req->smb_conn, "Failed to start SPNEGO - no first token\n"); @@ -94,29 +97,64 @@ static NTSTATUS smb2srv_negprot_backend(struct smb2srv_request *req, struct smb2 NTSTATUS status; struct timeval current_time; struct timeval boot_time; + uint16_t i; + uint16_t dialect = 0; + enum smb_signing_setting signing_setting; + struct loadparm_context *lp_ctx = req->smb_conn->lp_ctx; /* we only do one dialect for now */ if (io->in.dialect_count < 1) { return NT_STATUS_NOT_SUPPORTED; } - if (io->in.dialects[0] != 0 && - io->in.dialects[0] != SMB2_DIALECT_REVISION) { - DEBUG(0,("Got unexpected SMB2 dialect %u\n", io->in.dialects[0])); + for (i=0; i < io->in.dialect_count; i++) { + dialect = io->in.dialects[i]; + if (dialect == SMB2_DIALECT_REVISION_202) { + break; + } + } + if (dialect != SMB2_DIALECT_REVISION_202) { + DEBUG(0,("Got unexpected SMB2 dialect %u\n", dialect)); return NT_STATUS_NOT_SUPPORTED; } - req->smb_conn->negotiate.protocol = PROTOCOL_SMB2; + req->smb_conn->negotiate.protocol = PROTOCOL_SMB2_02; current_time = timeval_current(); /* TODO: handle timezone?! */ boot_time = timeval_current(); /* TODO: fix me */ ZERO_STRUCT(io->out); - switch (lp_server_signing(req->smb_conn->lp_ctx)) { + + signing_setting = lpcfg_server_signing(lp_ctx); + if (signing_setting == SMB_SIGNING_DEFAULT) { + /* + * If we are a domain controller, SMB signing is + * really important, as it can prevent a number of + * attacks on communications between us and the + * clients + * + * However, it really sucks (no sendfile, CPU + * overhead) performance-wise when used on a + * file server, so disable it by default + * on non-DCs + */ + + if (lpcfg_server_role(lp_ctx) >= ROLE_ACTIVE_DIRECTORY_DC) { + signing_setting = SMB_SIGNING_REQUIRED; + } else { + signing_setting = SMB_SIGNING_OFF; + } + } + + switch (signing_setting) { + case SMB_SIGNING_DEFAULT: + case SMB_SIGNING_IPC_DEFAULT: + smb_panic(__location__); + break; case SMB_SIGNING_OFF: io->out.security_mode = 0; break; - case SMB_SIGNING_SUPPORTED: - case SMB_SIGNING_AUTO: + case SMB_SIGNING_DESIRED: + case SMB_SIGNING_IF_REQUIRED: io->out.security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED; break; case SMB_SIGNING_REQUIRED: @@ -125,13 +163,13 @@ static NTSTATUS smb2srv_negprot_backend(struct smb2srv_request *req, struct smb2 req->smb_conn->smb2_signing_required = true; break; } - io->out.dialect_revision = SMB2_DIALECT_REVISION; + io->out.dialect_revision = dialect; io->out.capabilities = 0; - io->out.max_transact_size = lp_parm_ulong(req->smb_conn->lp_ctx, NULL, + io->out.max_transact_size = lpcfg_parm_ulong(req->smb_conn->lp_ctx, NULL, "smb2", "max transaction size", 0x10000); - io->out.max_read_size = lp_parm_ulong(req->smb_conn->lp_ctx, NULL, + io->out.max_read_size = lpcfg_parm_ulong(req->smb_conn->lp_ctx, NULL, "smb2", "max read size", 0x10000); - io->out.max_write_size = lp_parm_ulong(req->smb_conn->lp_ctx, NULL, + io->out.max_write_size = lpcfg_parm_ulong(req->smb_conn->lp_ctx, NULL, "smb2", "max write size", 0x10000); io->out.system_time = timeval_to_nttime(¤t_time); io->out.server_start_time = timeval_to_nttime(&boot_time); @@ -145,7 +183,6 @@ static NTSTATUS smb2srv_negprot_backend(struct smb2srv_request *req, struct smb2 static void smb2srv_negprot_send(struct smb2srv_request *req, struct smb2_negprot *io) { NTSTATUS status; - enum ndr_err_code ndr_err; if (NT_STATUS_IS_ERR(req->status)) { smb2srv_send_error(req, req->status); /* TODO: is this correct? */ @@ -162,8 +199,8 @@ static void smb2srv_negprot_send(struct smb2srv_request *req, struct smb2_negpro SSVAL(req->out.body, 0x02, io->out.security_mode); SIVAL(req->out.body, 0x04, io->out.dialect_revision); SIVAL(req->out.body, 0x06, io->out.reserved); - ndr_err = smbcli_push_guid(req->out.body, 0x08, &io->out.server_guid); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + status = smbcli_push_guid(req->out.body, 0x08, &io->out.server_guid); + if (!NT_STATUS_IS_OK(status)) { smbsrv_terminate_connection(req->smb_conn, nt_errstr(status)); talloc_free(req); return; @@ -189,7 +226,6 @@ void smb2srv_negprot_recv(struct smb2srv_request *req) { struct smb2_negprot *io; int i; - enum ndr_err_code ndr_err; if (req->in.body_size < 0x26) { smbsrv_terminate_connection(req->smb_conn, "Bad body size in SMB2 negprot"); @@ -207,8 +243,8 @@ void smb2srv_negprot_recv(struct smb2srv_request *req) io->in.security_mode = SVAL(req->in.body, 0x04); io->in.reserved = SVAL(req->in.body, 0x06); io->in.capabilities = IVAL(req->in.body, 0x08); - ndr_err = smbcli_pull_guid(req->in.body, 0xC, &io->in.client_guid); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + req->status = smbcli_pull_guid(req->in.body, 0xC, &io->in.client_guid); + if (!NT_STATUS_IS_OK(req->status)) { smbsrv_terminate_connection(req->smb_conn, "Bad GUID in SMB2 negprot"); talloc_free(req); return; @@ -278,7 +314,7 @@ void smb2srv_reply_smb_negprot(struct smbsrv_request *smb_req) SSVAL(req->in.body, 0x02, 1); memset(req->in.body+0x04, 0, 32); - SSVAL(req->in.body, 0x24, 0); + SSVAL(req->in.body, 0x24, SMB2_DIALECT_REVISION_202); smb2srv_negprot_recv(req); return;