From 9a6671cf9529fd7817c5ef266da3d3bea46a88c0 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 31 Dec 2004 22:45:11 +0000 Subject: r4459: GENSEC refinements: In developing a GSSAPI plugin for GENSEC, it became clear that the API needed to change: - GSSAPI exposes only a wrap() and unwrap() interface, and determines the location of the signature itself. - The 'have feature' API did not correctly function in the recursive SPNEGO environment. As such, NTLMSSP has been updated to support these methods. The LDAP client and server have been updated to use the new wrap() and unwrap() methods, and now pass the LDAP-* tests in our smbtorture. (Unfortunely I still get valgrind warnings, in the code that was previously unreachable). Andrew Bartlett (This used to be commit 9923c3bc1b5a6e93a5996aadb039bd229e888ac6) --- source4/ldap_server/ldap_bind.c | 21 ++++--- source4/ldap_server/ldap_server.c | 113 +++++++++++++-------------------- source4/libcli/auth/gensec.c | 30 +++++++-- source4/libcli/auth/gensec.h | 11 +++- source4/libcli/auth/gensec_krb5.c | 12 ++++ source4/libcli/auth/gensec_ntlmssp.c | 117 ++++++++++++++++++++++++++++++++++- source4/libcli/auth/spnego.c | 53 +++++++++++++++- source4/librpc/rpc/dcerpc_schannel.c | 17 +++-- source4/torture/ldap/common.c | 57 ++++++++--------- 9 files changed, 306 insertions(+), 125 deletions(-) (limited to 'source4') diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c index 80d1f51748..f4be5b5242 100644 --- a/source4/ldap_server/ldap_bind.c +++ b/source4/ldap_server/ldap_bind.c @@ -20,7 +20,7 @@ #include "includes.h" #include "ldap_server/ldap_server.h" - +#include "auth/auth.h" static NTSTATUS ldapsrv_BindSimple(struct ldapsrv_call *call) { @@ -50,11 +50,12 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call) struct ldap_BindRequest *req = &call->request.r.BindRequest; struct ldapsrv_reply *reply; struct ldap_BindResponse *resp; + struct ldapsrv_connection *conn; int result; const char *errstr; NTSTATUS status = NT_STATUS_OK; NTSTATUS sasl_status; - /*BOOL ret;*/ + BOOL ret; DEBUG(10, ("BindSASL dn: %s\n",req->dn)); @@ -69,7 +70,8 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call) gensec_set_target_service(call->conn->gensec, "ldap"); - /*gensec_want_feature(call->conn->gensec, GENSEC_WANT_SIGN|GENSEC_WANT_SEAL);*/ + gensec_want_feature(call->conn->gensec, GENSEC_FEATURE_SIGN); + gensec_want_feature(call->conn->gensec, GENSEC_FEATURE_SEAL); status = gensec_start_mech_by_sasl_name(call->conn->gensec, req->creds.SASL.mechanism); if (!NT_STATUS_IS_OK(status)) { @@ -85,6 +87,8 @@ reply: return NT_STATUS_NO_MEMORY; } resp = &reply->msg.r.BindResponse; + + conn = call->conn; if (NT_STATUS_IS_OK(status)) { status = gensec_update(call->conn->gensec, reply, @@ -118,17 +122,14 @@ reply: return status; } -/* ret = ldapsrv_append_to_buf(&call->conn->sasl_out_buffer, call->conn->out_buffer.data, call->conn->out_buffer.length); + ret = ldapsrv_append_to_buf(&conn->sasl_out_buffer, conn->out_buffer.data, conn->out_buffer.length); if (!ret) { return NT_STATUS_NO_MEMORY; } - ldapsrv_consumed_from_buf(&call->conn->out_buffer, call->conn->out_buffer.length); - - status = gensec_session_info(call->conn->gensec, &call->conn->session_info); - if (!NT_STATUS_IS_OK(status)) { - return status; + ldapsrv_consumed_from_buf(&conn->out_buffer, conn->out_buffer.length); + if (NT_STATUS_IS_OK(status)) { + status = gensec_session_info(conn->gensec, &conn->session_info); } -*/ return status; } diff --git a/source4/ldap_server/ldap_server.c b/source4/ldap_server/ldap_server.c index ea1b8cb9b4..0bace4b690 100644 --- a/source4/ldap_server/ldap_server.c +++ b/source4/ldap_server/ldap_server.c @@ -131,7 +131,7 @@ static void ldapsrv_init(struct server_service *service, void ldapsrv_consumed_from_buf(struct rw_buffer *buf, size_t length) { - memcpy(buf->data, buf->data+length, buf->length-length); + memmove(buf->data, buf->data+length, buf->length-length); buf->length -= length; } @@ -186,7 +186,8 @@ static BOOL ldapsrv_read_buf(struct ldapsrv_connection *conn) { NTSTATUS status; DATA_BLOB tmp_blob; - DATA_BLOB creds; + DATA_BLOB wrapped; + DATA_BLOB unwrapped; BOOL ret; uint8_t *buf; size_t buf_length, sasl_length; @@ -194,9 +195,14 @@ static BOOL ldapsrv_read_buf(struct ldapsrv_connection *conn) TALLOC_CTX *mem_ctx; size_t nread; - if (!conn->gensec || !conn->session_info || - !(gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN) && - gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL))) { + if (!conn->gensec) { + return read_into_buf(sock, &conn->in_buffer); + } + if (!conn->session_info) { + return read_into_buf(sock, &conn->in_buffer); + } + if (!(gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN) || + gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL))) { return read_into_buf(sock, &conn->in_buffer); } @@ -236,47 +242,25 @@ static BOOL ldapsrv_read_buf(struct ldapsrv_connection *conn) sasl_length = RIVAL(buf, 0); - if (buf_length < (4 + sasl_length)) { + if ((buf_length - 4) < sasl_length) { /* not enough yet */ talloc_free(mem_ctx); return True; } - creds.data = buf + 4; - creds.length = gensec_sig_size(conn->gensec); + wrapped.data = buf + 4; + wrapped.length = sasl_length; - if (creds.length > sasl_length) { - /* invalid packet? */ + status = gensec_unwrap(conn->gensec, mem_ctx, + &wrapped, + &unwrapped); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("gensec_unwrap: %s\n",nt_errstr(status))); talloc_free(mem_ctx); return False; } - tmp_blob.data = buf + (4 + creds.length); - tmp_blob.length = (4 + sasl_length) - (4 + creds.length); - - if (gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL)) { - status = gensec_unseal_packet(conn->gensec, mem_ctx, - tmp_blob.data, tmp_blob.length, - tmp_blob.data, tmp_blob.length, - &creds); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("gensec_unseal_packet: %s\n",nt_errstr(status))); - talloc_free(mem_ctx); - return False; - } - } else { - status = gensec_check_packet(conn->gensec, mem_ctx, - tmp_blob.data, tmp_blob.length, - tmp_blob.data, tmp_blob.length, - &creds); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("gensec_check_packet: %s\n",nt_errstr(status))); - talloc_free(mem_ctx); - return False; - } - } - - ret = ldapsrv_append_to_buf(&conn->in_buffer, tmp_blob.data, tmp_blob.length); + ret = ldapsrv_append_to_buf(&conn->in_buffer, unwrapped.data, unwrapped.length); if (!ret) { talloc_free(mem_ctx); return False; @@ -311,17 +295,23 @@ static BOOL write_from_buf(struct socket_context *sock, struct rw_buffer *buf) static BOOL ldapsrv_write_buf(struct ldapsrv_connection *conn) { NTSTATUS status; + DATA_BLOB wrapped; DATA_BLOB tmp_blob; - DATA_BLOB creds; DATA_BLOB sasl; size_t sendlen; BOOL ret; struct socket_context *sock = conn->connection->socket; TALLOC_CTX *mem_ctx; - if (!conn->gensec || !conn->session_info || - !(gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN) && - gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL))) { + + if (!conn->gensec) { + return write_from_buf(sock, &conn->out_buffer); + } + if (!conn->session_info) { + return write_from_buf(sock, &conn->out_buffer); + } + if (!(gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN) || + gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL))) { return write_from_buf(sock, &conn->out_buffer); } @@ -331,52 +321,37 @@ static BOOL ldapsrv_write_buf(struct ldapsrv_connection *conn) return False; } - tmp_blob.data = conn->out_buffer.data; - tmp_blob.length = conn->out_buffer.length; - - if (tmp_blob.length == 0) { + if (conn->out_buffer.length == 0) { goto nodata; } - if (gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL)) { - status = gensec_seal_packet(conn->gensec, mem_ctx, - tmp_blob.data, tmp_blob.length, - tmp_blob.data, tmp_blob.length, - &creds); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("gensec_seal_packet: %s\n",nt_errstr(status))); - talloc_free(mem_ctx); - return False; - } - } else { - status = gensec_sign_packet(conn->gensec, mem_ctx, - tmp_blob.data, tmp_blob.length, - tmp_blob.data, tmp_blob.length, - &creds); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("gensec_sign_packet: %s\n",nt_errstr(status))); - talloc_free(mem_ctx); - return False; - } + tmp_blob.data = conn->out_buffer.data; + tmp_blob.length = conn->out_buffer.length; + status = gensec_wrap(conn->gensec, mem_ctx, + &tmp_blob, + &wrapped); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("gensec_wrap: %s\n",nt_errstr(status))); + talloc_free(mem_ctx); + return False; } - sasl = data_blob_talloc(mem_ctx, NULL, 4 + creds.length + tmp_blob.length); + sasl = data_blob_talloc(mem_ctx, NULL, 4 + wrapped.length); if (!sasl.data) { DEBUG(0,("no memory\n")); talloc_free(mem_ctx); return False; } - RSIVAL(sasl.data, 0, creds.length + tmp_blob.length); - memcpy(sasl.data + 4, creds.data, creds.length); - memcpy(sasl.data + 4 + creds.length, tmp_blob.data, tmp_blob.length); + RSIVAL(sasl.data, 0, wrapped.length); + memcpy(sasl.data + 4, wrapped.data, wrapped.length); ret = ldapsrv_append_to_buf(&conn->sasl_out_buffer, sasl.data, sasl.length); if (!ret) { talloc_free(mem_ctx); return False; } - ldapsrv_consumed_from_buf(&conn->out_buffer, tmp_blob.length); + ldapsrv_consumed_from_buf(&conn->out_buffer, conn->out_buffer.length); nodata: tmp_blob.data = conn->sasl_out_buffer.data; tmp_blob.length = conn->sasl_out_buffer.length; diff --git a/source4/libcli/auth/gensec.c b/source4/libcli/auth/gensec.c index 75086f9281..79cd98a076 100644 --- a/source4/libcli/auth/gensec.c +++ b/source4/libcli/auth/gensec.c @@ -137,7 +137,6 @@ static NTSTATUS gensec_start(TALLOC_CTX *mem_ctx, struct gensec_security **gense (*gensec_security)->subcontext = False; (*gensec_security)->want_features = 0; - (*gensec_security)->have_features = 0; return NT_STATUS_OK; } @@ -395,6 +394,28 @@ size_t gensec_sig_size(struct gensec_security *gensec_security) return gensec_security->ops->sig_size(gensec_security); } +NTSTATUS gensec_wrap(struct gensec_security *gensec_security, + TALLOC_CTX *mem_ctx, + const DATA_BLOB *in, + DATA_BLOB *out) +{ + if (!gensec_security->ops->wrap) { + return NT_STATUS_NOT_IMPLEMENTED; + } + return gensec_security->ops->wrap(gensec_security, mem_ctx, in, out); +} + +NTSTATUS gensec_unwrap(struct gensec_security *gensec_security, + TALLOC_CTX *mem_ctx, + const DATA_BLOB *in, + DATA_BLOB *out) +{ + if (!gensec_security->ops->unwrap) { + return NT_STATUS_NOT_IMPLEMENTED; + } + return gensec_security->ops->unwrap(gensec_security, mem_ctx, in, out); +} + NTSTATUS gensec_session_key(struct gensec_security *gensec_security, DATA_BLOB *session_key) { @@ -459,11 +480,10 @@ void gensec_want_feature(struct gensec_security *gensec_security, BOOL gensec_have_feature(struct gensec_security *gensec_security, uint32 feature) { - if (gensec_security->have_features & feature) { - return True; + if (!gensec_security->ops->have_feature) { + return False; } - - return False; + return gensec_security->ops->have_feature(gensec_security, feature); } /** diff --git a/source4/libcli/auth/gensec.h b/source4/libcli/auth/gensec.h index 2b44f0d902..7c462414ff 100644 --- a/source4/libcli/auth/gensec.h +++ b/source4/libcli/auth/gensec.h @@ -81,9 +81,19 @@ struct gensec_security_ops { uint8_t *data, size_t length, const uint8_t *whole_pdu, size_t pdu_length, DATA_BLOB *sig); + NTSTATUS (*wrap)(struct gensec_security *gensec_security, + TALLOC_CTX *mem_ctx, + const DATA_BLOB *in, + DATA_BLOB *out); + NTSTATUS (*unwrap)(struct gensec_security *gensec_security, + TALLOC_CTX *mem_ctx, + const DATA_BLOB *in, + DATA_BLOB *out); NTSTATUS (*session_key)(struct gensec_security *gensec_security, DATA_BLOB *session_key); NTSTATUS (*session_info)(struct gensec_security *gensec_security, struct auth_session_info **session_info); + BOOL (*have_feature)(struct gensec_security *gensec_security, + uint32 feature); }; #define GENSEC_INTERFACE_VERSION 0 @@ -99,7 +109,6 @@ struct gensec_security { enum gensec_role gensec_role; BOOL subcontext; uint32 want_features; - uint32 have_features; }; /* this structure is used by backends to determine the size of some critical types */ diff --git a/source4/libcli/auth/gensec_krb5.c b/source4/libcli/auth/gensec_krb5.c index 86e76c5586..f55006c644 100644 --- a/source4/libcli/auth/gensec_krb5.c +++ b/source4/libcli/auth/gensec_krb5.c @@ -691,6 +691,16 @@ static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security return nt_status; } +static BOOL gensec_krb5_have_feature(struct gensec_security *gensec_security, + uint32 feature) +{ + if (feature & GENSEC_FEATURE_SESSION_KEY) { + return True; + } + + return False; +} + static const struct gensec_security_ops gensec_krb5_security_ops = { .name = "krb5", @@ -701,6 +711,7 @@ static const struct gensec_security_ops gensec_krb5_security_ops = { .update = gensec_krb5_update, .session_key = gensec_krb5_session_key, .session_info = gensec_krb5_session_info, + .have_feature = gensec_krb5_have_feature, }; static const struct gensec_security_ops gensec_ms_krb5_security_ops = { @@ -712,6 +723,7 @@ static const struct gensec_security_ops gensec_ms_krb5_security_ops = { .update = gensec_krb5_update, .session_key = gensec_krb5_session_key, .session_info = gensec_krb5_session_info, + .have_feature = gensec_krb5_have_feature, }; diff --git a/source4/libcli/auth/gensec_ntlmssp.c b/source4/libcli/auth/gensec_ntlmssp.c index cf8019402c..10b71ca8b0 100644 --- a/source4/libcli/auth/gensec_ntlmssp.c +++ b/source4/libcli/auth/gensec_ntlmssp.c @@ -28,6 +28,7 @@ struct gensec_ntlmssp_state { struct auth_context *auth_context; struct auth_serversupplied_info *server_info; struct ntlmssp_state *ntlmssp_state; + uint32 have_features; }; @@ -171,6 +172,7 @@ static NTSTATUS gensec_ntlmssp_start(struct gensec_security *gensec_security) gensec_ntlmssp_state->ntlmssp_state = NULL; gensec_ntlmssp_state->auth_context = NULL; gensec_ntlmssp_state->server_info = NULL; + gensec_ntlmssp_state->have_features = 0; talloc_set_destructor(gensec_ntlmssp_state, gensec_ntlmssp_destroy); @@ -341,6 +343,99 @@ static size_t gensec_ntlmssp_sig_size(struct gensec_security *gensec_security) return NTLMSSP_SIG_SIZE; } +static NTSTATUS gensec_ntlmssp_wrap(struct gensec_security *gensec_security, + TALLOC_CTX *mem_ctx, + const DATA_BLOB *in, + DATA_BLOB *out) +{ + struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data; + DATA_BLOB sig; + NTSTATUS nt_status; + + if (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) { + + *out = data_blob_talloc(mem_ctx, NULL, in->length + NTLMSSP_SIG_SIZE); + memcpy(out->data + NTLMSSP_SIG_SIZE, in->data, in->length); + + nt_status = ntlmssp_seal_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, + out->data + NTLMSSP_SIG_SIZE, + out->length - NTLMSSP_SIG_SIZE, + out->data + NTLMSSP_SIG_SIZE, + out->length - NTLMSSP_SIG_SIZE, + &sig); + + if (NT_STATUS_IS_OK(nt_status)) { + memcpy(out->data, sig.data, NTLMSSP_SIG_SIZE); + } + return nt_status; + + } else if ((gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) + || (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) { + + *out = data_blob_talloc(mem_ctx, NULL, in->length + NTLMSSP_SIG_SIZE); + memcpy(out->data + NTLMSSP_SIG_SIZE, in->data, in->length); + + nt_status = ntlmssp_sign_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, + out->data + NTLMSSP_SIG_SIZE, + out->length - NTLMSSP_SIG_SIZE, + out->data + NTLMSSP_SIG_SIZE, + out->length - NTLMSSP_SIG_SIZE, + &sig); + + if (NT_STATUS_IS_OK(nt_status)) { + memcpy(out->data, sig.data, NTLMSSP_SIG_SIZE); + } + return nt_status; + + } else { + *out = *in; + return NT_STATUS_OK; + } +} + + +static NTSTATUS gensec_ntlmssp_unwrap(struct gensec_security *gensec_security, + TALLOC_CTX *mem_ctx, + const DATA_BLOB *in, + DATA_BLOB *out) +{ + struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data; + DATA_BLOB sig; + + if (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) { + if (in->length < NTLMSSP_SIG_SIZE) { + return NT_STATUS_INVALID_PARAMETER; + } + sig.data = in->data; + sig.length = NTLMSSP_SIG_SIZE; + + *out = data_blob_talloc(mem_ctx, in->data + NTLMSSP_SIG_SIZE, in->length - NTLMSSP_SIG_SIZE); + + return ntlmssp_unseal_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, + out->data, out->length, + out->data, out->length, + &sig); + + } else if ((gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) + || (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) { + if (in->length < NTLMSSP_SIG_SIZE) { + return NT_STATUS_INVALID_PARAMETER; + } + sig.data = in->data; + sig.length = NTLMSSP_SIG_SIZE; + + *out = data_blob_talloc(mem_ctx, in->data + NTLMSSP_SIG_SIZE, in->length - NTLMSSP_SIG_SIZE); + + return ntlmssp_check_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, + out->data, out->length, + out->data, out->length, + &sig); + } else { + *out = *in; + return NT_STATUS_OK; + } +} + static NTSTATUS gensec_ntlmssp_session_key(struct gensec_security *gensec_security, DATA_BLOB *session_key) { @@ -371,17 +466,19 @@ static NTSTATUS gensec_ntlmssp_update(struct gensec_security *gensec_security, T if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) { return status; } + + gensec_ntlmssp_state->have_features = 0; if (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) { - gensec_security->have_features |= GENSEC_FEATURE_SIGN; + gensec_ntlmssp_state->have_features |= GENSEC_FEATURE_SIGN; } if (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) { - gensec_security->have_features |= GENSEC_FEATURE_SEAL; + gensec_ntlmssp_state->have_features |= GENSEC_FEATURE_SEAL; } if (gensec_ntlmssp_state->ntlmssp_state->session_key.data) { - gensec_security->have_features |= GENSEC_FEATURE_SESSION_KEY; + gensec_ntlmssp_state->have_features |= GENSEC_FEATURE_SESSION_KEY; } return status; @@ -418,6 +515,17 @@ static NTSTATUS gensec_ntlmssp_session_info(struct gensec_security *gensec_secur return NT_STATUS_OK; } +static BOOL gensec_ntlmssp_have_feature(struct gensec_security *gensec_security, + uint32 feature) +{ + struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data; + if (gensec_ntlmssp_state->have_features & feature) { + return True; + } + + return False; +} + static const struct gensec_security_ops gensec_ntlmssp_security_ops = { .name = "ntlmssp", .sasl_name = "NTLM", @@ -431,8 +539,11 @@ static const struct gensec_security_ops gensec_ntlmssp_security_ops = { .sign_packet = gensec_ntlmssp_sign_packet, .check_packet = gensec_ntlmssp_check_packet, .unseal_packet = gensec_ntlmssp_unseal_packet, + .wrap = gensec_ntlmssp_wrap, + .unwrap = gensec_ntlmssp_unwrap, .session_key = gensec_ntlmssp_session_key, .session_info = gensec_ntlmssp_session_info, + .have_feature = gensec_ntlmssp_have_feature }; diff --git a/source4/libcli/auth/spnego.c b/source4/libcli/auth/spnego.c index 4f1dc57e9d..f13bbc11b4 100644 --- a/source4/libcli/auth/spnego.c +++ b/source4/libcli/auth/spnego.c @@ -162,6 +162,40 @@ static NTSTATUS gensec_spnego_sign_packet(struct gensec_security *gensec_securit sig); } +static NTSTATUS gensec_spnego_wrap(struct gensec_security *gensec_security, + TALLOC_CTX *mem_ctx, + const DATA_BLOB *in, + DATA_BLOB *out) +{ + struct spnego_state *spnego_state = gensec_security->private_data; + + if (spnego_state->state_position != SPNEGO_DONE + && spnego_state->state_position != SPNEGO_FALLBACK) { + DEBUG(1, ("gensec_spnego_wrap: wrong state for wrap\n")); + return NT_STATUS_INVALID_PARAMETER; + } + + return gensec_wrap(spnego_state->sub_sec_security, + mem_ctx, in, out); +} + +static NTSTATUS gensec_spnego_unwrap(struct gensec_security *gensec_security, + TALLOC_CTX *mem_ctx, + const DATA_BLOB *in, + DATA_BLOB *out) +{ + struct spnego_state *spnego_state = gensec_security->private_data; + + if (spnego_state->state_position != SPNEGO_DONE + && spnego_state->state_position != SPNEGO_FALLBACK) { + DEBUG(1, ("gensec_spnego_unwrap: wrong state for unwrap\n")); + return NT_STATUS_INVALID_PARAMETER; + } + + return gensec_unwrap(spnego_state->sub_sec_security, + mem_ctx, in, out); +} + static size_t gensec_spnego_sig_size(struct gensec_security *gensec_security) { struct spnego_state *spnego_state = gensec_security->private_data; @@ -357,11 +391,11 @@ static NTSTATUS gensec_spnego_client_negTokenInit(struct gensec_security *gensec spnego_state->expected_packet = SPNEGO_NEG_TOKEN_TARG; spnego_state->state_position = SPNEGO_CLIENT_TARG; return nt_status; - } + } talloc_free(spnego_state->sub_sec_security); spnego_state->sub_sec_security = NULL; - DEBUG(1, ("Failed to setup SPNEGO netTokenInit request\n")); + DEBUG(1, ("Failed to setup SPNEGO negTokenInit request: %s\n", nt_errstr(nt_status))); return NT_STATUS_INVALID_PARAMETER; } @@ -698,6 +732,18 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA return NT_STATUS_INVALID_PARAMETER; } +static BOOL gensec_spnego_have_feature(struct gensec_security *gensec_security, + uint32 feature) +{ + struct spnego_state *spnego_state = gensec_security->private_data; + if (!spnego_state->sub_sec_security) { + return False; + } + + return gensec_have_feature(spnego_state->sub_sec_security, + feature); +} + static const struct gensec_security_ops gensec_spnego_security_ops = { .name = "spnego", .sasl_name = "GSS-SPNEGO", @@ -711,8 +757,11 @@ static const struct gensec_security_ops gensec_spnego_security_ops = { .sig_size = gensec_spnego_sig_size, .check_packet = gensec_spnego_check_packet, .unseal_packet = gensec_spnego_unseal_packet, + .wrap = gensec_spnego_wrap, + .unwrap = gensec_spnego_unwrap, .session_key = gensec_spnego_session_key, .session_info = gensec_spnego_session_info, + .have_feature = gensec_spnego_have_feature }; NTSTATUS gensec_spnego_init(void) diff --git a/source4/librpc/rpc/dcerpc_schannel.c b/source4/librpc/rpc/dcerpc_schannel.c index 6df48b7dd3..d58f58625e 100644 --- a/source4/librpc/rpc/dcerpc_schannel.c +++ b/source4/librpc/rpc/dcerpc_schannel.c @@ -289,10 +289,6 @@ static NTSTATUS dcerpc_schannel_start(struct gensec_security *gensec_security) dce_schan_state->state = DCERPC_SCHANNEL_STATE_START; gensec_security->private_data = dce_schan_state; - gensec_security->have_features = - GENSEC_FEATURE_SESSION_KEY | - GENSEC_FEATURE_SIGN | - GENSEC_FEATURE_SEAL; talloc_set_destructor(dce_schan_state, dcerpc_schannel_destroy); @@ -513,6 +509,18 @@ NTSTATUS dcerpc_bind_auth_schannel(struct dcerpc_pipe *p, creds); } +static BOOL dcerpc_schannel_have_feature(struct gensec_security *gensec_security, + uint32 feature) +{ + if (feature & (GENSEC_FEATURE_SESSION_KEY | + GENSEC_FEATURE_SIGN | + GENSEC_FEATURE_SEAL)) { + return True; + } + return False; +} + + static const struct gensec_security_ops gensec_dcerpc_schannel_security_ops = { .name = "dcerpc_schannel", .auth_type = DCERPC_AUTH_TYPE_SCHANNEL, @@ -526,6 +534,7 @@ static const struct gensec_security_ops gensec_dcerpc_schannel_security_ops = { .session_key = dcerpc_schannel_session_key, .session_info = dcerpc_schannel_session_info, .sig_size = dcerpc_schannel_sig_size, + .have_feature = dcerpc_schannel_have_feature }; NTSTATUS gensec_dcerpc_schannel_init(void) diff --git a/source4/torture/ldap/common.c b/source4/torture/ldap/common.c index eea3b12073..162934a38d 100644 --- a/source4/torture/ldap/common.c +++ b/source4/torture/ldap/common.c @@ -57,7 +57,7 @@ NTSTATUS torture_ldap_bind_sasl(struct ldap_connection *conn, const char *userna result = ldap_bind_sasl(conn, username, domain, password); if (result != LDAP_SUCCESS) { - printf("Failed to bind with provided credentialsi and SASL mechanism\n"); + printf("Failed to bind with provided credentials and SASL mechanism\n"); /* FIXME: what abut actually implementing an ldap_connection_free() function ? :-) sss */ return status; @@ -109,9 +109,9 @@ BOOL ldap_sasl_send_msg(struct ldap_connection *conn, struct ldap_message *msg, NTSTATUS status; DATA_BLOB request; BOOL result; - DATA_BLOB creds; - DATA_BLOB pdu; + DATA_BLOB wrapped; int len; + char length[4]; struct asn1_data asn1; TALLOC_CTX *mem_ctx; @@ -120,53 +120,48 @@ BOOL ldap_sasl_send_msg(struct ldap_connection *conn, struct ldap_message *msg, if (!ldap_encode(msg, &request)) return False; - status = gensec_seal_packet(conn->gensec, - msg->mem_ctx, - request.data, request.length, - request.data, request.length, - &creds); + status = gensec_wrap(conn->gensec, + msg->mem_ctx, + &request, + &wrapped); if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("gensec_seal_packet: %s\n",nt_errstr(status))); + DEBUG(0,("gensec_wrap: %s\n",nt_errstr(status))); return False; } - len = 4 + creds.length + request.length; - pdu = data_blob_talloc(msg->mem_ctx, NULL, len); - RSIVAL(pdu.data, 0, len-4); - memcpy(pdu.data + 4, creds.data, creds.length); - memcpy(pdu.data + 4 + creds.length, request.data, request.length); + RSIVAL(length, 0, wrapped.length); - result = (write_data_until(conn->sock, pdu.data, pdu.length, - endtime) == pdu.length); + result = (write_data_until(conn->sock, length, 4, + endtime) == 4); if (!result) return result; - pdu = data_blob(NULL, 0x4000); - data_blob_clear(&pdu); - - result = (read_data_until(conn->sock, pdu.data, 4, NULL) == 4); + result = (write_data_until(conn->sock, wrapped.data, wrapped.length, + endtime) == wrapped.length); if (!result) return result; - len = RIVAL(pdu.data,0); + wrapped = data_blob(NULL, 0x4000); + data_blob_clear(&wrapped); - result = (read_data_until(conn->sock, pdu.data + 4, MIN(0x4000,len), NULL) == len); + result = (read_data_until(conn->sock, length, 4, NULL) == 4); if (!result) return result; - pdu.length = 4+len; + len = RIVAL(length,0); - creds = data_blob(pdu.data + 4 , gensec_sig_size(conn->gensec)); + result = (read_data_until(conn->sock, wrapped.data, MIN(wrapped.length,len), NULL) == len); + if (!result) + return result; - request = data_blob(pdu.data + (4 + creds.length), pdu.length - (4 + creds.length)); + wrapped.length = len; - status = gensec_unseal_packet(conn->gensec, - msg->mem_ctx, - request.data, request.length, - request.data, request.length, - &creds); + status = gensec_unwrap(conn->gensec, + msg->mem_ctx, + &wrapped, + &request); if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("gensec_unseal_packet: %s\n",nt_errstr(status))); + DEBUG(0,("gensec_unwrap: %s\n",nt_errstr(status))); return False; } -- cgit