+struct cli_session_setup_ntlmssp_state {
+ struct tevent_context *ev;
+ struct cli_state *cli;
+ struct ntlmssp_state *ntlmssp_state;
+ int turn;
+ DATA_BLOB blob_out;
+};
+
+static int cli_session_setup_ntlmssp_state_destructor(
+ struct cli_session_setup_ntlmssp_state *state)
+{
+ if (state->ntlmssp_state != NULL) {
+ TALLOC_FREE(state->ntlmssp_state);
+ }
+ return 0;
+}
+
+static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
+
+static struct tevent_req *cli_session_setup_ntlmssp_send(
+ TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
+ const char *user, const char *pass, const char *domain)
+{
+ struct tevent_req *req, *subreq;
+ struct cli_session_setup_ntlmssp_state *state;
+ NTSTATUS status;
+ DATA_BLOB blob_out;
+ const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct cli_session_setup_ntlmssp_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->ev = ev;
+ state->cli = cli;
+ state->turn = 1;
+
+ state->ntlmssp_state = NULL;
+ talloc_set_destructor(
+ state, cli_session_setup_ntlmssp_state_destructor);
+
+ cli_temp_set_signing(cli);
+
+ status = ntlmssp_client_start(state,
+ global_myname(),
+ lp_workgroup(),
+ lp_client_ntlmv2_auth(),
+ &state->ntlmssp_state);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto fail;
+ }
+ ntlmssp_want_feature(state->ntlmssp_state,
+ NTLMSSP_FEATURE_SESSION_KEY);
+ if (cli->use_ccache) {
+ ntlmssp_want_feature(state->ntlmssp_state,
+ NTLMSSP_FEATURE_CCACHE);
+ }
+ status = ntlmssp_set_username(state->ntlmssp_state, user);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto fail;
+ }
+ status = ntlmssp_set_domain(state->ntlmssp_state, domain);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto fail;
+ }
+ status = ntlmssp_set_password(state->ntlmssp_state, pass);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto fail;
+ }
+ status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
+ &blob_out);
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ goto fail;
+ }
+
+ state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
+ data_blob_free(&blob_out);
+
+ subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
+ return req;
+fail:
+ tevent_req_nterror(req, status);
+ return tevent_req_post(req, ev);
+}
+
+static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)