summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2011-12-27 12:27:11 +1100
committerStefan Metzmacher <metze@samba.org>2012-01-06 08:12:49 +0100
commit27af0ffdf224a71c7532a22039f455bff6adfb41 (patch)
treee4545912f060e88fbef1e734fc6d9ad3e2ca6b77
parenta00032a92d9c0fcd4fa3f551abb901e5240f780f (diff)
downloadsamba-27af0ffdf224a71c7532a22039f455bff6adfb41.tar.gz
samba-27af0ffdf224a71c7532a22039f455bff6adfb41.tar.bz2
samba-27af0ffdf224a71c7532a22039f455bff6adfb41.zip
s3-libads Use NTLMSSP via auth_generic/gensec
This allows us to use the shared gensec_wrap() implementation already used by the smb sealing code, as well as making this code more generic. Andrew Bartlett Signed-off-by: Stefan Metzmacher <metze@samba.org>
-rw-r--r--source3/libads/sasl.c169
1 files changed, 79 insertions, 90 deletions
diff --git a/source3/libads/sasl.c b/source3/libads/sasl.c
index a39971eafb..4186841ad4 100644
--- a/source3/libads/sasl.c
+++ b/source3/libads/sasl.c
@@ -19,7 +19,8 @@
#include "includes.h"
#include "../libcli/auth/spnego.h"
-#include "../auth/ntlmssp/ntlmssp.h"
+#include "auth/gensec/gensec.h"
+#include "auth_generic.h"
#include "ads.h"
#include "smb_krb5.h"
@@ -27,88 +28,77 @@
static ADS_STATUS ads_sasl_ntlmssp_wrap(ADS_STRUCT *ads, uint8 *buf, uint32 len)
{
- struct ntlmssp_state *ntlmssp_state =
- (struct ntlmssp_state *)ads->ldap.wrap_private_data;
- ADS_STATUS status;
+ struct gensec_security *gensec_security =
+ talloc_get_type_abort(ads->ldap.wrap_private_data,
+ struct gensec_security);
NTSTATUS nt_status;
- DATA_BLOB sig;
- TALLOC_CTX *frame;
- uint8 *dptr = ads->ldap.out.buf + (4 + NTLMSSP_SIG_SIZE);
-
- frame = talloc_stackframe();
- /* copy the data to the right location */
- memcpy(dptr, buf, len);
-
- /* create the signature and may encrypt the data */
- if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
- nt_status = ntlmssp_seal_packet(ntlmssp_state,
- frame,
- dptr, len,
- dptr, len,
- &sig);
- } else {
- nt_status = ntlmssp_sign_packet(ntlmssp_state,
- frame,
- dptr, len,
- dptr, len,
- &sig);
+ DATA_BLOB unwrapped, wrapped;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ unwrapped = data_blob_const(buf, len);
+
+ nt_status = gensec_wrap(gensec_security, frame, &unwrapped, &wrapped);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ TALLOC_FREE(frame);
+ return ADS_ERROR_NT(nt_status);
}
- status = ADS_ERROR_NT(nt_status);
- if (!ADS_ERR_OK(status)) return status;
- /* copy the signature to the right location */
- memcpy(ads->ldap.out.buf + 4,
- sig.data, NTLMSSP_SIG_SIZE);
+ if ((ads->ldap.out.size - 4) < wrapped.length) {
+ return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
+ }
- TALLOC_FREE(frame);
+ /* copy the wrapped blob to the right location */
+ memcpy(ads->ldap.out.buf + 4, wrapped.data, wrapped.length);
/* set how many bytes must be written to the underlying socket */
- ads->ldap.out.left = 4 + NTLMSSP_SIG_SIZE + len;
+ ads->ldap.out.left = 4 + wrapped.length;
+
+ TALLOC_FREE(frame);
return ADS_SUCCESS;
}
static ADS_STATUS ads_sasl_ntlmssp_unwrap(ADS_STRUCT *ads)
{
- struct ntlmssp_state *ntlmssp_state =
- (struct ntlmssp_state *)ads->ldap.wrap_private_data;
- ADS_STATUS status;
+ struct gensec_security *gensec_security =
+ talloc_get_type_abort(ads->ldap.wrap_private_data,
+ struct gensec_security);
NTSTATUS nt_status;
- DATA_BLOB sig;
- uint8 *dptr = ads->ldap.in.buf + (4 + NTLMSSP_SIG_SIZE);
- uint32 dlen = ads->ldap.in.ofs - (4 + NTLMSSP_SIG_SIZE);
-
- /* wrap the signature into a DATA_BLOB */
- sig = data_blob_const(ads->ldap.in.buf + 4, NTLMSSP_SIG_SIZE);
-
- /* verify the signature and maybe decrypt the data */
- if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
- nt_status = ntlmssp_unseal_packet(ntlmssp_state,
- dptr, dlen,
- dptr, dlen,
- &sig);
- } else {
- nt_status = ntlmssp_check_packet(ntlmssp_state,
- dptr, dlen,
- dptr, dlen,
- &sig);
+ DATA_BLOB unwrapped, wrapped;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ wrapped = data_blob_const(ads->ldap.in.buf + 4, ads->ldap.in.ofs - 4);
+
+ nt_status = gensec_unwrap(gensec_security, frame, &wrapped, &unwrapped);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ TALLOC_FREE(frame);
+ return ADS_ERROR_NT(nt_status);
+ }
+
+ if (wrapped.length < unwrapped.length) {
+ TALLOC_FREE(frame);
+ return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
}
- status = ADS_ERROR_NT(nt_status);
- if (!ADS_ERR_OK(status)) return status;
- /* set the amount of bytes for the upper layer and set the ofs to the data */
- ads->ldap.in.left = dlen;
- ads->ldap.in.ofs = 4 + NTLMSSP_SIG_SIZE;
+ /* copy the wrapped blob to the right location */
+ memcpy(ads->ldap.in.buf + 4, unwrapped.data, unwrapped.length);
+
+ /* set how many bytes must be written to the underlying socket */
+ ads->ldap.in.left = unwrapped.length;
+ ads->ldap.in.ofs = 4;
+
+ TALLOC_FREE(frame);
return ADS_SUCCESS;
}
static void ads_sasl_ntlmssp_disconnect(ADS_STRUCT *ads)
{
- struct ntlmssp_state *ntlmssp_state =
- (struct ntlmssp_state *)ads->ldap.wrap_private_data;
+ struct gensec_security *gensec_security =
+ talloc_get_type_abort(ads->ldap.wrap_private_data,
+ struct gensec_security);
- TALLOC_FREE(ntlmssp_state);
+ TALLOC_FREE(gensec_security);
ads->ldap.wrap_ops = NULL;
ads->ldap.wrap_private_data = NULL;
@@ -136,42 +126,39 @@ static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads)
NTSTATUS nt_status;
ADS_STATUS status;
int turn = 1;
- uint32 features = 0;
- struct ntlmssp_state *ntlmssp_state;
+ struct auth_generic_state *auth_generic_state;
- nt_status = ntlmssp_client_start(NULL,
- lp_netbios_name(),
- lp_workgroup(),
- lp_client_ntlmv2_auth(),
- &ntlmssp_state);
+ nt_status = auth_generic_client_prepare(NULL, &auth_generic_state);
if (!NT_STATUS_IS_OK(nt_status)) {
return ADS_ERROR_NT(nt_status);
}
- if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, ads->auth.user_name))) {
+ if (!NT_STATUS_IS_OK(nt_status = auth_generic_set_username(auth_generic_state, ads->auth.user_name))) {
return ADS_ERROR_NT(nt_status);
}
- if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, ads->auth.realm))) {
+ if (!NT_STATUS_IS_OK(nt_status = auth_generic_set_domain(auth_generic_state, ads->auth.realm))) {
return ADS_ERROR_NT(nt_status);
}
- if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, ads->auth.password))) {
+ if (!NT_STATUS_IS_OK(nt_status = auth_generic_set_password(auth_generic_state, ads->auth.password))) {
return ADS_ERROR_NT(nt_status);
}
switch (ads->ldap.wrap_type) {
case ADS_SASLWRAP_TYPE_SEAL:
- features = NTLMSSP_FEATURE_SIGN | NTLMSSP_FEATURE_SEAL;
+ gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SIGN);
+ gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SEAL);
break;
case ADS_SASLWRAP_TYPE_SIGN:
if (ads->auth.flags & ADS_AUTH_SASL_FORCE) {
- features = NTLMSSP_FEATURE_SIGN;
+ gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SIGN);
} else {
/*
* windows servers are broken with sign only,
* so we need to use seal here too
*/
- features = NTLMSSP_FEATURE_SIGN | NTLMSSP_FEATURE_SEAL;
+ gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SIGN);
+ gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SEAL);
ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SEAL;
}
break;
@@ -179,13 +166,16 @@ static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads)
break;
}
- ntlmssp_want_feature(ntlmssp_state, features);
+ nt_status = auth_generic_client_start(auth_generic_state, GENSEC_OID_NTLMSSP);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return ADS_ERROR_NT(nt_status);
+ }
blob_in = data_blob_null;
do {
- nt_status = ntlmssp_update(ntlmssp_state,
- blob_in, &blob_out);
+ nt_status = gensec_update(auth_generic_state->gensec_security,
+ talloc_tos(), NULL, blob_in, &blob_out);
data_blob_free(&blob_in);
if ((NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)
|| NT_STATUS_IS_OK(nt_status))
@@ -212,7 +202,7 @@ static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads)
ber_bvfree(scred);
}
- TALLOC_FREE(ntlmssp_state);
+ TALLOC_FREE(auth_generic_state);
return ADS_ERROR(rc);
}
if (scred) {
@@ -224,7 +214,7 @@ static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads)
} else {
- TALLOC_FREE(ntlmssp_state);
+ TALLOC_FREE(auth_generic_state);
data_blob_free(&blob_out);
return ADS_ERROR_NT(nt_status);
}
@@ -236,7 +226,7 @@ static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads)
if (!spnego_parse_challenge(talloc_tos(), blob, &blob_in,
&tmp_blob)) {
- TALLOC_FREE(ntlmssp_state);
+ TALLOC_FREE(auth_generic_state);
data_blob_free(&blob);
DEBUG(3,("Failed to parse challenges\n"));
return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
@@ -246,7 +236,7 @@ static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads)
if (!spnego_parse_auth_response(talloc_tos(), blob, nt_status, OID_NTLMSSP,
&blob_in)) {
- TALLOC_FREE(ntlmssp_state);
+ TALLOC_FREE(auth_generic_state);
data_blob_free(&blob);
DEBUG(3,("Failed to parse auth response\n"));
return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
@@ -257,24 +247,23 @@ static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads)
turn++;
} while (rc == LDAP_SASL_BIND_IN_PROGRESS && !NT_STATUS_IS_OK(nt_status));
- /* we have a reference conter on ntlmssp_state, if we are signing
- then the state will be kept by the signing engine */
-
if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
- ads->ldap.out.max_unwrapped = ADS_SASL_WRAPPING_OUT_MAX_WRAPPED - NTLMSSP_SIG_SIZE;
- ads->ldap.out.sig_size = NTLMSSP_SIG_SIZE;
+ uint32_t sig_size = gensec_sig_size(auth_generic_state->gensec_security, 0);
+ ads->ldap.out.max_unwrapped = ADS_SASL_WRAPPING_OUT_MAX_WRAPPED - sig_size;
+ ads->ldap.out.sig_size = sig_size;
ads->ldap.in.min_wrapped = ads->ldap.out.sig_size;
ads->ldap.in.max_wrapped = ADS_SASL_WRAPPING_IN_MAX_WRAPPED;
- status = ads_setup_sasl_wrapping(ads, &ads_sasl_ntlmssp_ops, ntlmssp_state);
+ status = ads_setup_sasl_wrapping(ads, &ads_sasl_ntlmssp_ops, auth_generic_state->gensec_security);
if (!ADS_ERR_OK(status)) {
DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
ads_errstr(status)));
- TALLOC_FREE(ntlmssp_state);
+ TALLOC_FREE(auth_generic_state);
return status;
}
- } else {
- TALLOC_FREE(ntlmssp_state);
+ /* Only keep the gensec_security element around long-term */
+ talloc_steal(NULL, auth_generic_state->gensec_security);
}
+ TALLOC_FREE(auth_generic_state);
return ADS_ERROR(rc);
}