*/
#include "includes.h"
+#include "../libcli/auth/spnego.h"
+#include "../libcli/auth/ntlmssp.h"
+#include "ads.h"
+#include "smb_krb5.h"
#ifdef HAVE_LDAP
ADS_STATUS status;
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);
memcpy(ads->ldap.out.buf + 4,
sig.data, NTLMSSP_SIG_SIZE);
- data_blob_free(&sig);
+ TALLOC_FREE(frame);
/* set how many bytes must be written to the underlying socket */
ads->ldap.out.left = 4 + NTLMSSP_SIG_SIZE + len;
struct ntlmssp_state *ntlmssp_state =
(struct ntlmssp_state *)ads->ldap.wrap_private_data;
- ntlmssp_end(&ntlmssp_state);
+ TALLOC_FREE(ntlmssp_state);
ads->ldap.wrap_ops = NULL;
ads->ldap.wrap_private_data = NULL;
struct ntlmssp_state *ntlmssp_state;
- if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) {
+ nt_status = ntlmssp_client_start(NULL,
+ global_myname(),
+ lp_workgroup(),
+ lp_client_ntlmv2_auth(),
+ &ntlmssp_state);
+ if (!NT_STATUS_IS_OK(nt_status)) {
return ADS_ERROR_NT(nt_status);
}
ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_SIGN;
|| NT_STATUS_IS_OK(nt_status))
&& blob_out.length) {
if (turn == 1) {
+ const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
/* and wrap it in a SPNEGO wrapper */
- msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out);
+ msg1 = spnego_gen_negTokenInit(talloc_tos(),
+ OIDs_ntlm, &blob_out, NULL);
} else {
/* wrap it in SPNEGO */
- msg1 = spnego_gen_auth(blob_out);
+ msg1 = spnego_gen_auth(talloc_tos(), blob_out);
}
data_blob_free(&blob_out);
ber_bvfree(scred);
}
- ntlmssp_end(&ntlmssp_state);
+ TALLOC_FREE(ntlmssp_state);
return ADS_ERROR(rc);
}
if (scred) {
} else {
- ntlmssp_end(&ntlmssp_state);
+ TALLOC_FREE(ntlmssp_state);
data_blob_free(&blob_out);
return ADS_ERROR_NT(nt_status);
}
(rc == LDAP_SASL_BIND_IN_PROGRESS)) {
DATA_BLOB tmp_blob = data_blob_null;
/* the server might give us back two challenges */
- if (!spnego_parse_challenge(blob, &blob_in,
+ if (!spnego_parse_challenge(talloc_tos(), blob, &blob_in,
&tmp_blob)) {
- ntlmssp_end(&ntlmssp_state);
+ TALLOC_FREE(ntlmssp_state);
data_blob_free(&blob);
DEBUG(3,("Failed to parse challenges\n"));
return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
data_blob_free(&tmp_blob);
} else if (rc == LDAP_SASL_BIND_IN_PROGRESS) {
- if (!spnego_parse_auth_response(blob, nt_status, OID_NTLMSSP,
+ if (!spnego_parse_auth_response(talloc_tos(), blob, nt_status, OID_NTLMSSP,
&blob_in)) {
- ntlmssp_end(&ntlmssp_state);
+ TALLOC_FREE(ntlmssp_state);
data_blob_free(&blob);
DEBUG(3,("Failed to parse auth response\n"));
return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
if (!ADS_ERR_OK(status)) {
DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
ads_errstr(status)));
- ntlmssp_end(&ntlmssp_state);
+ TALLOC_FREE(ntlmssp_state);
return status;
}
} else {
- ntlmssp_end(&ntlmssp_state);
+ TALLOC_FREE(ntlmssp_state);
}
return ADS_ERROR(rc);
#ifdef HAVE_GSSAPI
static ADS_STATUS ads_sasl_gssapi_wrap(ADS_STRUCT *ads, uint8 *buf, uint32 len)
{
- gss_ctx_id_t context_handle = ads->ldap.wrap_private_data;
+ gss_ctx_id_t context_handle = (gss_ctx_id_t)ads->ldap.wrap_private_data;
ADS_STATUS status;
int gss_rc;
uint32 minor_status;
static ADS_STATUS ads_sasl_gssapi_unwrap(ADS_STRUCT *ads)
{
- gss_ctx_id_t context_handle = ads->ldap.wrap_private_data;
+ gss_ctx_id_t context_handle = (gss_ctx_id_t)ads->ldap.wrap_private_data;
ADS_STATUS status;
int gss_rc;
uint32 minor_status;
return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED);
}
- if (wrapped.length < wrapped.length) {
+ if (wrapped.length < unwrapped.length) {
return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
}
static void ads_sasl_gssapi_disconnect(ADS_STRUCT *ads)
{
- gss_ctx_id_t context_handle = ads->ldap.wrap_private_data;
+ gss_ctx_id_t context_handle = (gss_ctx_id_t)ads->ldap.wrap_private_data;
uint32 minor_status;
gss_delete_sec_context(&minor_status, &context_handle, GSS_C_NO_BUFFER);
static ADS_STATUS ads_sasl_spnego_gsskrb5_bind(ADS_STRUCT *ads, const gss_name_t serv_name)
{
ADS_STATUS status;
- BOOL ok;
+ bool ok;
uint32 minor_status;
int gss_rc, rc;
gss_OID_desc krb5_mech_type =
/* and wrap that in a shiny SPNEGO wrapper */
unwrapped = data_blob_const(output_token.value, output_token.length);
- wrapped = gen_negTokenTarg(spnego_mechs, unwrapped);
+ wrapped = spnego_gen_negTokenInit(talloc_tos(),
+ spnego_mechs, &unwrapped, NULL);
gss_release_buffer(&minor_status, &output_token);
if (unwrapped.length > wrapped.length) {
status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
wrapped = data_blob_null;
}
- ok = spnego_parse_auth_response(wrapped, NT_STATUS_OK,
+ ok = spnego_parse_auth_response(talloc_tos(), wrapped, NT_STATUS_OK,
OID_KERBEROS5_OLD,
&unwrapped);
if (scred) ber_bvfree(scred);
context_handle = GSS_C_NO_CONTEXT;
}
+ status = ADS_SUCCESS;
+
failed:
if (context_handle != GSS_C_NO_CONTEXT)
gss_delete_sec_context(&minor_status, &context_handle, GSS_C_NO_BUFFER);
return ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
}
- rc = spnego_gen_negTokenTarg(principal, ads->auth.time_offset, &blob, &session_key, 0,
+ rc = spnego_gen_krb5_negTokenInit(talloc_tos(), principal,
+ ads->auth.time_offset, &blob, &session_key, 0,
&ads->auth.tgs_expire);
if (rc) {
char *given_principal = NULL;
char *OIDs[ASN1_MAX_OIDS];
#ifdef HAVE_KRB5
- BOOL got_kerberos_mechanism = False;
+ bool got_kerberos_mechanism = False;
#endif
rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", NULL, NULL, NULL, &scred);
/* the server sent us the first part of the SPNEGO exchange in the negprot
reply */
- if (!spnego_parse_negTokenInit(blob, OIDs, &given_principal)) {
+ if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &given_principal, NULL)) {
data_blob_free(&blob);
status = ADS_ERROR(LDAP_OPERATIONS_ERROR);
goto failed;
got_kerberos_mechanism = True;
}
#endif
- free(OIDs[i]);
+ talloc_free(OIDs[i]);
}
DEBUG(3,("ads_sasl_spnego_bind: got server principal name = %s\n", given_principal));
struct ads_service_principal p;
status = ads_generate_service_principal(ads, given_principal, &p);
- SAFE_FREE(given_principal);
+ TALLOC_FREE(given_principal);
if (!ADS_ERR_OK(status)) {
return status;
}
if (ADS_ERR_OK(status)) {
status = ads_sasl_spnego_krb5_bind(ads, &p);
+ if (!ADS_ERR_OK(status)) {
+ DEBUG(0,("kinit succeeded but "
+ "ads_sasl_spnego_krb5_bind failed: %s\n",
+ ads_errstr(status)));
+ }
}
ads_free_service_principal(&p);
} else
#endif
{
- SAFE_FREE(given_principal);
+ TALLOC_FREE(given_principal);
}
/* lets do NTLMSSP ... this has the big advantage that we don't need
output_token.length = 4;
output_token.value = SMB_MALLOC(output_token.length);
+ if (!output_token.value) {
+ output_token.length = 0;
+ status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
+ goto failed;
+ }
p = (uint8 *)output_token.value;
RSIVAL(p,0,max_msg_size);
*/
gss_rc = gss_wrap(&minor_status, context_handle,0,GSS_C_QOP_DEFAULT,
- &output_token, &conf_state,
- &input_token);
+ &output_token, /* used as *input* here. */
+ &conf_state,
+ &input_token); /* Used as *output* here. */
if (gss_rc) {
status = ADS_ERROR_GSS(gss_rc, minor_status);
+ output_token.length = 0;
+ SAFE_FREE(output_token.value);
goto failed;
}
- free(output_token.value);
+ /* We've finished with output_token. */
+ SAFE_FREE(output_token.value);
+ output_token.length = 0;
cred.bv_val = (char *)input_token.value;
cred.bv_len = input_token.length;
for (j=0;values && values[j];j++) {
if (strcmp(values[j], sasl_mechanisms[i].name) == 0) {
DEBUG(4,("Found SASL mechanism %s\n", values[j]));
+retry:
status = sasl_mechanisms[i].fn(ads);
+ if (status.error_type == ENUM_ADS_ERROR_LDAP &&
+ status.err.rc == LDAP_STRONG_AUTH_REQUIRED &&
+ ads->ldap.wrap_type == ADS_SASLWRAP_TYPE_PLAIN)
+ {
+ DEBUG(3,("SASL bin got LDAP_STRONG_AUTH_REQUIRED "
+ "retrying with signing enabled\n"));
+ ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SIGN;
+ goto retry;
+ }
ldap_value_free(values);
ldap_msgfree(res);
return status;