Example #1
0
/*
 * Test activating the IWbemLevel1Login interface asynchronously.
 */
static void torture_wbem_login_async_cont(struct composite_context *ctx)
{
    struct composite_context *c = NULL;
    BOOL *pRet = NULL;
    struct IUnknown **mqi = NULL;
    NTSTATUS status;

    /* retrieve the parent composite context */
    c = talloc_get_type(ctx->async.private_data, struct composite_context);
    if (!composite_is_ok(c)) return;

    pRet = (BOOL *)c->private_data;

    status = dcom_activate_recv(ctx, c, &mqi);
    *pRet = NT_STATUS_IS_OK(status);

    talloc_report_full(c, stdout);

    if (*pRet)
    {
        /*
         * Clean up by releasing the IUnknown interface on the remote server
         * and also by releasing our allocated interface pointer.
         */
        IUnknown_Release(mqi[0], c); /* really synchronous but eh */
        talloc_free(mqi);
    }

    composite_done(c);
}
Example #2
0
/*
  Receive a bind reply from the transport
*/
static void dcerpc_bind_recv_handler(struct rpc_request *req, 
				     DATA_BLOB *raw_packet, struct ncacn_packet *pkt)
{
	struct composite_context *c;
	struct dcerpc_connection *conn;

	c = talloc_get_type(req->async.private_data, struct composite_context);

	if (pkt->ptype == DCERPC_PKT_BIND_NAK) {
		DEBUG(2,("dcerpc: bind_nak reason %d\n",
			 pkt->u.bind_nak.reject_reason));
		composite_error(c, dcerpc_map_reason(pkt->u.bind_nak.
						     reject_reason));
		return;
	}

	if ((pkt->ptype != DCERPC_PKT_BIND_ACK) ||
	    (pkt->u.bind_ack.num_results == 0) ||
	    (pkt->u.bind_ack.ctx_list[0].result != 0)) {
		composite_error(c, NT_STATUS_NET_WRITE_FAULT);
		return;
	}

	conn = req->p->conn;

	conn->srv_max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
	conn->srv_max_recv_frag = pkt->u.bind_ack.max_recv_frag;

	if ((req->p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) &&
	    (pkt->pfc_flags & DCERPC_PFC_FLAG_CONC_MPX)) {
		conn->flags |= DCERPC_CONCURRENT_MULTIPLEX;
	}

	if ((req->p->binding->flags & DCERPC_HEADER_SIGNING) &&
	    (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN)) {
		conn->flags |= DCERPC_HEADER_SIGNING;
	}

	/* the bind_ack might contain a reply set of credentials */
	if (conn->security_state.auth_info &&
	    pkt->u.bind_ack.auth_info.length) {
		enum ndr_err_code ndr_err;
		ndr_err = ndr_pull_struct_blob(
			&pkt->u.bind_ack.auth_info, conn,
			NULL,
			conn->security_state.auth_info,
			(ndr_pull_flags_fn_t)ndr_pull_dcerpc_auth);
		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
			c->status = ndr_map_error2ntstatus(ndr_err);
			if (!composite_is_ok(c)) return;
		}
	}

	req->p->assoc_group_id = pkt->u.bind_ack.assoc_group_id;

	composite_done(c);
}
Example #3
0
static struct composite_context *wreplsrv_pull_table_send(TALLOC_CTX *mem_ctx, struct wreplsrv_pull_table_io *io)
{
	struct composite_context *c = NULL;
	struct wreplsrv_service *service = io->in.partner->service;
	struct wreplsrv_pull_table_state *state = NULL;

	c = talloc_zero(mem_ctx, struct composite_context);
	if (!c) goto failed;

	state = talloc_zero(c, struct wreplsrv_pull_table_state);
	if (!state) goto failed;
	state->c	= c;
	state->io	= io;

	c->state	= COMPOSITE_STATE_IN_PROGRESS;
	c->event_ctx	= service->task->event_ctx;
	c->private_data	= state;

	if (io->in.num_owners) {
		struct wrepl_wins_owner *partners;
		uint32_t i;

		partners = talloc_array(state,
					struct wrepl_wins_owner,
					io->in.num_owners);
		if (composite_nomem(partners, c)) goto failed;

		for (i=0; i < io->in.num_owners; i++) {
			partners[i] = io->in.owners[i];
			partners[i].address = talloc_strdup(partners,
						io->in.owners[i].address);
			if (composite_nomem(partners[i].address, c)) goto failed;
		}

		state->table_io.out.num_partners	= io->in.num_owners;
		state->table_io.out.partners		= partners;
		state->stage				= WREPLSRV_PULL_TABLE_STAGE_DONE;
		composite_done(c);
		return c;
	}

	state->stage    = WREPLSRV_PULL_TABLE_STAGE_WAIT_CONNECTION;
	state->creq	= wreplsrv_out_connect_send(io->in.partner, WINSREPL_PARTNER_PULL, NULL);
	if (!state->creq) goto failed;

	state->creq->async.fn		= wreplsrv_pull_table_handler_creq;
	state->creq->async.private_data	= state;

	return c;
failed:
	talloc_free(c);
	return NULL;
}
Example #4
0
_PUBLIC_ void composite_error(struct composite_context *ctx, NTSTATUS status)
{
	/* you are allowed to pass NT_STATUS_OK to composite_error(), in which
	   case it is equivalent to composite_done() */
	if (NT_STATUS_IS_OK(status)) {
		composite_done(ctx);
		return;
	}
	if (!ctx->used_wait && !ctx->async.fn) {
		tevent_add_timer(ctx->event_ctx, ctx, timeval_zero(), composite_trigger, ctx);
	}
	ctx->status = status;
	ctx->state = COMPOSITE_STATE_ERROR;
	if (ctx->async.fn != NULL) {
		ctx->async.fn(ctx);
	}
}
Example #5
0
/*
  composite session setup function that hides the details of all the
  different session setup varients, including the multi-pass nature of
  the spnego varient
*/
struct composite_context *smb_composite_sesssetup_send(struct smbcli_session *session, 
						       struct smb_composite_sesssetup *io)
{
	struct composite_context *c;
	struct sesssetup_state *state;
	NTSTATUS status;

	c = composite_create(session, session->transport->ev);
	if (c == NULL) return NULL;

	state = talloc_zero(c, struct sesssetup_state);
	if (composite_nomem(state, c)) return c;
	c->private_data = state;

	state->io = io;

	talloc_set_destructor(state, sesssetup_state_destructor);

	/* no session setup at all in earliest protocol varients */
	if (session->transport->negotiate.protocol < PROTOCOL_LANMAN1) {
		ZERO_STRUCT(io->out);
		composite_done(c);
		return c;
	}

	/* see what session setup interface we will use */
	if (session->transport->negotiate.protocol < PROTOCOL_NT1) {
		status = session_setup_old(c, session, io, &state->req);
	} else if (!session->transport->options.use_spnego ||
		   !(io->in.capabilities & CAP_EXTENDED_SECURITY)) {
		status = session_setup_nt1(c, session, io, &state->req);
	} else {
		status = session_setup_spnego(c, session, io, &state->req);
	}

	if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) || 
	    NT_STATUS_IS_OK(status)) {
		composite_continue_smb(c, state->req, request_handler, c);	
		return c;
	}

	composite_error(c, status);
	return c;
}
Example #6
0
/*
  Receive an alter reply from the transport
*/
static void dcerpc_alter_recv_handler(struct rpc_request *req,
				      DATA_BLOB *raw_packet, struct ncacn_packet *pkt)
{
	struct composite_context *c;
	struct dcerpc_pipe *recv_pipe;

	c = talloc_get_type(req->async.private_data, struct composite_context);
	recv_pipe = talloc_get_type(c->private_data, struct dcerpc_pipe);

	if (pkt->ptype == DCERPC_PKT_ALTER_RESP &&
	    pkt->u.alter_resp.num_results == 1 &&
	    pkt->u.alter_resp.ctx_list[0].result != 0) {
		DEBUG(2,("dcerpc: alter_resp failed - reason %d\n", 
			 pkt->u.alter_resp.ctx_list[0].reason));
		composite_error(c, dcerpc_map_reason(pkt->u.alter_resp.ctx_list[0].reason));
		return;
	}

	if (pkt->ptype != DCERPC_PKT_ALTER_RESP ||
	    pkt->u.alter_resp.num_results == 0 ||
	    pkt->u.alter_resp.ctx_list[0].result != 0) {
		composite_error(c, NT_STATUS_NET_WRITE_FAULT);
		return;
	}

	/* the alter_resp might contain a reply set of credentials */
	if (recv_pipe->conn->security_state.auth_info &&
	    pkt->u.alter_resp.auth_info.length) {
		enum ndr_err_code ndr_err;
		ndr_err = ndr_pull_struct_blob(
			&pkt->u.alter_resp.auth_info, recv_pipe,
			NULL,
			recv_pipe->conn->security_state.auth_info,
			(ndr_pull_flags_fn_t)ndr_pull_dcerpc_auth);
		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
			c->status = ndr_map_error2ntstatus(ndr_err);
			if (!composite_is_ok(c)) return;
		}
	}

	composite_done(c);
}
static void init_domain_recv_ldapconn(struct composite_context *ctx)
{
	struct init_domain_state *state =
		talloc_get_type(ctx->async.private_data,
				struct init_domain_state);

	state->ctx->status = ldap_connect_recv(ctx);
	if (NT_STATUS_IS_OK(state->ctx->status)) {
		state->domain->ldap_conn->host =
			talloc_strdup(state->domain->ldap_conn,
				      state->domain->dc_name);
		state->ctx->status =
			ldap_bind_sasl(state->domain->ldap_conn,
				       state->domain->schannel_creds);
		DEBUG(0, ("ldap_bind returned %s\n",
			  nt_errstr(state->ctx->status)));
	}

	composite_done(state->ctx);
}
Example #8
0
static void unbecomeDC_drsuapi_remove_ds_server_recv(struct rpc_request *req)
{
	struct libnet_UnbecomeDC_state *s = talloc_get_type(req->async.private_data,
					    struct libnet_UnbecomeDC_state);
	struct composite_context *c = s->creq;
	struct drsuapi_DsRemoveDSServer *r = &s->drsuapi.rm_ds_srv_r;

	c->status = dcerpc_ndr_request_recv(req);
	if (!composite_is_ok(c)) return;

	if (!W_ERROR_IS_OK(r->out.result)) {
		composite_error(c, werror_to_ntstatus(r->out.result));
		return;
	}

	if (*r->out.level_out != 1) {
		composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
		return;
	}

	composite_done(c);
}
Example #9
0
/* Recv the SAMR details (SamrConnect and SamrOpenDomain handle) and
 * open an LDAP connection */
static void init_domain_recv_samr(struct composite_context *ctx)
{
	struct init_domain_state *state =
		talloc_get_type(ctx->async.private_data,
				struct init_domain_state);

	state->ctx->status = wb_connect_samr_recv(
		ctx, state->domain,
		&state->domain->libnet_ctx->samr.pipe,
		&state->domain->libnet_ctx->samr.connect_handle,
		&state->domain->libnet_ctx->samr.handle);
	if (!composite_is_ok(state->ctx)) return;

	talloc_reparent(state, state->domain->libnet_ctx->samr.pipe, state->domain->samr_binding);
	state->domain->libnet_ctx->samr.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
	state->domain->libnet_ctx->samr.name = state->domain->info->name;
	state->domain->libnet_ctx->samr.sid = dom_sid_dup(
						state->domain->libnet_ctx,
						state->domain->info->sid);

	composite_done(state->ctx);
}
Example #10
0
static void unbecomeDC_drsuapi_remove_ds_server_recv(struct tevent_req *subreq)
{
	struct libnet_UnbecomeDC_state *s = tevent_req_callback_data(subreq,
					    struct libnet_UnbecomeDC_state);
	struct composite_context *c = s->creq;
	struct drsuapi_DsRemoveDSServer *r = &s->drsuapi.rm_ds_srv_r;

	c->status = dcerpc_drsuapi_DsRemoveDSServer_r_recv(subreq, s);
	TALLOC_FREE(subreq);
	if (!composite_is_ok(c)) return;

	if (!W_ERROR_IS_OK(r->out.result)) {
		composite_error(c, werror_to_ntstatus(r->out.result));
		return;
	}

	if (*r->out.level_out != 1) {
		composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
		return;
	}

	composite_done(c);
}
Example #11
0
static struct composite_context *wreplsrv_out_connect_send(struct wreplsrv_partner *partner,
							   enum winsrepl_partner_type type,
							   struct wreplsrv_out_connection *wreplconn)
{
	struct composite_context *c = NULL;
	struct wreplsrv_service *service = partner->service;
	struct wreplsrv_out_connect_state *state = NULL;
	struct wreplsrv_out_connection **wreplconnp = &wreplconn;
	bool cached_connection = false;

	c = talloc_zero(partner, struct composite_context);
	if (!c) goto failed;

	state = talloc_zero(c, struct wreplsrv_out_connect_state);
	if (!state) goto failed;
	state->c	= c;
	state->type	= type;

	c->state	= COMPOSITE_STATE_IN_PROGRESS;
	c->event_ctx	= service->task->event_ctx;
	c->private_data	= state;

	if (type == WINSREPL_PARTNER_PUSH) {
		cached_connection	= true;
		wreplconn		= partner->push.wreplconn;
		wreplconnp		= &partner->push.wreplconn;
	} else if (type == WINSREPL_PARTNER_PULL) {
		cached_connection	= true;
		wreplconn		= partner->pull.wreplconn;
		wreplconnp		= &partner->pull.wreplconn;
	}

	/* we have a connection already, so use it */
	if (wreplconn) {
		if (wrepl_socket_is_connected(wreplconn->sock)) {
			state->stage	= WREPLSRV_OUT_CONNECT_STAGE_DONE;
			state->wreplconn= wreplconn;
			composite_done(c);
			return c;
		} else if (!cached_connection) {
			state->stage	= WREPLSRV_OUT_CONNECT_STAGE_DONE;
			state->wreplconn= NULL;
			composite_done(c);
			return c;
		} else {
			talloc_free(wreplconn);
			*wreplconnp = NULL;
		}
	}

	wreplconn = talloc_zero(state, struct wreplsrv_out_connection);
	if (!wreplconn) goto failed;

	wreplconn->service	= service;
	wreplconn->partner	= partner;
	wreplconn->sock		= wrepl_socket_init(wreplconn, service->task->event_ctx);
	if (!wreplconn->sock) goto failed;

	state->stage	= WREPLSRV_OUT_CONNECT_STAGE_WAIT_SOCKET;
	state->wreplconn= wreplconn;
	state->subreq	= wrepl_connect_send(state,
					     service->task->event_ctx,
					     wreplconn->sock,
					     partner->our_address?partner->our_address:wrepl_best_ip(service->task->lp_ctx, partner->address),
					     partner->address);
	if (!state->subreq) goto failed;

	tevent_req_set_callback(state->subreq,
				wreplsrv_out_connect_handler_treq,
				state);

	return c;
failed:
	talloc_free(c);
	return NULL;
}
Example #12
0
/*
  handler for completion of a smbcli_request sub-request
*/
static void request_handler(struct smbcli_request *req)
{
	struct composite_context *c = (struct composite_context *)req->async.private_data;
	struct sesssetup_state *state = talloc_get_type(c->private_data, struct sesssetup_state);
	struct smbcli_session *session = req->session;
	DATA_BLOB null_data_blob = data_blob(NULL, 0);
	NTSTATUS session_key_err, nt_status;
	struct smbcli_request *check_req = NULL;
	const char *os = NULL;
	const char *lanman = NULL;

	if (req->sign_caller_checks) {
		req->do_not_free = true;
		check_req = req;
	}

	state->remote_status = smb_raw_sesssetup_recv(req, state, &state->setup);
	c->status = state->remote_status;
	state->req = NULL;

	/*
	 * we only need to check the signature if the
	 * NT_STATUS_OK is returned
	 */
	if (!NT_STATUS_IS_OK(state->remote_status)) {
		talloc_free(check_req);
		check_req = NULL;
	}

	switch (state->setup.old.level) {
	case RAW_SESSSETUP_OLD:
		state->io->out.vuid = state->setup.old.out.vuid;
		/* This doesn't work, as this only happens on old
		 * protocols, where this comparison won't match. */
		if (NT_STATUS_EQUAL(c->status, NT_STATUS_LOGON_FAILURE)) {
			/* we neet to reset the vuid for a new try */
			session->vuid = 0;
			if (cli_credentials_wrong_password(state->io->in.credentials)) {
				nt_status = session_setup_old(c, session, 
							      state->io, 
							      &state->req);
				if (NT_STATUS_IS_OK(nt_status)) {
					talloc_free(check_req);
					c->status = nt_status;
					composite_continue_smb(c, state->req, request_handler, c);
					return;
				}
			}
		}
		os = state->setup.old.out.os;
		lanman = state->setup.old.out.lanman;
		break;

	case RAW_SESSSETUP_NT1:
		state->io->out.vuid = state->setup.nt1.out.vuid;
		if (NT_STATUS_EQUAL(c->status, NT_STATUS_LOGON_FAILURE)) {
			/* we need to reset the vuid for a new try */
			session->vuid = 0;
			if (cli_credentials_wrong_password(state->io->in.credentials)) {
				nt_status = session_setup_nt1(c, session, 
							      state->io, 
							      &state->req);
				if (NT_STATUS_IS_OK(nt_status)) {
					talloc_free(check_req);
					c->status = nt_status;
					composite_continue_smb(c, state->req, request_handler, c);
					return;
				}
			}
		}
		os = state->setup.nt1.out.os;
		lanman = state->setup.nt1.out.lanman;
		break;

	case RAW_SESSSETUP_SPNEGO:
		state->io->out.vuid = state->setup.spnego.out.vuid;
		if (NT_STATUS_EQUAL(c->status, NT_STATUS_LOGON_FAILURE)) {
			const char *principal;

			/* we need to reset the vuid for a new try */
			session->vuid = 0;

			principal = gensec_get_target_principal(session->gensec);
			if (principal == NULL) {
				const char *hostname = gensec_get_target_hostname(session->gensec);
				const char *service  = gensec_get_target_service(session->gensec);
				if (hostname != NULL && service != NULL) {
					principal = talloc_asprintf(state, "%s/%s", service, hostname);
				}
			}
			if (cli_credentials_failed_kerberos_login(state->io->in.credentials, principal, &state->logon_retries) ||
			    cli_credentials_wrong_password(state->io->in.credentials)) {
				nt_status = session_setup_spnego(c, session, 
								      state->io, 
								      &state->req);
				if (NT_STATUS_IS_OK(nt_status)) {
					talloc_free(check_req);
					c->status = nt_status;
					composite_continue_smb(c, state->req, request_handler, c);
					return;
				}
			}
		}
		if (!NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED) && 
		    !NT_STATUS_IS_OK(c->status)) {
			break;
		}
		if (NT_STATUS_EQUAL(state->gensec_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {

			/* The status value here, from the earlier pass at GENSEC is
			 * vital to the security of the system.  Even if the other end
			 * accepts, if GENSEC claims 'MORE_PROCESSING_REQUIRED' then
			 * you must keep feeding it blobs, or else the remote
			 * host/attacker might avoid mutal authentication
			 * requirements */
			
			state->gensec_status = gensec_update(session->gensec, state, c->event_ctx,
							 state->setup.spnego.out.secblob,
							 &state->setup.spnego.in.secblob);
			c->status = state->gensec_status;
			if (!NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED) && 
			    !NT_STATUS_IS_OK(c->status)) {
				break;
			}
		} else {
			state->setup.spnego.in.secblob = data_blob(NULL, 0);
		}

		if (NT_STATUS_IS_OK(state->remote_status)) {
			DATA_BLOB session_key;

			if (state->setup.spnego.in.secblob.length) {
				c->status = NT_STATUS_INTERNAL_ERROR;
				break;
			}
			session_key_err = gensec_session_key(session->gensec, session, &session_key);
			if (NT_STATUS_IS_OK(session_key_err)) {
				smb1cli_conn_activate_signing(session->transport->conn,
							      session_key,
							      null_data_blob);
			}

			c->status = smb1cli_session_set_session_key(session->smbXcli,
								    session_key);
			data_blob_free(&session_key);
			if (!NT_STATUS_IS_OK(c->status)) {
				break;
			}
		}

		if (state->setup.spnego.in.secblob.length) {
			/* 
			 * set the session->vuid value only for calling
			 * smb_raw_sesssetup_send()
			 */
			uint16_t vuid = session->vuid;
			session->vuid = state->io->out.vuid;
			state->req = smb_raw_sesssetup_send(session, &state->setup);
			session->vuid = vuid;
			if (state->req &&
			    !smb1cli_conn_signing_is_active(state->req->transport->conn)) {
				state->req->sign_caller_checks = true;
			}
			composite_continue_smb(c, state->req, request_handler, c);
			return;
		}
		os = state->setup.spnego.out.os;
		lanman = state->setup.spnego.out.lanman;
		break;

	case RAW_SESSSETUP_SMB2:
		c->status = NT_STATUS_INTERNAL_ERROR;
		break;
	}

	if (check_req) {
		bool ok;

		check_req->sign_caller_checks = false;

		ok = smb1cli_conn_check_signing(check_req->transport->conn,
						check_req->in.buffer, 1);
		if (!ok) {
			c->status = NT_STATUS_ACCESS_DENIED;
		}
		talloc_free(check_req);
		check_req = NULL;
	}

	if (!NT_STATUS_IS_OK(c->status)) {
		composite_error(c, c->status);
		return;
	}

	if (os) {
		session->os = talloc_strdup(session, os);
		if (composite_nomem(session->os, c)) return;
	} else {
		session->os = NULL;
	}
	if (lanman) {
		session->lanman = talloc_strdup(session, lanman);
		if (composite_nomem(session->lanman, c)) return;
	} else {
		session->lanman = NULL;
	}

	composite_done(c);
}
Example #13
0
/*
  handler for completion of a smbcli_request sub-request
*/
static void request_handler(struct smbcli_request *req)
{
	struct composite_context *c = (struct composite_context *)req->async.private_data;
	struct sesssetup_state *state = talloc_get_type(c->private_data, struct sesssetup_state);
	struct smbcli_session *session = req->session;
	DATA_BLOB session_key = data_blob(NULL, 0);
	DATA_BLOB null_data_blob = data_blob(NULL, 0);
	NTSTATUS session_key_err, nt_status;
	struct smbcli_request *check_req = NULL;
	const char *os = NULL;
	const char *lanman = NULL;

	if (req->sign_caller_checks) {
		req->do_not_free = true;
		check_req = req;
	}

	state->remote_status = smb_raw_sesssetup_recv(req, state, &state->setup);
	c->status = state->remote_status;
	state->req = NULL;

	/*
	 * we only need to check the signature if the
	 * NT_STATUS_OK is returned
	 */
	if (!NT_STATUS_IS_OK(state->remote_status)) {
		talloc_free(check_req);
		check_req = NULL;
	}

	switch (state->setup.old.level) {
	case RAW_SESSSETUP_OLD:
		state->io->out.vuid = state->setup.old.out.vuid;
		/* This doesn't work, as this only happens on old
		 * protocols, where this comparison won't match. */
		if (NT_STATUS_EQUAL(c->status, NT_STATUS_LOGON_FAILURE)) {
			/* we neet to reset the vuid for a new try */
			session->vuid = 0;
			if (cli_credentials_wrong_password(state->io->in.credentials)) {
				nt_status = session_setup_old(c, session, 
							      state->io, 
							      &state->req);
				if (NT_STATUS_IS_OK(nt_status)) {
					talloc_free(check_req);
					c->status = nt_status;
					composite_continue_smb(c, state->req, request_handler, c);
					return;
				}
			}
		}
		os = state->setup.old.out.os;
		lanman = state->setup.old.out.lanman;
		break;

	case RAW_SESSSETUP_NT1:
		state->io->out.vuid = state->setup.nt1.out.vuid;
		if (NT_STATUS_EQUAL(c->status, NT_STATUS_LOGON_FAILURE)) {
			/* we neet to reset the vuid for a new try */
			session->vuid = 0;
			if (cli_credentials_wrong_password(state->io->in.credentials)) {
				nt_status = session_setup_nt1(c, session, 
							      state->io, 
							      &state->req);
				if (NT_STATUS_IS_OK(nt_status)) {
					talloc_free(check_req);
					c->status = nt_status;
					composite_continue_smb(c, state->req, request_handler, c);
					return;
				}
			}
		}
		os = state->setup.nt1.out.os;
		lanman = state->setup.nt1.out.lanman;
		break;

	case RAW_SESSSETUP_SPNEGO:
		state->io->out.vuid = state->setup.spnego.out.vuid;
		if (NT_STATUS_EQUAL(c->status, NT_STATUS_LOGON_FAILURE)) {
			/* we need to reset the vuid for a new try */
			session->vuid = 0;
			if (cli_credentials_wrong_password(state->io->in.credentials)) {
				nt_status = session_setup_spnego(c, session, 
								      state->io, 
								      &state->req);
				if (NT_STATUS_IS_OK(nt_status)) {
					talloc_free(check_req);
					c->status = nt_status;
					composite_continue_smb(c, state->req, request_handler, c);
					return;
				}
			}
		}
		if (!NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED) && 
		    !NT_STATUS_IS_OK(c->status)) {
			break;
		}
		if (NT_STATUS_EQUAL(state->gensec_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {

			/* The status value here, from the earlier pass at GENSEC is
			 * vital to the security of the system.  Even if the other end
			 * accepts, if GENSEC claims 'MORE_PROCESSING_REQUIRED' then
			 * you must keep feeding it blobs, or else the remote
			 * host/attacker might avoid mutal authentication
			 * requirements */
			
			state->gensec_status = gensec_update(session->gensec, state,
							 state->setup.spnego.out.secblob,
							 &state->setup.spnego.in.secblob);
			c->status = state->gensec_status;
			if (!NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED) && 
			    !NT_STATUS_IS_OK(c->status)) {
				break;
			}
		} else {
			state->setup.spnego.in.secblob = data_blob(NULL, 0);
		}

		if (NT_STATUS_IS_OK(state->remote_status)) {
			if (state->setup.spnego.in.secblob.length) {
				c->status = NT_STATUS_INTERNAL_ERROR;
				break;
			}
			session_key_err = gensec_session_key(session->gensec, session, &session->user_session_key);
			if (NT_STATUS_IS_OK(session_key_err)) {
				smbcli_transport_simple_set_signing(session->transport, session->user_session_key, null_data_blob);
			}
		}

		if (state->setup.spnego.in.secblob.length) {
			/* 
			 * set the session->vuid value only for calling
			 * smb_raw_sesssetup_send()
			 */
			uint16_t vuid = session->vuid;
			session->vuid = state->io->out.vuid;
			state->req = smb_raw_sesssetup_send(session, &state->setup);
			session->vuid = vuid;
			if (state->req) {
				state->req->sign_caller_checks = true;
			}
			composite_continue_smb(c, state->req, request_handler, c);
			return;
		}
		os = state->setup.spnego.out.os;
		lanman = state->setup.spnego.out.lanman;
		break;

	case RAW_SESSSETUP_SMB2:
		c->status = NT_STATUS_INTERNAL_ERROR;
		break;
	}

	if (check_req) {
		check_req->sign_caller_checks = false;
		if (!smbcli_request_check_sign_mac(check_req)) {
			c->status = NT_STATUS_ACCESS_DENIED;
		}
		talloc_free(check_req);
		check_req = NULL;
	}

	/* enforce the local signing required flag */
	if (NT_STATUS_IS_OK(c->status) && !cli_credentials_is_anonymous(state->io->in.credentials)) {
		if (!session->transport->negotiate.sign_info.doing_signing 
		    && session->transport->negotiate.sign_info.mandatory_signing) {
			DEBUG(0, ("SMB signing required, but server does not support it\n"));
			c->status = NT_STATUS_ACCESS_DENIED;
		}
	}

	if (!NT_STATUS_IS_OK(c->status)) {
		composite_error(c, c->status);
		return;
	}

	if (os) {
		session->os = talloc_strdup(session, os);
		if (composite_nomem(session->os, c)) return;
	} else {
		session->os = NULL;
	}
	if (lanman) {
		session->lanman = talloc_strdup(session, lanman);
		if (composite_nomem(session->lanman, c)) return;
	} else {
		session->lanman = NULL;
	}

	composite_done(c);
}