diff options
Diffstat (limited to 'source4/auth/gensec/schannel.c')
-rw-r--r-- | source4/auth/gensec/schannel.c | 110 |
1 files changed, 61 insertions, 49 deletions
diff --git a/source4/auth/gensec/schannel.c b/source4/auth/gensec/schannel.c index 8e56f671d7..15d64436e3 100644 --- a/source4/auth/gensec/schannel.c +++ b/source4/auth/gensec/schannel.c @@ -1,4 +1,4 @@ -/* +/* Unix SMB/CIFS implementation. dcerpc schannel operations @@ -10,12 +10,12 @@ 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/>. */ @@ -36,24 +36,26 @@ static size_t schannel_sig_size(struct gensec_security *gensec_security, size_t return 32; } -static NTSTATUS schannel_session_key(struct gensec_security *gensec_security, +static NTSTATUS schannel_session_key(struct gensec_security *gensec_security, DATA_BLOB *session_key) { return NT_STATUS_NOT_IMPLEMENTED; } -static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, - const DATA_BLOB in, DATA_BLOB *out) +static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, + const DATA_BLOB in, DATA_BLOB *out) { struct schannel_state *state = (struct schannel_state *)gensec_security->private_data; NTSTATUS status; enum ndr_err_code ndr_err; - struct schannel_bind bind_schannel; - struct schannel_bind_ack bind_schannel_ack; + struct NL_AUTH_MESSAGE bind_schannel; + struct NL_AUTH_MESSAGE bind_schannel_ack; struct netlogon_creds_CredentialState *creds; struct ldb_context *schannel_ldb; const char *workstation; const char *domain; + uint32_t required_flags; + *out = data_blob(NULL, 0); switch (gensec_security->gensec_role) { @@ -65,71 +67,78 @@ static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_ state->creds = talloc_reference(state, cli_credentials_get_netlogon_creds(gensec_security->credentials)); - bind_schannel.unknown1 = 0; + bind_schannel.MessageType = NL_NEGOTIATE_REQUEST; #if 0 /* to support this we'd need to have access to the full domain name */ - bind_schannel.bind_type = 23; - bind_schannel.u.info23.domain = cli_credentials_get_domain(gensec_security->credentials); - bind_schannel.u.info23.workstation = cli_credentials_get_workstation(gensec_security->credentials); - bind_schannel.u.info23.dnsdomain = cli_credentials_get_realm(gensec_security->credentials); + /* 0x17, 23 */ + bind_schannel.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME | + NL_FLAG_OEM_NETBIOS_COMPUTER_NAME | + NL_FLAG_UTF8_DNS_DOMAIN_NAME | + NL_FLAG_UTF8_NETBIOS_COMPUTER_NAME; + bind_schannel.oem_netbios_domain.a = cli_credentials_get_domain(gensec_security->credentials); + bind_schannel.oem_netbios_computer.a = cli_credentials_get_workstation(gensec_security->credentials); + bind_schannel.utf8_dns_domain = cli_credentials_get_realm(gensec_security->credentials); /* w2k3 refuses us if we use the full DNS workstation? why? perhaps because we don't fill in the dNSHostName attribute in the machine account? */ - bind_schannel.u.info23.dnsworkstation = cli_credentials_get_workstation(gensec_security->credentials); + bind_schannel.utf8_netbios_computer = cli_credentials_get_workstation(gensec_security->credentials); #else - bind_schannel.bind_type = 3; - bind_schannel.u.info3.domain = cli_credentials_get_domain(gensec_security->credentials); - bind_schannel.u.info3.workstation = cli_credentials_get_workstation(gensec_security->credentials); + bind_schannel.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME | + NL_FLAG_OEM_NETBIOS_COMPUTER_NAME; + bind_schannel.oem_netbios_domain.a = cli_credentials_get_domain(gensec_security->credentials); + bind_schannel.oem_netbios_computer.a = cli_credentials_get_workstation(gensec_security->credentials); #endif - - ndr_err = ndr_push_struct_blob(out, out_mem_ctx, + + ndr_err = ndr_push_struct_blob(out, out_mem_ctx, gensec_security->settings->iconv_convenience, &bind_schannel, - (ndr_push_flags_fn_t)ndr_push_schannel_bind); + (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); DEBUG(3, ("Could not create schannel bind: %s\n", nt_errstr(status))); return status; } - + state->state = SCHANNEL_STATE_UPDATE_1; return NT_STATUS_MORE_PROCESSING_REQUIRED; case GENSEC_SERVER: - + + required_flags = NL_FLAG_OEM_NETBIOS_COMPUTER_NAME | + NL_FLAG_OEM_NETBIOS_DOMAIN_NAME; + if (state->state != SCHANNEL_STATE_START) { /* no third leg on this protocol */ return NT_STATUS_INVALID_PARAMETER; } - + /* parse the schannel startup blob */ ndr_err = ndr_pull_struct_blob(&in, out_mem_ctx, gensec_security->settings->iconv_convenience, - &bind_schannel, - (ndr_pull_flags_fn_t)ndr_pull_schannel_bind); + &bind_schannel, + (ndr_pull_flags_fn_t)ndr_pull_NL_AUTH_MESSAGE); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); DEBUG(3, ("Could not parse incoming schannel bind: %s\n", nt_errstr(status))); return status; } - - if (bind_schannel.bind_type == 23) { - workstation = bind_schannel.u.info23.workstation; - domain = bind_schannel.u.info23.domain; - } else { - workstation = bind_schannel.u.info3.workstation; - domain = bind_schannel.u.info3.domain; + + if (!(required_flags == (bind_schannel.Flags & required_flags))) { + return NT_STATUS_INVALID_PARAMETER; } - + + workstation = bind_schannel.oem_netbios_computer.a; + domain = bind_schannel.oem_netbios_domain.a; + if (strcasecmp_m(domain, lp_workgroup(gensec_security->settings->lp_ctx)) != 0) { DEBUG(3, ("Request for schannel to incorrect domain: %s != our domain %s\n", domain, lp_workgroup(gensec_security->settings->lp_ctx))); - + return NT_STATUS_LOGON_FAILURE; } - schannel_ldb = schannel_db_connect(out_mem_ctx, gensec_security->event_ctx, + schannel_ldb = schannel_db_connect(out_mem_ctx, gensec_security->event_ctx, gensec_security->settings->lp_ctx); if (!schannel_ldb) { return NT_STATUS_ACCESS_DENIED; @@ -149,13 +158,16 @@ static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_ state->creds = talloc_reference(state, creds); - bind_schannel_ack.unknown1 = 1; - bind_schannel_ack.unknown2 = 0; - bind_schannel_ack.unknown3 = 0x6c0000; - - ndr_err = ndr_push_struct_blob(out, out_mem_ctx, + bind_schannel_ack.MessageType = NL_NEGOTIATE_RESPONSE; + bind_schannel_ack.Flags = 0; + bind_schannel_ack.Buffer.dummy = 0x6c0000; /* actually I think + * this does not have + * any meaning here + * - gd */ + + ndr_err = ndr_push_struct_blob(out, out_mem_ctx, gensec_security->settings->iconv_convenience, &bind_schannel_ack, - (ndr_push_flags_fn_t)ndr_push_schannel_bind_ack); + (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); DEBUG(3, ("Could not return schannel bind ack for client %s: %s\n", @@ -181,7 +193,7 @@ static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_ _PUBLIC_ NTSTATUS dcerpc_schannel_creds(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx, struct netlogon_creds_CredentialState **creds) -{ +{ struct schannel_state *state = talloc_get_type(gensec_security->private_data, struct schannel_state); *creds = talloc_reference(mem_ctx, state->creds); @@ -190,15 +202,15 @@ _PUBLIC_ NTSTATUS dcerpc_schannel_creds(struct gensec_security *gensec_security, } return NT_STATUS_OK; } - -/** + +/** * Returns anonymous credentials for schannel, matching Win2k3. * */ static NTSTATUS schannel_session_info(struct gensec_security *gensec_security, - struct auth_session_info **_session_info) + struct auth_session_info **_session_info) { struct schannel_state *state = talloc_get_type(gensec_security->private_data, struct schannel_state); return auth_anonymous_session_info(state, gensec_security->event_ctx, gensec_security->settings->lp_ctx, _session_info); @@ -220,7 +232,7 @@ static NTSTATUS schannel_start(struct gensec_security *gensec_security) return NT_STATUS_OK; } -static NTSTATUS schannel_server_start(struct gensec_security *gensec_security) +static NTSTATUS schannel_server_start(struct gensec_security *gensec_security) { NTSTATUS status; struct schannel_state *state; @@ -232,7 +244,7 @@ static NTSTATUS schannel_server_start(struct gensec_security *gensec_security) state = (struct schannel_state *)gensec_security->private_data; state->initiator = false; - + return NT_STATUS_OK; } @@ -248,7 +260,7 @@ static NTSTATUS schannel_client_start(struct gensec_security *gensec_security) state = (struct schannel_state *)gensec_security->private_data; state->initiator = true; - + return NT_STATUS_OK; } @@ -256,7 +268,7 @@ static NTSTATUS schannel_client_start(struct gensec_security *gensec_security) static bool schannel_have_feature(struct gensec_security *gensec_security, uint32_t feature) { - if (feature & (GENSEC_FEATURE_SIGN | + if (feature & (GENSEC_FEATURE_SIGN | GENSEC_FEATURE_SEAL)) { return true; } |