Exemple #1
0
static NTSTATUS gensec_ntlmssp3_client_start(struct gensec_security *gensec_security)
{
	NTSTATUS nt_status;
	struct gensec_ntlmssp_context *gensec_ntlmssp;
	const char *user, *domain;
	const char *password;

	nt_status = gensec_ntlmssp_start(gensec_security);
	NT_STATUS_NOT_OK_RETURN(nt_status);

	gensec_ntlmssp =
		talloc_get_type_abort(gensec_security->private_data,
				      struct gensec_ntlmssp_context);

	nt_status = ntlmssp_client_start(gensec_ntlmssp,
					 lp_netbios_name(), lp_workgroup(),
					 lp_client_ntlmv2_auth(), &gensec_ntlmssp->ntlmssp_state);
	if (!NT_STATUS_IS_OK(nt_status)) {
		return nt_status;
	}

	cli_credentials_get_ntlm_username_domain(gensec_security->credentials, gensec_ntlmssp, &user, &domain);
	if (!user || !domain) {
		return NT_STATUS_NO_MEMORY;
	}

	nt_status = ntlmssp_set_username(gensec_ntlmssp->ntlmssp_state, user);
	if (!NT_STATUS_IS_OK(nt_status)) {
		return nt_status;
	}

	nt_status = ntlmssp_set_domain(gensec_ntlmssp->ntlmssp_state, domain);
	if (!NT_STATUS_IS_OK(nt_status)) {
		return nt_status;
	}

	password = cli_credentials_get_password(gensec_security->credentials);
	if (!password) {
		return NT_STATUS_NO_MEMORY;
	}

	nt_status = ntlmssp_set_password(gensec_ntlmssp->ntlmssp_state, password);
	if (!NT_STATUS_IS_OK(nt_status)) {
		return nt_status;
	}

	if (gensec_ntlmssp->gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) {
		gensec_ntlmssp->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
	}
	if (gensec_ntlmssp->gensec_security->want_features & GENSEC_FEATURE_SIGN) {
		gensec_ntlmssp->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
	}
	if (gensec_ntlmssp->gensec_security->want_features & GENSEC_FEATURE_SEAL) {
		gensec_ntlmssp->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
		gensec_ntlmssp->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
	}

	return NT_STATUS_OK;
}
Exemple #2
0
static NTSTATUS ntlm_auth_start_ntlmssp_client(NTLMSSP_STATE **client_ntlmssp_state) 
{
	NTSTATUS status;
	if ( (opt_username == NULL) || (opt_domain == NULL) ) {
		status = NT_STATUS_UNSUCCESSFUL;
		DEBUG(1, ("Need username and domain for NTLMSSP\n"));
		return NT_STATUS_INVALID_PARAMETER;
	}

	status = ntlmssp_client_start(client_ntlmssp_state);

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("Could not start NTLMSSP client: %s\n",
			  nt_errstr(status)));
		ntlmssp_end(client_ntlmssp_state);
		return status;
	}

	status = ntlmssp_set_username(*client_ntlmssp_state, opt_username);

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("Could not set username: %s\n",
			  nt_errstr(status)));
		ntlmssp_end(client_ntlmssp_state);
		return status;
	}

	status = ntlmssp_set_domain(*client_ntlmssp_state, opt_domain);

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("Could not set domain: %s\n",
			  nt_errstr(status)));
		ntlmssp_end(client_ntlmssp_state);
		return status;
	}

	status = ntlmssp_set_password(*client_ntlmssp_state, opt_password);
	
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("Could not set password: %s\n",
			  nt_errstr(status)));
		ntlmssp_end(client_ntlmssp_state);
		return status;
	}
	return NT_STATUS_OK;
}
Exemple #3
0
/* 
   perform a LDAP/SASL/SPNEGO/NTLMSSP bind (just how many layers can
   we fit on one socket??)
*/
static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads)
{
	DATA_BLOB msg1 = data_blob_null;
	DATA_BLOB blob = data_blob_null;
	DATA_BLOB blob_in = data_blob_null;
	DATA_BLOB blob_out = data_blob_null;
	struct berval cred, *scred = NULL;
	int rc;
	NTSTATUS nt_status;
	ADS_STATUS status;
	int turn = 1;
	uint32 features = 0;

	struct ntlmssp_state *ntlmssp_state;

	if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) {
		return ADS_ERROR_NT(nt_status);
	}
	ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_SIGN;

	if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_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))) {
		return ADS_ERROR_NT(nt_status);
	}
	if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_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;
		break;
	case ADS_SASLWRAP_TYPE_SIGN:
		if (ads->auth.flags & ADS_AUTH_SASL_FORCE) {
			features = NTLMSSP_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;
			ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SEAL;
		}
		break;
	case ADS_SASLWRAP_TYPE_PLAIN:
		break;
	}

	ntlmssp_want_feature(ntlmssp_state, features);

	blob_in = data_blob_null;

	do {
		nt_status = ntlmssp_update(ntlmssp_state, 
					   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))
		    && blob_out.length) {
			if (turn == 1) {
				/* and wrap it in a SPNEGO wrapper */
				msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out);
			} else {
				/* wrap it in SPNEGO */
				msg1 = spnego_gen_auth(blob_out);
			}

			data_blob_free(&blob_out);

			cred.bv_val = (char *)msg1.data;
			cred.bv_len = msg1.length;
			scred = NULL;
			rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred);
			data_blob_free(&msg1);
			if ((rc != LDAP_SASL_BIND_IN_PROGRESS) && (rc != 0)) {
				if (scred) {
					ber_bvfree(scred);
				}

				ntlmssp_end(&ntlmssp_state);
				return ADS_ERROR(rc);
			}
			if (scred) {
				blob = data_blob(scred->bv_val, scred->bv_len);
				ber_bvfree(scred);
			} else {
				blob = data_blob_null;
			}

		} else {

			ntlmssp_end(&ntlmssp_state);
			data_blob_free(&blob_out);
			return ADS_ERROR_NT(nt_status);
		}
		
		if ((turn == 1) && 
		    (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, 
						    &tmp_blob)) {

				ntlmssp_end(&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, 
							&blob_in)) {

				ntlmssp_end(&ntlmssp_state);
				data_blob_free(&blob);
				DEBUG(3,("Failed to parse auth response\n"));
				return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
			}
		}
		data_blob_free(&blob);
		data_blob_free(&blob_out);
		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;
		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);
		if (!ADS_ERR_OK(status)) {
			DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
				ads_errstr(status)));
			ntlmssp_end(&ntlmssp_state);
			return status;
		}
	} else {
		ntlmssp_end(&ntlmssp_state);
	}

	return ADS_ERROR(rc);
}
Exemple #4
0
static BOOL rpc_pipe_bind(struct cli_state *cli, int pipe_idx, const char *my_name)
{
	RPC_IFACE abstract;
	RPC_IFACE transfer;
	prs_struct rpc_out;
	prs_struct rdata;
	uint32 rpc_call_id;
	char buffer[MAX_PDU_FRAG_LEN];

	if ( (pipe_idx < 0) || (pipe_idx >= PI_MAX_PIPES) )
		return False;

	DEBUG(5,("Bind RPC Pipe[%x]: %s\n", cli->nt_pipe_fnum, pipe_names[pipe_idx].client_pipe));

	if (!valid_pipe_name(pipe_idx, &abstract, &transfer))
		return False;

	prs_init(&rpc_out, 0, cli->mem_ctx, MARSHALL);

	/*
	 * Use the MAX_PDU_FRAG_LEN buffer to store the bind request.
	 */

	prs_give_memory( &rpc_out, buffer, sizeof(buffer), False);

	rpc_call_id = get_rpc_call_id();

	if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) {
		NTSTATUS nt_status;
		fstring password;

		DEBUG(5, ("NTLMSSP authenticated pipe selected\n"));

		nt_status = ntlmssp_client_start(&cli->ntlmssp_pipe_state);
		
		if (!NT_STATUS_IS_OK(nt_status))
			return False;

		/* Currently the NTLMSSP code does not implement NTLM2 correctly for signing or sealing */

		cli->ntlmssp_pipe_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;

		nt_status = ntlmssp_set_username(cli->ntlmssp_pipe_state, 
						 cli->user_name);
		if (!NT_STATUS_IS_OK(nt_status))
			return False;

		nt_status = ntlmssp_set_domain(cli->ntlmssp_pipe_state, 
					       cli->domain);	
		if (!NT_STATUS_IS_OK(nt_status))
			return False;

		if (cli->pwd.null_pwd) {
			nt_status = ntlmssp_set_password(cli->ntlmssp_pipe_state, 
							 NULL);
			if (!NT_STATUS_IS_OK(nt_status))
				return False;
		} else {
			pwd_get_cleartext(&cli->pwd, password);
			nt_status = ntlmssp_set_password(cli->ntlmssp_pipe_state, 
							 password);
			if (!NT_STATUS_IS_OK(nt_status))
				return False;
		}

		if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) {
			cli->ntlmssp_pipe_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
		}

		if (cli->pipe_auth_flags & AUTH_PIPE_SEAL) {
			cli->ntlmssp_pipe_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
		}
	} else if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) {
		cli->auth_info.seq_num = 0;
	}

	/* Marshall the outgoing data. */
	create_rpc_bind_req(cli, &rpc_out, rpc_call_id,
	                    &abstract, &transfer,
	                    global_myname(), cli->domain);

	/* Initialize the incoming data struct. */
	prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL);

	/* send data on \PIPE\.  receive a response */
	if (rpc_api_pipe(cli, &rpc_out, &rdata, RPC_BINDACK)) {
		RPC_HDR_BA   hdr_ba;

		DEBUG(5, ("rpc_pipe_bind: rpc_api_pipe returned OK.\n"));

		if(!smb_io_rpc_hdr_ba("", &hdr_ba, &rdata, 0)) {
			DEBUG(0,("rpc_pipe_bind: Failed to unmarshall RPC_HDR_BA.\n"));
			prs_mem_free(&rdata);
			return False;
		}

		if(!check_bind_response(&hdr_ba, pipe_idx, &transfer)) {
			DEBUG(2,("rpc_pipe_bind: check_bind_response failed.\n"));
			prs_mem_free(&rdata);
			return False;
		}

		cli->max_xmit_frag = hdr_ba.bba.max_tsize;
		cli->max_recv_frag = hdr_ba.bba.max_rsize;

		/*
		 * If we're doing NTLMSSP auth we need to send a reply to
		 * the bind-ack to complete the 3-way challenge response
		 * handshake.
		 */

		if ((cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) 
		    && !rpc_send_auth_reply(cli, &rdata, rpc_call_id)) {
			DEBUG(0,("rpc_pipe_bind: rpc_send_auth_reply failed.\n"));
			prs_mem_free(&rdata);
			return False;
		}
		prs_mem_free(&rdata);
		return True;
	}

	return False;
}
Exemple #5
0
/* 
   perform a LDAP/SASL/SPNEGO/NTLMSSP bind (just how many layers can
   we fit on one socket??)
*/
static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads)
{
	DATA_BLOB msg1 = data_blob(NULL, 0);
	DATA_BLOB blob = data_blob(NULL, 0);
	DATA_BLOB blob_in = data_blob(NULL, 0);
	DATA_BLOB blob_out = data_blob(NULL, 0);
	struct berval cred, *scred = NULL;
	int rc;
	NTSTATUS nt_status;
	int turn = 1;

	struct ntlmssp_state *ntlmssp_state;

	if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) {
		return ADS_ERROR_NT(nt_status);
	}
	ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_SIGN;

	if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_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))) {
		return ADS_ERROR_NT(nt_status);
	}
	if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, ads->auth.password))) {
		return ADS_ERROR_NT(nt_status);
	}

	blob_in = data_blob(NULL, 0);

	do {
		nt_status = ntlmssp_update(ntlmssp_state, 
					   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))
		    && blob_out.length) {
			if (turn == 1) {
				/* and wrap it in a SPNEGO wrapper */
				msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out);
			} else {
				/* wrap it in SPNEGO */
				msg1 = spnego_gen_auth(blob_out);
			}

			data_blob_free(&blob_out);

			cred.bv_val = (char *)msg1.data;
			cred.bv_len = msg1.length;
			scred = NULL;
			rc = ldap_sasl_bind_s(ads->ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred);
			data_blob_free(&msg1);
			if ((rc != LDAP_SASL_BIND_IN_PROGRESS) && (rc != 0)) {
				if (scred) {
					ber_bvfree(scred);
				}

				ntlmssp_end(&ntlmssp_state);
				return ADS_ERROR(rc);
			}
			if (scred) {
				blob = data_blob(scred->bv_val, scred->bv_len);
				ber_bvfree(scred);
			} else {
				blob = data_blob(NULL, 0);
			}

		} else {

			ntlmssp_end(&ntlmssp_state);
			data_blob_free(&blob_out);
			return ADS_ERROR_NT(nt_status);
		}
		
		if ((turn == 1) && 
		    (rc == LDAP_SASL_BIND_IN_PROGRESS)) {
			DATA_BLOB tmp_blob = data_blob(NULL, 0);
			/* the server might give us back two challenges */
			if (!spnego_parse_challenge(blob, &blob_in, 
						    &tmp_blob)) {

				ntlmssp_end(&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, 
							&blob_in)) {

				ntlmssp_end(&ntlmssp_state);
				data_blob_free(&blob);
				DEBUG(3,("Failed to parse auth response\n"));
				return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
			}
		}
		data_blob_free(&blob);
		data_blob_free(&blob_out);
		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 */

	ntlmssp_end(&ntlmssp_state);

	return ADS_ERROR(rc);
}
static NTSTATUS do_ntlm_auth_with_hashes(const char *username,
					const char *domain,
					const unsigned char lm_hash[LM_HASH_LEN],
					const unsigned char nt_hash[NT_HASH_LEN],
					const DATA_BLOB initial_msg,
					const DATA_BLOB challenge_msg,
					DATA_BLOB *auth_msg,
					uint8_t session_key[16])
{
	NTSTATUS status;
	struct ntlmssp_state *ntlmssp_state = NULL;
	DATA_BLOB dummy_msg, reply;

	status = ntlmssp_client_start(NULL,
				      global_myname(),
				      lp_workgroup(),
				      lp_client_ntlmv2_auth(),
				      &ntlmssp_state);

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("Could not start NTLMSSP client: %s\n",
			nt_errstr(status)));
		goto done;
	}

	status = ntlmssp_set_username(ntlmssp_state, username);

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("Could not set username: %s\n",
			nt_errstr(status)));
		goto done;
	}

	status = ntlmssp_set_domain(ntlmssp_state, domain);

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("Could not set domain: %s\n",
			nt_errstr(status)));
		goto done;
	}

	status = ntlmssp_set_hashes(ntlmssp_state, lm_hash, nt_hash);

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("Could not set hashes: %s\n",
			nt_errstr(status)));
		goto done;
	}

	ntlmssp_want_feature(ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);

	/* We need to get our protocol handler into the right state. So first
	   we ask it to generate the initial message. Actually the client has already
	   sent its own initial message, so we're going to drop this one on the floor.
	   The client might have sent a different message, for example with different
	   negotiation options, but as far as I can tell this won't hurt us. (Unless
	   the client sent a different username or domain, in which case that's their
	   problem for telling us the wrong username or domain.)
	   Since we have a copy of the initial message that the client sent, we could
	   resolve any discrepancies if we had to.
	*/
	dummy_msg = data_blob_null;
	reply = data_blob_null;
	status = ntlmssp_update(ntlmssp_state, dummy_msg, &reply);
	data_blob_free(&dummy_msg);
	data_blob_free(&reply);

	if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
		DEBUG(1, ("Failed to create initial message! [%s]\n",
			nt_errstr(status)));
		goto done;
	}

	/* Now we are ready to handle the server's actual response. */
	status = ntlmssp_update(ntlmssp_state, challenge_msg, &reply);

	if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
		DEBUG(1, ("We didn't get a response to the challenge! [%s]\n",
			nt_errstr(status)));
		data_blob_free(&reply);
		goto done;
	}

	if (ntlmssp_state->session_key.length != 16) {
		DEBUG(1, ("invalid session key length %d\n",
			  (int)ntlmssp_state->session_key.length));
		data_blob_free(&reply);
		goto done;
	}

	*auth_msg = data_blob(reply.data, reply.length);
	memcpy(session_key, ntlmssp_state->session_key.data, 16);
	status = NT_STATUS_OK;

done:
	TALLOC_FREE(ntlmssp_state);
	return status;
}