From 1c9216f36cc451156d6c65f0e971ce48f05da3e5 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 11 Aug 2004 18:09:40 +0000 Subject: r1731: Add server-side SPNEGO support to Samba (disabled, until SMB signing is reworked). Andrew Bartlett (This used to be commit 73ee549b8c54e93556ff0105941996e0d4de8303) --- source4/smb_server/sesssetup.c | 117 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 104 insertions(+), 13 deletions(-) (limited to 'source4/smb_server/sesssetup.c') diff --git a/source4/smb_server/sesssetup.c b/source4/smb_server/sesssetup.c index cb0b3a6c5c..39aadf8778 100644 --- a/source4/smb_server/sesssetup.c +++ b/source4/smb_server/sesssetup.c @@ -103,19 +103,41 @@ static NTSTATUS sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *s req->smb_conn->negotiate.client_caps = sess->nt1.in.capabilities; } - status = make_user_info_for_reply_enc(&user_info, - sess->nt1.in.user, sess->nt1.in.domain, - sess->nt1.in.password1, - sess->nt1.in.password2); - if (!NT_STATUS_IS_OK(status)) { - return NT_STATUS_ACCESS_DENIED; + if (req->smb_conn->negotiate.spnego_negotiated) { + struct auth_context *auth_context; + + status = make_auth_context_subsystem(&auth_context); + + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + if (!sess->nt1.in.user || !*sess->nt1.in.user) { + make_user_info_guest(&user_info); + } + + status = auth_context->check_ntlm_password(auth_context, + user_info, + &server_info); + + free_auth_context(&auth_context); + + } else { + status = make_user_info_for_reply_enc(&user_info, + sess->nt1.in.user, sess->nt1.in.domain, + sess->nt1.in.password1, + sess->nt1.in.password2); + if (!NT_STATUS_IS_OK(status)) { + return NT_STATUS_ACCESS_DENIED; + } + + status = req->smb_conn->negotiate + .auth_context->check_ntlm_password(req->smb_conn->negotiate + .auth_context, + user_info, + &server_info); } - status = req->smb_conn->negotiate - .auth_context->check_ntlm_password(req->smb_conn->negotiate - .auth_context, - user_info, - &server_info); if (!NT_STATUS_IS_OK(status)) { return nt_status_squash(status); } @@ -149,8 +171,74 @@ static NTSTATUS sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *s */ static NTSTATUS sesssetup_spnego(struct smbsrv_request *req, union smb_sesssetup *sess) { - /* defer this one for now */ - return NT_STATUS_INVALID_LEVEL; + NTSTATUS status = NT_STATUS_ACCESS_DENIED; + struct smbsrv_session *smb_sess; + struct gensec_security *gensec_ctx = NULL; + struct auth_session_info *session_info = NULL; + uint16_t vuid; + + if (!req->smb_conn->negotiate.done_sesssetup) { + req->smb_conn->negotiate.max_send = sess->nt1.in.bufsize; + req->smb_conn->negotiate.client_caps = sess->nt1.in.capabilities; + } + + vuid = SVAL(req->in.hdr,HDR_UID); + smb_sess = smbsrv_session_find(req->smb_conn, vuid); + if (smb_sess) { + if (!smb_sess->gensec_ctx) { + return NT_STATUS_INVALID_HANDLE; + } + + /* what is when the client is already successful authentificated? */ + if (smb_sess->session_info) { + return NT_STATUS_ACCESS_DENIED; + } + + status = gensec_update(smb_sess->gensec_ctx, req->mem_ctx, sess->spnego.in.secblob, &sess->spnego.out.secblob); + } else { + status = gensec_server_start(&gensec_ctx); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("Failed to start GENSEC server code: %s\n", nt_errstr(status))); + return status; + } + + status = gensec_start_mech_by_oid(gensec_ctx, OID_SPNEGO); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("Failed to start GENSEC SPNEGO server code: %s\n", nt_errstr(status))); + return status; + } + + status = gensec_update(gensec_ctx, req->mem_ctx, sess->spnego.in.secblob, &sess->spnego.out.secblob); + + } + + if (NT_STATUS_IS_OK(status)) { + DATA_BLOB session_key; + DATA_BLOB null_data_blob = data_blob(NULL, 0); + status = gensec_session_info(smb_sess->gensec_ctx, &smb_sess->session_info); + if (NT_STATUS_IS_OK(gensec_session_key(smb_sess->gensec_ctx, + &session_key))) { + srv_setup_signing(req->smb_conn, &session_key, &null_data_blob); + req->seq_num = 0; + req->smb_conn->signing.next_seq_num = 2; + } + } + + if (!smb_sess) { + vuid = smbsrv_register_session(req->smb_conn, session_info, gensec_ctx); + if (vuid == UID_FIELD_INVALID) { + return NT_STATUS_ACCESS_DENIED; + } + } + + sess->spnego.out.action = 0; + sess->spnego.out.vuid = vuid; + sesssetup_common_strings(req, + &sess->spnego.out.os, + &sess->spnego.out.lanman, + &sess->spnego.out.domain); + + return status; } /* @@ -162,6 +250,9 @@ NTSTATUS sesssetup_backend(struct smbsrv_request *req, NTSTATUS status = NT_STATUS_INVALID_LEVEL; switch (sess->generic.level) { + case RAW_SESSSETUP_GENERIC: + status = NT_STATUS_INVALID_LEVEL; + break; case RAW_SESSSETUP_OLD: status = sesssetup_old(req, sess); break; -- cgit