diff options
Diffstat (limited to 'source4/libcli')
-rw-r--r-- | source4/libcli/auth/gensec.c | 30 | ||||
-rw-r--r-- | source4/libcli/auth/gensec.h | 11 | ||||
-rw-r--r-- | source4/libcli/auth/gensec_krb5.c | 12 | ||||
-rw-r--r-- | source4/libcli/auth/gensec_ntlmssp.c | 117 | ||||
-rw-r--r-- | source4/libcli/auth/spnego.c | 53 |
5 files changed, 212 insertions, 11 deletions
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) |