Beispiel #1
0
/****************************************************************************
check for existance of a trans2 call
****************************************************************************/
static NTSTATUS try_trans2(struct cli_state *cli, 
			 int op,
			 char *param, char *data,
			 int param_len, int data_len,
			 unsigned int *rparam_len, unsigned int *rdata_len)
{
	uint16 setup = op;
	char *rparam=NULL, *rdata=NULL;

	if (!cli_send_trans(cli, SMBtrans2, 
                            NULL,                           /* name */
                            -1, 0,                          /* fid, flags */
                            &setup, 1, 0,                   /* setup, length, max */
                            param, param_len, 2,            /* param, length, max */
                            data, data_len, cli->max_xmit   /* data, length, max */
                           )) {
		return cli_nt_error(cli);
	}

	cli_receive_trans(cli, SMBtrans2,
			   &rparam, rparam_len,
			   &rdata, rdata_len);

	SAFE_FREE(rdata);
	SAFE_FREE(rparam);

	return cli_nt_error(cli);
}
Beispiel #2
0
int cli_errno(struct cli_state *cli)
{
	NTSTATUS status;

	if (cli_is_nt_error(cli)) {
		status = cli_nt_error(cli);
		return map_errno_from_nt_status(status);
	}

        if (cli_is_dos_error(cli)) {
                uint8 eclass;
                uint32 ecode;

                cli_dos_error(cli, &eclass, &ecode);
		status = dos_to_ntstatus(eclass, ecode);
		return map_errno_from_nt_status(status);
        }

        /*
         * Yuck!  A special case for this Vista error.  Since its high-order
         * byte isn't 0xc0, it doesn't match cli_is_nt_error() above.
         */
        status = cli_nt_error(cli);
        if (NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_INACCESSIBLE_SYSTEM_SHORTCUT)) {
            return EACCES;
        }

	/* for other cases */
	return EINVAL;
}
Beispiel #3
0
/****************************************************************************
check for existance of a nttrans call
****************************************************************************/
static NTSTATUS try_nttrans(struct cli_state *cli, 
			 int op,
			 char *param, char *data,
			 int param_len, int data_len,
			 unsigned int *rparam_len, unsigned int *rdata_len)
{
	char *rparam=NULL, *rdata=NULL;

	if (!cli_send_nt_trans(cli, op, 
			       0,   
			       NULL, 0, 0,
			       param, param_len, 2,            /* param, length, max */
			       data, data_len, cli->max_xmit   /* data, length, max */
                           )) {
		return cli_nt_error(cli);
	}

	cli_receive_nt_trans(cli,
			     &rparam, rparam_len,
			     &rdata, rdata_len);

	SAFE_FREE(rdata);
	SAFE_FREE(rparam);

	return cli_nt_error(cli);
}
Beispiel #4
0
/*
 * Convert an SMB error into a UNIX error ...
 */
int
SMBC_errno(SMBCCTX *context,
           struct cli_state *c)
{
	int ret = cli_errno(c);

        if (cli_is_dos_error(c)) {
                uint8 eclass;
                uint32 ecode;

                cli_dos_error(c, &eclass, &ecode);

                DEBUG(3,("smbc_error %d %d (0x%x) -> %d\n",
                         (int)eclass, (int)ecode, (int)ecode, ret));
        } else {
                NTSTATUS status;

                status = cli_nt_error(c);

                DEBUG(3,("smbc errno %s -> %d\n",
                         nt_errstr(status), ret));
        }

	return ret;
}
Beispiel #5
0
/* 
   send a raw ioctl - used by the torture code
*/
NTSTATUS cli_raw_ioctl(struct cli_state *cli, int fnum, uint32 code, DATA_BLOB *blob)
{
	memset(cli->outbuf,'\0',smb_size);
	memset(cli->inbuf,'\0',smb_size);

	set_message(cli->outbuf, 3, 0, True);
	SCVAL(cli->outbuf,smb_com,SMBioctl);
	cli_setup_packet(cli);

	SSVAL(cli->outbuf, smb_vwv0, fnum);
	SSVAL(cli->outbuf, smb_vwv1, code>>16);
	SSVAL(cli->outbuf, smb_vwv2, (code&0xFFFF));

	cli_send_smb(cli);
	if (!cli_receive_smb(cli)) {
		return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
	}

	if (cli_is_error(cli)) {
		return cli_nt_error(cli);
	}

	*blob = data_blob(NULL, 0);

	return NT_STATUS_OK;
}
Beispiel #6
0
static NTSTATUS enc_blob_send_receive(struct cli_state *cli, DATA_BLOB *in, DATA_BLOB *out, DATA_BLOB *param_out)
{
	uint16 setup;
	char param[4];
	char *rparam=NULL, *rdata=NULL;
	unsigned int rparam_count=0, rdata_count=0;
	NTSTATUS status = NT_STATUS_OK;

	setup = TRANSACT2_SETFSINFO;

	SSVAL(param,0,0);
	SSVAL(param,2,SMB_REQUEST_TRANSPORT_ENCRYPTION);

	if (!cli_send_trans(cli, SMBtrans2,
				NULL,
				0, 0,
				&setup, 1, 0,
				param, 4, 0,
				(char *)in->data, in->length, CLI_BUFFER_SIZE)) {
		status = cli_nt_error(cli);
		goto out;
	}

	if (!cli_receive_trans(cli, SMBtrans2,
				&rparam, &rparam_count,
				&rdata, &rdata_count)) {
		status = cli_nt_error(cli);
		goto out;
	}

	if (cli_is_error(cli)) {
		status = cli_nt_error(cli);
		if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
			goto out;
		}
	}

	*out = data_blob(rdata, rdata_count);
	*param_out = data_blob(rparam, rparam_count);

  out:

	SAFE_FREE(rparam);
	SAFE_FREE(rdata);
	return status;
}
Beispiel #7
0
NTSTATUS cli_get_nt_error(struct cli_state *cli)
{
    if (cli_is_nt_error(cli)) {
        return cli_nt_error(cli);
    } else if (cli_is_dos_error(cli)) {
        uint32 ecode;
        uint8 eclass;
        cli_dos_error(cli, &eclass, &ecode);
        return dos_to_ntstatus(eclass, ecode);
    } else {
        /* Something went wrong, we don't know what. */
        return NT_STATUS_UNSUCCESSFUL;
    }
}
Beispiel #8
0
/****************************************************************************
 send a lock with a specified locktype 
 this is used for testing LOCKING_ANDX_CANCEL_LOCK
****************************************************************************/
NTSTATUS cli_locktype(struct cli_state *cli, int fnum, 
		      uint32 offset, uint32 len, int timeout, unsigned char locktype)
{
	char *p;
	int saved_timeout = cli->timeout;

	memset(cli->outbuf,'\0',smb_size);
	memset(cli->inbuf,'\0', smb_size);

	set_message(cli->outbuf,8,0,True);

	SCVAL(cli->outbuf,smb_com,SMBlockingX);
	SSVAL(cli->outbuf,smb_tid,cli->cnum);
	cli_setup_packet(cli);

	SCVAL(cli->outbuf,smb_vwv0,0xFF);
	SSVAL(cli->outbuf,smb_vwv2,fnum);
	SCVAL(cli->outbuf,smb_vwv3,locktype);
	SIVALS(cli->outbuf, smb_vwv4, timeout);
	SSVAL(cli->outbuf,smb_vwv6,0);
	SSVAL(cli->outbuf,smb_vwv7,1);

	p = smb_buf(cli->outbuf);
	SSVAL(p, 0, cli->pid);
	SIVAL(p, 2, offset);
	SIVAL(p, 6, len);

	p += 10;

	cli_setup_bcc(cli, p);

	cli_send_smb(cli);

	if (timeout != 0) {
		cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout + 2*1000);
	}

	if (!cli_receive_smb(cli)) {
		cli->timeout = saved_timeout;
		return NT_STATUS_UNSUCCESSFUL;
	}

	cli->timeout = saved_timeout;

	return cli_nt_error(cli);
}
Beispiel #9
0
NTSTATUS cli_full_connection(struct cli_state **output_cli, 
			     const char *my_name, const char *dest_host, 
			     struct in_addr *dest_ip, int port,
			     const char *service, const char *service_type,
			     const char *user, const char *domain, 
			     const char *password, int pass_len) 
{
	struct ntuser_creds creds;
	NTSTATUS nt_status;
	struct nmb_name calling;
	struct nmb_name called;
	struct cli_state *cli;
	struct in_addr ip;
	
	if (!output_cli)
		DEBUG(0, ("output_cli is NULL!?!"));

	*output_cli = NULL;
	
	make_nmb_name(&calling, my_name, 0x0);
	make_nmb_name(&called , dest_host, 0x20);

again:

	if (!(cli = cli_initialise(NULL)))
		return NT_STATUS_NO_MEMORY;
	
	if (cli_set_port(cli, port) != port) {
		cli_shutdown(cli);
		return NT_STATUS_UNSUCCESSFUL;
	}

	ip = *dest_ip;
	
	DEBUG(3,("Connecting to host=%s share=%s\n", dest_host, service));
	
	if (!cli_connect(cli, dest_host, &ip)) {
		DEBUG(1,("cli_establish_connection: failed to connect to %s (%s)\n",
			 nmb_namestr(&called), inet_ntoa(*dest_ip)));
		cli_shutdown(cli);
		return NT_STATUS_UNSUCCESSFUL;
	}

	if (!cli_session_request(cli, &calling, &called)) {
		char *p;
		DEBUG(1,("session request to %s failed (%s)\n", 
			 called.name, cli_errstr(cli)));
		cli_shutdown(cli);
		if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
			*p = 0;
			goto again;
		}
		if (strcmp(called.name, "*SMBSERVER")) {
			make_nmb_name(&called , "*SMBSERVER", 0x20);
			goto again;
		}
		return NT_STATUS_UNSUCCESSFUL;
	}

	if (!cli_negprot(cli)) {
		DEBUG(1,("failed negprot\n"));
		nt_status = NT_STATUS_UNSUCCESSFUL;
		cli_shutdown(cli);
		return nt_status;
	}

	if (!cli_session_setup(cli, user, password, pass_len, password, pass_len, 
			       domain)) {
		DEBUG(1,("failed session setup\n"));
		nt_status = cli_nt_error(cli);
		cli_shutdown(cli);
		if (NT_STATUS_IS_OK(nt_status)) 
			nt_status = NT_STATUS_UNSUCCESSFUL;
		return nt_status;
	} 

	if (service) {
		if (!cli_send_tconX(cli, service, service_type,
				    password, pass_len)) {
			DEBUG(1,("failed tcon_X\n"));
			nt_status = cli_nt_error(cli);
			cli_shutdown(cli);
			if (NT_STATUS_IS_OK(nt_status)) 
				nt_status = NT_STATUS_UNSUCCESSFUL;
			return nt_status;
		}
	}

	init_creds(&creds, user, domain, password, pass_len);
	cli_init_creds(cli, &creds);

	*output_cli = cli;
	return NT_STATUS_OK;
}
Beispiel #10
0
NTSTATUS remote_password_change(const char *remote_machine, const char *user_name, 
				const char *old_passwd, const char *new_passwd,
				char **err_str)
{
	struct cli_state *cli = NULL;
	struct rpc_pipe_client *pipe_hnd = NULL;
	char *user, *domain, *p;

	NTSTATUS result;
	bool pass_must_change = False;

	user = talloc_strdup(talloc_tos(), user_name);
	SMB_ASSERT(user != NULL);
	domain = talloc_strdup(talloc_tos(), "");
	SMB_ASSERT(domain != NULL);

	/* allow usernames of the form domain\\user or domain/user */
	if ((p = strchr_m(user,'\\')) || (p = strchr_m(user,'/')) ||
	    (p = strchr_m(user,*lp_winbind_separator()))) {
		*p = 0;
		domain = user;
		user = p+1;
	}

	*err_str = NULL;

	result = cli_connect_nb(remote_machine, NULL, 0, 0x20, NULL,
				SMB_SIGNING_DEFAULT, 0, &cli);
	if (!NT_STATUS_IS_OK(result)) {
		if (asprintf(err_str, "Unable to connect to SMB server on "
			 "machine %s. Error was : %s.\n",
			 remote_machine, nt_errstr(result))==-1) {
			*err_str = NULL;
		}
		return result;
	}

	result = cli_negprot(cli, PROTOCOL_NT1);

	if (!NT_STATUS_IS_OK(result)) {
		if (asprintf(err_str, "machine %s rejected the negotiate "
			 "protocol. Error was : %s.\n",        
			 remote_machine, nt_errstr(result)) == -1) {
			*err_str = NULL;
		}
		cli_shutdown(cli);
		return result;
	}

	/* Given things like SMB signing, restrict anonymous and the like, 
	   try an authenticated connection first */
	result = cli_session_setup(cli, user_name,
				   old_passwd, strlen(old_passwd)+1,
				   old_passwd, strlen(old_passwd)+1, "");

	if (!NT_STATUS_IS_OK(result)) {

		/* Password must change or Password expired are the only valid
		 * error conditions here from where we can proceed, the rest like
		 * account locked out or logon failure will lead to errors later
		 * anyway */

		if (!NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_MUST_CHANGE) &&
		    !NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_EXPIRED)) {
			if (asprintf(err_str, "Could not connect to machine %s: "
				 "%s\n", remote_machine, nt_errstr(result)) == -1) {
				*err_str = NULL;
			}
			cli_shutdown(cli);
			return result;
		}

		pass_must_change = True;

		/*
		 * We should connect as the anonymous user here, in case
		 * the server has "must change password" checked...
		 * Thanks to <*****@*****.**> for this fix.
		 */

		result = cli_session_setup(cli, "", "", 0, "", 0, "");

		if (!NT_STATUS_IS_OK(result)) {
			if (asprintf(err_str, "machine %s rejected the session "
				 "setup. Error was : %s.\n",        
				 remote_machine, nt_errstr(result)) == -1) {
				*err_str = NULL;
			}
			cli_shutdown(cli);
			return result;
		}

		result = cli_init_creds(cli, "", "", NULL);
		if (!NT_STATUS_IS_OK(result)) {
			cli_shutdown(cli);
			return result;
		}
	} else {
		result = cli_init_creds(cli, user, domain, old_passwd);
		if (!NT_STATUS_IS_OK(result)) {
			cli_shutdown(cli);
			return result;
		}
	}

	result = cli_tree_connect(cli, "IPC$", "IPC", "", 1);
	if (!NT_STATUS_IS_OK(result)) {
		if (asprintf(err_str, "machine %s rejected the tconX on the "
			     "IPC$ share. Error was : %s.\n",
			     remote_machine, nt_errstr(result))) {
			*err_str = NULL;
		}
		cli_shutdown(cli);
		return result;
	}

	/* Try not to give the password away too easily */

	if (!pass_must_change) {
		result = cli_rpc_pipe_open_ntlmssp(cli,
						   &ndr_table_samr.syntax_id,
						   NCACN_NP,
						   DCERPC_AUTH_LEVEL_PRIVACY,
						   domain, user,
						   old_passwd,
						   &pipe_hnd);
	} else {
		/*
		 * If the user password must be changed the ntlmssp bind will
		 * fail the same way as the session setup above did. The
		 * difference ist that with a pipe bind we don't get a good
		 * error message, the result will be that the rpc call below
		 * will just fail. So we do it anonymously, there's no other
		 * way.
		 */
		result = cli_rpc_pipe_open_noauth(
			cli, &ndr_table_samr.syntax_id, &pipe_hnd);
	}

	if (!NT_STATUS_IS_OK(result)) {
		if (lp_client_lanman_auth()) {
			/* Use the old RAP method. */
			if (!cli_oem_change_password(cli, user_name, new_passwd, old_passwd)) {
				result = cli_nt_error(cli);
				if (asprintf(err_str, "machine %s rejected the "
					 "password change: Error was : %s.\n",
					 remote_machine, nt_errstr(result)) == -1) {
					*err_str = NULL;
				}
				cli_shutdown(cli);
				return result;
			}
		} else {
			if (asprintf(err_str, "SAMR connection to machine %s "
				 "failed. Error was %s, but LANMAN password "
				 "changes are disabled\n",
				 remote_machine, nt_errstr(result)) == -1) {
				*err_str = NULL;
			}
			cli_shutdown(cli);
			return result;
		}
	}

	result = rpccli_samr_chgpasswd_user2(pipe_hnd, talloc_tos(),
					     user_name, new_passwd, old_passwd);
	if (NT_STATUS_IS_OK(result)) {
		/* Great - it all worked! */
		cli_shutdown(cli);
		return NT_STATUS_OK;

	} else if (!(NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) 
		     || NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL))) {
		/* it failed, but for reasons such as wrong password, too short etc ... */

		if (asprintf(err_str, "machine %s rejected the password change: "
			 "Error was : %s.\n",
			 remote_machine, get_friendly_nt_error_msg(result)) == -1) {
			*err_str = NULL;
		}
		cli_shutdown(cli);
		return result;
	}

	/* OK, that failed, so try again... */
	TALLOC_FREE(pipe_hnd);

	/* Try anonymous NTLMSSP... */
	result = cli_init_creds(cli, "", "", NULL);
	if (!NT_STATUS_IS_OK(result)) {
		cli_shutdown(cli);
		return result;
	}

	result = NT_STATUS_UNSUCCESSFUL;

	/* OK, this is ugly, but... try an anonymous pipe. */
	result = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr.syntax_id,
					  &pipe_hnd);

	if ( NT_STATUS_IS_OK(result) &&
		(NT_STATUS_IS_OK(result = rpccli_samr_chgpasswd_user2(
					 pipe_hnd, talloc_tos(), user_name,
					 new_passwd, old_passwd)))) {
		/* Great - it all worked! */
		cli_shutdown(cli);
		return NT_STATUS_OK;
	} else {
		if (!(NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) 
		      || NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL))) {
			/* it failed, but again it was due to things like new password too short */

			if (asprintf(err_str, "machine %s rejected the "
				 "(anonymous) password change: Error was : "
				 "%s.\n", remote_machine,
				 get_friendly_nt_error_msg(result)) == -1) {
				*err_str = NULL;
			}
			cli_shutdown(cli);
			return result;
		}

		/* We have failed to change the user's password, and we think the server
		   just might not support SAMR password changes, so fall back */

		if (lp_client_lanman_auth()) {
			/* Use the old RAP method. */
			if (cli_oem_change_password(cli, user_name, new_passwd, old_passwd)) {
				/* SAMR failed, but the old LanMan protocol worked! */

				cli_shutdown(cli);
				return NT_STATUS_OK;
			}

			result = cli_nt_error(cli);
			if (asprintf(err_str, "machine %s rejected the password "
				 "change: Error was : %s.\n",
				 remote_machine, nt_errstr(result)) == -1) {
				*err_str = NULL;
			}
			cli_shutdown(cli);
			return result;
		} else {
			if (asprintf(err_str, "SAMR connection to machine %s "
				 "failed. Error was %s, but LANMAN password "
				 "changes are disabled\n",
				nt_errstr(result), remote_machine) == -1) {
				*err_str = NULL;
			}
			cli_shutdown(cli);
			return NT_STATUS_UNSUCCESSFUL;
		}
	}
}
Beispiel #11
0
bool cli_receive_nt_trans(struct cli_state *cli,
			  char **param, unsigned int *param_len,
			  char **data, unsigned int *data_len)
{
	unsigned int total_data=0;
	unsigned int total_param=0;
	unsigned int this_data,this_param;
	uint8 eclass;
	uint32 ecode;
	bool ret = False;
	uint16_t mid;

	*data_len = *param_len = 0;

	mid = SVAL(cli->outbuf,smb_mid);

	if (!cli_receive_smb(cli)) {
		cli_state_seqnum_remove(cli, mid);
		return False;
	}

	show_msg(cli->inbuf);

	/* sanity check */
	if (CVAL(cli->inbuf,smb_com) != SMBnttrans) {
		DEBUG(0,("Expected SMBnttrans response, got command 0x%02x\n",
			 CVAL(cli->inbuf,smb_com)));
		cli_state_seqnum_remove(cli, mid);
		return(False);
	}

	/*
	 * An NT RPC pipe call can return ERRDOS, ERRmoredata
	 * to a trans call. This is not an error and should not
	 * be treated as such.
	 */
	if (cli_is_dos_error(cli)) {
                cli_dos_error(cli, &eclass, &ecode);
		if (!(eclass == ERRDOS && ecode == ERRmoredata)) {
			goto out;
		}
	}

	/*
	 * Likewise for NT_STATUS_BUFFER_TOO_SMALL
	 */
	if (cli_is_nt_error(cli)) {
		if (!NT_STATUS_EQUAL(cli_nt_error(cli),
				     NT_STATUS_BUFFER_TOO_SMALL)) {
			goto out;
		}
	}

	/* parse out the lengths */
	total_data = IVAL(cli->inbuf,smb_ntr_TotalDataCount);
	total_param = IVAL(cli->inbuf,smb_ntr_TotalParameterCount);
	/* Only allow 16 megs. */
	if (total_param > 16*1024*1024) {
		DEBUG(0,("cli_receive_nt_trans: param buffer too large %d\n",
					total_param));
		goto out;
	}
	if (total_data > 16*1024*1024) {
		DEBUG(0,("cli_receive_nt_trans: data buffer too large %d\n",
					total_data));
		goto out;
	}

	/* allocate it */
	if (total_data) {
		/* We know adding 2 is safe as total_data is less
		 * than 16mb (above). */
		*data = (char *)SMB_REALLOC(*data,total_data+2);
		if (!(*data)) {
			DEBUG(0,("cli_receive_nt_trans: failed to enlarge data buffer to %d\n",total_data));
			goto out;
		}
	}

	if (total_param) {
		/* We know adding 2 is safe as total_param is less
		 * than 16mb (above). */
		*param = (char *)SMB_REALLOC(*param,total_param+2);
		if (!(*param)) {
			DEBUG(0,("cli_receive_nt_trans: failed to enlarge param buffer to %d\n", total_param));
			goto out;
		}
	}

	while (1)  {
		this_data = SVAL(cli->inbuf,smb_ntr_DataCount);
		this_param = SVAL(cli->inbuf,smb_ntr_ParameterCount);

		if (this_data + *data_len > total_data ||
		    this_param + *param_len > total_param) {
			DEBUG(1,("Data overflow in cli_receive_nt_trans\n"));
			goto out;
		}

		if (this_data + *data_len < this_data ||
				this_data + *data_len < *data_len ||
				this_param + *param_len < this_param ||
				this_param + *param_len < *param_len) {
			DEBUG(1,("Data overflow in cli_receive_nt_trans\n"));
			goto out;
		}

		if (this_data) {
			unsigned int data_offset_out = SVAL(cli->inbuf,smb_ntr_DataDisplacement);
			unsigned int data_offset_in = SVAL(cli->inbuf,smb_ntr_DataOffset);

			if (data_offset_out > total_data ||
					data_offset_out + this_data > total_data ||
					data_offset_out + this_data < data_offset_out ||
					data_offset_out + this_data < this_data) {
				DEBUG(1,("Data overflow in cli_receive_nt_trans\n"));
				goto out;
			}
			if (data_offset_in > cli->bufsize ||
					data_offset_in + this_data >  cli->bufsize ||
					data_offset_in + this_data < data_offset_in ||
					data_offset_in + this_data < this_data) {
				DEBUG(1,("Data overflow in cli_receive_nt_trans\n"));
				goto out;
			}

			memcpy(*data + data_offset_out, smb_base(cli->inbuf) + data_offset_in, this_data);
		}

		if (this_param) {
			unsigned int param_offset_out = SVAL(cli->inbuf,smb_ntr_ParameterDisplacement);
			unsigned int param_offset_in = SVAL(cli->inbuf,smb_ntr_ParameterOffset);

			if (param_offset_out > total_param ||
					param_offset_out + this_param > total_param ||
					param_offset_out + this_param < param_offset_out ||
					param_offset_out + this_param < this_param) {
				DEBUG(1,("Param overflow in cli_receive_nt_trans\n"));
				goto out;
			}
			if (param_offset_in > cli->bufsize ||
					param_offset_in + this_param >  cli->bufsize ||
					param_offset_in + this_param < param_offset_in ||
					param_offset_in + this_param < this_param) {
				DEBUG(1,("Param overflow in cli_receive_nt_trans\n"));
				goto out;
			}

			memcpy(*param + param_offset_out, smb_base(cli->inbuf) + param_offset_in, this_param);
		}

		*data_len += this_data;
		*param_len += this_param;

		if (total_data <= *data_len && total_param <= *param_len) {
			ret = True;
			break;
		}

		if (!cli_receive_smb(cli)) {
			goto out;
		}

		show_msg(cli->inbuf);

		/* sanity check */
		if (CVAL(cli->inbuf,smb_com) != SMBnttrans) {
			DEBUG(0,("Expected SMBnttrans response, got command 0x%02x\n",
				 CVAL(cli->inbuf,smb_com)));
			goto out;
		}
		if (cli_is_dos_error(cli)) {
                        cli_dos_error(cli, &eclass, &ecode);
			if(!(eclass == ERRDOS && ecode == ERRmoredata)) {
				goto out;
			}
		}
		/*
		 * Likewise for NT_STATUS_BUFFER_TOO_SMALL
		 */
		if (cli_is_nt_error(cli)) {
			if (!NT_STATUS_EQUAL(cli_nt_error(cli),
					     NT_STATUS_BUFFER_TOO_SMALL)) {
				goto out;
			}
		}

		/* parse out the total lengths again - they can shrink! */
		if (IVAL(cli->inbuf,smb_ntr_TotalDataCount) < total_data)
			total_data = IVAL(cli->inbuf,smb_ntr_TotalDataCount);
		if (IVAL(cli->inbuf,smb_ntr_TotalParameterCount) < total_param)
			total_param = IVAL(cli->inbuf,smb_ntr_TotalParameterCount);

		if (total_data <= *data_len && total_param <= *param_len) {
			ret = True;
			break;
		}
	}

  out:

	cli_state_seqnum_remove(cli, mid);

	if (ret) {
		/* Ensure the last 2 bytes of param and data are 2 null
		 * bytes. These are malloc'ed, but not included in any
		 * length counts. This allows cli_XX string reading functions
		 * to safely null terminate. */
		if (total_data) {
			SSVAL(*data,total_data,0);
		}
		if (total_param) {
			SSVAL(*param,total_param,0);
		}
	}

	return ret;
}
Beispiel #12
0
static int join_domain_byuser(char *domain, const char *remote,
			      char *username, char *password)
{
	/* libsmb variables */

	pstring pdc_name;
	struct nmb_name calling, called;
	struct ntuser_creds creds;
	struct cli_state cli;
	fstring acct_name;
	struct in_addr dest_ip;
	TALLOC_CTX *mem_ctx;

	/* rpc variables */

	POLICY_HND lsa_pol, sam_pol, domain_pol, user_pol;
	DOM_SID domain_sid;
	uint32 user_rid;

	/* Password stuff */

	char *machine_pwd;
	int plen = 0;
	uchar pwbuf[516], ntpw[16], sess_key[16];
	SAM_USERINFO_CTR ctr;
	SAM_USER_INFO_24 p24;
	SAM_USER_INFO_10 p10;

	/* Misc */

	NTSTATUS result;
	int retval = 1;

	pstrcpy(pdc_name, remote ? remote : "");

	/* Connect to remote machine */

	ZERO_STRUCT(cli);
	ZERO_STRUCT(creds);
	ZERO_STRUCT(dest_ip); /* Make sure no nasty surprises */

	if (!(mem_ctx = talloc_init())) {
		DEBUG(0, ("Could not initialise talloc context\n"));
		goto done;
	}

	if (!cli_initialise(&cli)) {
		DEBUG(0, ("Could not initialise client structure\n"));
		goto done;
	}

	init_rpcclient_creds(&creds, username, domain, password);
	cli_init_creds(&cli, &creds);

	/*
	 * If we are given a remote machine assume this is the PDC.
	 */
	
	if(remote == NULL || !strcmp(remote, "*")) {
                struct in_addr *ip_list;
                int addr_count;
                if (!get_dc_list(True /* PDC only*/, domain, &ip_list, &addr_count)) {
			fprintf(stderr, "Unable to find the domain controller for domain %s.\n", domain);
			return 1;
		}
		if ((addr_count < 1) || (is_zero_ip(ip_list[0]))) {
			fprintf(stderr, "Incorrect entries returned when finding the domain controller for domain %s.\n", domain);
			return 1;
		}

		if (!lookup_dc_name(global_myname, domain, &ip_list[0], pdc_name)) {
			fprintf(stderr, "Unable to lookup the name for the domain controller for domain %s.\n", domain);
			return 1;
		}
		dest_ip = ip_list[0];
	}

	make_nmb_name(&called, pdc_name, 0x20);
	make_nmb_name(&calling, dns_to_netbios_name(global_myname), 0);

	if (!cli_establish_connection(&cli, pdc_name, &dest_ip, &calling, 
				      &called, "IPC$", "IPC", False, True)) {
		if (!NT_STATUS_IS_OK(cli_nt_error(&cli))) {
			DEBUG(0, ("Error connecting to %s - %s\n", pdc_name,cli_errstr(&cli)));
		} else {
			DEBUG(0, ("Error connecting to %s\n", pdc_name));
		}
		goto done;
	}

	/* Fetch domain sid */

	if (!cli_nt_session_open(&cli, PIPE_LSARPC)) {
		DEBUG(0, ("Error connecting to SAM pipe\n"));
		goto done;
	}


	CHECK_RPC_ERR(cli_lsa_open_policy(&cli, mem_ctx, True,
					  SEC_RIGHTS_MAXIMUM_ALLOWED,
					  &lsa_pol),
		      "error opening lsa policy handle");

	CHECK_RPC_ERR(cli_lsa_query_info_policy(&cli, mem_ctx, &lsa_pol,
						5, domain, &domain_sid),
		      "error querying info policy");

	cli_lsa_close(&cli, mem_ctx, &lsa_pol);

	cli_nt_session_close(&cli); /* Done with this pipe */

	/* Create domain user */

	if (!cli_nt_session_open(&cli, PIPE_SAMR)) {
		DEBUG(0, ("Error connecting to SAM pipe\n"));
		goto done;
	}

	CHECK_RPC_ERR(cli_samr_connect(&cli, mem_ctx, 
				       SEC_RIGHTS_MAXIMUM_ALLOWED,
				       &sam_pol),
		      "could not connect to SAM database");

	
	CHECK_RPC_ERR(cli_samr_open_domain(&cli, mem_ctx, &sam_pol,
					   SEC_RIGHTS_MAXIMUM_ALLOWED,
					   &domain_sid, &domain_pol),
		      "could not open domain");

	/* Create domain user */

	fstrcpy(acct_name, global_myname);
	fstrcat(acct_name, "$");

	strlower(acct_name);

	{
		uint32 unknown = 0xe005000b;

		result = cli_samr_create_dom_user(&cli, mem_ctx, &domain_pol,
						  acct_name, ACB_WSTRUST,
						  unknown, &user_pol, 
						  &user_rid);
	}


	if (NT_STATUS_IS_OK(result)) {

		/* We *must* do this.... don't ask... */
	  
		CHECK_RPC_ERR_DEBUG(cli_samr_close(&cli, mem_ctx, &user_pol), ("error closing user policy"));
		result = NT_STATUS_USER_EXISTS;
	}

	if (NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_USER_EXISTS)) {
		uint32 num_rids, *name_types, *user_rids;
		uint32 flags = 0x3e8;
		const char *names;
		
		/* Look up existing rid */
		
		names = (char *)&acct_name[0];

		CHECK_RPC_ERR_DEBUG(
			cli_samr_lookup_names(&cli, mem_ctx,
					      &domain_pol, flags,
					      1, &names, &num_rids,
					      &user_rids, &name_types),
			("error looking up rid for user %s: %s\n",
			 acct_name, get_nt_error_msg(result)));

		if (name_types[0] != SID_NAME_USER) {
			DEBUG(0, ("%s is not a user account\n", acct_name));
			goto done;
		}

		user_rid = user_rids[0];
		
		/* Open handle on user */

		CHECK_RPC_ERR_DEBUG(
			cli_samr_open_user(&cli, mem_ctx, &domain_pol,
					   SEC_RIGHTS_MAXIMUM_ALLOWED,
					   user_rid, &user_pol),
			("could not re-open existing user %s: %s\n",
			 acct_name, get_nt_error_msg(result)));
		
	} else if (!NT_STATUS_IS_OK(result)) {
		DEBUG(0, ("error creating domain user: %s\n",
			  get_nt_error_msg(result)));
		goto done;
	}

	/* Create a random machine account password */

	{
		UNISTR2 upw;	/* Unicode password */

		upw.buffer = (uint16 *)talloc_zero(mem_ctx, 0xc * 
						   sizeof(uint16));

		upw.uni_str_len = 0xc;
		upw.uni_max_len = 0xc;

		machine_pwd = (char *)upw.buffer;
		plen = upw.uni_str_len * 2;
		generate_random_buffer((unsigned char *)machine_pwd, plen, True);

		encode_pw_buffer((char *)pwbuf, machine_pwd, plen, False);

		mdfour( ntpw, (unsigned char *)upw.buffer, plen);
	}

	/* Set password on machine account */

	ZERO_STRUCT(ctr);
	ZERO_STRUCT(p24);

	init_sam_user_info24(&p24, (char *)pwbuf,24);

	ctr.switch_value = 24;
	ctr.info.id24 = &p24;

	/* I don't think this is quite the right place for this
	   calculation.  It should be moved somewhere where the credentials
	   are calculated. )-: */

	mdfour(sess_key, cli.pwd.smb_nt_pwd, 16);

	CHECK_RPC_ERR(cli_samr_set_userinfo(&cli, mem_ctx, &user_pol, 24, 
					    sess_key, &ctr),
		      "error setting trust account password");

	/* Why do we have to try to (re-)set the ACB to be the same as what
	   we passed in the samr_create_dom_user() call?  When a NT
	   workstation is joined to a domain by an administrator the
	   acb_info is set to 0x80.  For a normal user with "Add
	   workstations to the domain" rights the acb_info is 0x84.  I'm
	   not sure whether it is supposed to make a difference or not.  NT
	   seems to cope with either value so don't bomb out if the set
	   userinfo2 level 0x10 fails.  -tpot */

	ZERO_STRUCT(ctr);
	ctr.switch_value = 0x10;
	ctr.info.id10 = &p10;

	init_sam_user_info10(&p10, ACB_WSTRUST);

	/* Ignoring the return value is necessary for joining a domain
	   as a normal user with "Add workstation to domain" privilege. */

	result = cli_samr_set_userinfo2(&cli, mem_ctx, &user_pol, 0x10, 
					sess_key, &ctr);

	/* Now store the secret in the secrets database */

	strupper(domain);

	if (!secrets_store_domain_sid(domain, &domain_sid) ||
	    !secrets_store_trust_account_password(domain, ntpw)) {
		DEBUG(0, ("error storing domain secrets\n"));
		goto done;
	}

	retval = 0;		/* Success! */

 done:
	/* Close down pipe - this will clean up open policy handles */

	if (cli.nt_pipe_fnum)
		cli_nt_session_close(&cli);

	/* Display success or failure */

	if (retval != 0) {
		trust_password_delete(domain);
		fprintf(stderr,"Unable to join domain %s.\n",domain);
	} else {
		printf("Joined domain %s.\n",domain);
	}
	
	return retval;
}
Beispiel #13
0
static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
				      const int sockfd,
				      const int pipe_index,
				      const char *controller,
				      struct cli_state **cli,
				      BOOL *retry)
{
	char *machine_password, *machine_krb5_principal;
	char *ipc_username, *ipc_domain, *ipc_password;

	BOOL got_mutex;
	BOOL add_failed_connection = True;

	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;

	struct sockaddr peeraddr;
	socklen_t peeraddr_len;

	struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;

	machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL,
							  NULL);
	
	if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(),
		     lp_realm()) == -1) {
		SAFE_FREE(machine_password);
		return NT_STATUS_NO_MEMORY;
	}

	cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);

	*retry = True;

	got_mutex = secrets_named_mutex(controller,
					WINBIND_SERVER_MUTEX_WAIT_TIME);

	if (!got_mutex) {
		DEBUG(0,("cm_open_connection: mutex grab failed for %s\n",
			 controller));
		result = NT_STATUS_POSSIBLE_DEADLOCK;
		goto done;
	}

	if ((*cli = cli_initialise(NULL)) == NULL) {
		DEBUG(1, ("Could not cli_initialize\n"));
		result = NT_STATUS_NO_MEMORY;
		goto done;
	}

	(*cli)->timeout = 10000; 	/* 10 seconds */
	(*cli)->fd = sockfd;
	fstrcpy((*cli)->desthost, controller);
	(*cli)->use_kerberos = True;

	peeraddr_len = sizeof(peeraddr);

	if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
	    (peeraddr_len != sizeof(struct sockaddr_in)) ||
	    (peeraddr_in->sin_family != PF_INET))
	{
		DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
		goto done;
	}

	if (ntohs(peeraddr_in->sin_port) == 139) {
		struct nmb_name calling;
		struct nmb_name called;

		make_nmb_name(&calling, global_myname(), 0x0);
		make_nmb_name(&called, "*SMBSERVER", 0x20);

		if (!cli_session_request(*cli, &calling, &called)) {
			DEBUG(8, ("cli_session_request failed for %s\n",
				  controller));
			goto done;
		}
	}

	cli_setup_signing_state(*cli, Undefined);

	if (!cli_negprot(*cli)) {
		DEBUG(1, ("cli_negprot failed\n"));
		cli_shutdown(*cli);
		goto done;
	}

	/* Krb5 session */
			
	if ((lp_security() == SEC_ADS) 
	    && ((*cli)->protocol >= PROTOCOL_NT1 &&
		(*cli)->capabilities & CAP_EXTENDED_SECURITY)) {

		ADS_STATUS ads_status;
		(*cli)->use_kerberos = True;
		DEBUG(5, ("connecting to %s from %s with kerberos principal "
			  "[%s]\n", controller, global_myname(),
			  machine_krb5_principal));

		ads_status = cli_session_setup_spnego(*cli,
						      machine_krb5_principal, 
						      machine_password, 
						      lp_workgroup());

		if (!ADS_ERR_OK(ads_status))
			DEBUG(4,("failed kerberos session setup with %s\n",
				 ads_errstr(ads_status)));

		result = ads_ntstatus(ads_status);
	}

	if (NT_STATUS_IS_OK(result))
		goto session_setup_done;

	/* Fall back to non-kerberos session setup */

	(*cli)->use_kerberos = False;

	if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
	    (strlen(ipc_username) > 0)) {

		/* Only try authenticated if we have a username */

		DEBUG(5, ("connecting to %s from %s with username "
			  "[%s]\\[%s]\n",  controller, global_myname(),
			  ipc_domain, ipc_username));

		if (cli_session_setup(*cli, ipc_username,
				      ipc_password, strlen(ipc_password)+1,
				      ipc_password, strlen(ipc_password)+1,
				      ipc_domain)) {
			DEBUG(5, ("authenticated session setup failed\n"));
			goto session_setup_done;
		}
	}

	/* Fall back to anonymous connection, this might fail later */

	if (cli_session_setup(*cli, "", NULL, 0, NULL, 0, "")) {
		DEBUG(5, ("Connected anonymously\n"));
		goto session_setup_done;
	}

	result = cli_nt_error(*cli);

	if (NT_STATUS_IS_OK(result))
		result = NT_STATUS_UNSUCCESSFUL;

	/* We can't session setup */

	goto done;

 session_setup_done:

	if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {

		result = cli_nt_error(*cli);

		DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));

		if (NT_STATUS_IS_OK(result))
			result = NT_STATUS_UNSUCCESSFUL;

		cli_shutdown(*cli);
		goto done;
	}

	secrets_named_mutex_release(controller);
	got_mutex = False;
	*retry = False;

	/* Windows 2003 SP1 does not lie LsaOpenPolicy() over schannel.
	   Returns RPC_NT_CANNOT_SUPPPORT (0xc0020041) for that call.
	   So just drop it on the lsarpc pipe */

	if ( (domain->primary || IS_DC) && (pipe_index!=PI_LSARPC) ) {
		NTSTATUS status = setup_schannel( *cli, domain->name );
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(3,("schannel refused - continuing without "
				 "schannel (%s)\n", nt_errstr(status)));
		}
	}

	/* set the domain if empty; needed for schannel connections */
	if ( !*(*cli)->domain )
		fstrcpy( (*cli)->domain, domain->name );

	if ( !cli_nt_session_open (*cli, pipe_index) ) {

		result = NT_STATUS_PIPE_NOT_AVAILABLE;

		/* This might be a NT4 DC */
		if ( is_win2k_pipe(pipe_index) )
			add_failed_connection = False;

		cli_shutdown(*cli);
		goto done;
	}

	result = NT_STATUS_OK;
	add_failed_connection = False;

 done:
	if (got_mutex)
		secrets_named_mutex_release(controller);

	SAFE_FREE(machine_password);
	SAFE_FREE(machine_krb5_principal);
	SAFE_FREE(ipc_username);
	SAFE_FREE(ipc_domain);
	SAFE_FREE(ipc_password);

	if (add_failed_connection)
		add_failed_connection_entry(domain->name, controller, result);

	return result;
}
Beispiel #14
0
static int			/* O - 0 = success, non-0 = failure */
smb_print(struct cli_state * cli,	/* I - SMB connection */
	  char *title,		/* I - Title/job name */
	  FILE * fp)
{				/* I - File to print */
	uint16_t             fnum;	/* File number */
	int             nbytes,	/* Number of bytes read */
	                tbytes;	/* Total bytes read */
	char            buffer[8192],	/* Buffer for copy */
	               *ptr;	/* Pointer into title */


	/*
         * Sanitize the title...
         */

	for (ptr = title; *ptr; ptr++) {
		if (!isalnum((int) *ptr) && !isspace((int) *ptr)) {
			*ptr = '_';
		}
	}

	/*
         * Open the printer device...
         */

	if (!NT_STATUS_IS_OK(cli_open(cli, title, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum))) {
		fprintf(stderr, "ERROR: %s opening remote spool %s\n",
			cli_errstr(cli), title);
		return (get_exit_code(cli, cli_nt_error(cli)));
	}

	/*
         * Copy the file to the printer...
         */

	if (fp != stdin)
		rewind(fp);

	tbytes = 0;

	while ((nbytes = fread(buffer, 1, sizeof(buffer), fp)) > 0) {
		if (cli_write(cli, fnum, 0, buffer, tbytes, nbytes) != nbytes) {
			int status = get_exit_code(cli, cli_nt_error(cli));

			fprintf(stderr, "ERROR: Error writing spool: %s\n", cli_errstr(cli));
			fprintf(stderr, "DEBUG: Returning status %d...\n", status);
			cli_close(cli, fnum);

			return (status);
		}
		tbytes += nbytes;
	}

	if (!NT_STATUS_IS_OK(cli_close(cli, fnum))) {
		fprintf(stderr, "ERROR: %s closing remote spool %s\n",
			cli_errstr(cli), title);
		return (get_exit_code(cli, cli_nt_error(cli)));
	} else {
		return (0);
	}
}
Beispiel #15
0
static NTSTATUS do_connect(TALLOC_CTX *ctx,
					const char *server,
					const char *share,
					const struct user_auth_info *auth_info,
					bool show_sessetup,
					bool force_encrypt,
					int max_protocol,
					int port,
					int name_type,
					struct cli_state **pcli)
{
	struct cli_state *c = NULL;
	char *servicename;
	char *sharename;
	char *newserver, *newshare;
	const char *username;
	const char *password;
	NTSTATUS status;

	/* make a copy so we don't modify the global string 'service' */
	servicename = talloc_strdup(ctx,share);
	if (!servicename) {
		return NT_STATUS_NO_MEMORY;
	}
	sharename = servicename;
	if (*sharename == '\\') {
		sharename += 2;
		if (server == NULL) {
			server = sharename;
		}
		sharename = strchr_m(sharename,'\\');
		if (!sharename) {
			return NT_STATUS_NO_MEMORY;
		}
		*sharename = 0;
		sharename++;
	}
	if (server == NULL) {
		return NT_STATUS_INVALID_PARAMETER;
	}

	status = cli_connect_nb(
		server, NULL, port, name_type, NULL,
		get_cmdline_auth_info_signing_state(auth_info), &c);

	if (!NT_STATUS_IS_OK(status)) {
		d_printf("Connection to %s failed (Error %s)\n",
				server,
				nt_errstr(status));
		return status;
	}

	if (max_protocol == 0) {
		max_protocol = PROTOCOL_NT1;
	}
	c->protocol = max_protocol;
	c->use_kerberos = get_cmdline_auth_info_use_kerberos(auth_info);
	c->fallback_after_kerberos =
		get_cmdline_auth_info_fallback_after_kerberos(auth_info);
	c->use_ccache = get_cmdline_auth_info_use_ccache(auth_info);

	DEBUG(4,(" session request ok\n"));

	status = cli_negprot(c);

	if (!NT_STATUS_IS_OK(status)) {
		d_printf("protocol negotiation failed: %s\n",
			 nt_errstr(status));
		cli_shutdown(c);
		return status;
	}

	username = get_cmdline_auth_info_username(auth_info);
	password = get_cmdline_auth_info_password(auth_info);

	status = cli_session_setup(c, username,
				   password, strlen(password),
				   password, strlen(password),
				   lp_workgroup());
	if (!NT_STATUS_IS_OK(status)) {
		/* If a password was not supplied then
		 * try again with a null username. */
		if (password[0] || !username[0] ||
			get_cmdline_auth_info_use_kerberos(auth_info) ||
			!NT_STATUS_IS_OK(status = cli_session_setup(c, "",
				    		"", 0,
						"", 0,
					       lp_workgroup()))) {
			d_printf("session setup failed: %s\n",
				 nt_errstr(status));
			if (NT_STATUS_V(cli_nt_error(c)) ==
			    NT_STATUS_V(NT_STATUS_MORE_PROCESSING_REQUIRED))
				d_printf("did you forget to run kinit?\n");
			cli_shutdown(c);
			return status;
		}
		d_printf("Anonymous login successful\n");
		status = cli_init_creds(c, "", lp_workgroup(), "");
	} else {
		status = cli_init_creds(c, username, lp_workgroup(), password);
	}

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10,("cli_init_creds() failed: %s\n", nt_errstr(status)));
		cli_shutdown(c);
		return status;
	}

	if ( show_sessetup ) {
		if (*c->server_domain) {
			DEBUG(0,("Domain=[%s] OS=[%s] Server=[%s]\n",
				c->server_domain,c->server_os,c->server_type));
		} else if (*c->server_os || *c->server_type) {
			DEBUG(0,("OS=[%s] Server=[%s]\n",
				 c->server_os,c->server_type));
		}
	}
	DEBUG(4,(" session setup ok\n"));

	/* here's the fun part....to support 'msdfs proxy' shares
	   (on Samba or windows) we have to issues a TRANS_GET_DFS_REFERRAL
	   here before trying to connect to the original share.
	   cli_check_msdfs_proxy() will fail if it is a normal share. */

	if ((c->capabilities & CAP_DFS) &&
			cli_check_msdfs_proxy(ctx, c, sharename,
				&newserver, &newshare,
				force_encrypt,
				username,
				password,
				lp_workgroup())) {
		cli_shutdown(c);
		return do_connect(ctx, newserver,
				newshare, auth_info, false,
				force_encrypt, max_protocol,
				port, name_type, pcli);
	}

	/* must be a normal share */

	status = cli_tcon_andx(c, sharename, "?????",
			       password, strlen(password)+1);
	if (!NT_STATUS_IS_OK(status)) {
		d_printf("tree connect failed: %s\n", nt_errstr(status));
		cli_shutdown(c);
		return status;
	}

	if (force_encrypt) {
		status = cli_cm_force_encryption(c,
					username,
					password,
					lp_workgroup(),
					sharename);
		if (!NT_STATUS_IS_OK(status)) {
			cli_shutdown(c);
			return status;
		}
	}

	DEBUG(4,(" tconx ok\n"));
	*pcli = c;
	return NT_STATUS_OK;
}
Beispiel #16
0
static struct cli_state *do_connect( const char *server, const char *share,
                                     BOOL show_sessetup )
{
	struct cli_state *c;
	struct nmb_name called, calling;
	const char *server_n;
	struct in_addr ip;
	pstring servicename;
	char *sharename;
	
	/* make a copy so we don't modify the global string 'service' */
	pstrcpy(servicename, share);
	sharename = servicename;
	if (*sharename == '\\') {
		server = sharename+2;
		sharename = strchr_m(server,'\\');
		if (!sharename) return NULL;
		*sharename = 0;
		sharename++;
	}

	server_n = server;
	
	zero_ip(&ip);

	make_nmb_name(&calling, global_myname(), 0x0);
	make_nmb_name(&called , server, name_type);

 again:
	zero_ip(&ip);
	if (have_ip) 
		ip = dest_ip;

	/* have to open a new connection */
	if (!(c=cli_initialise(NULL)) || (cli_set_port(c, port) != port) ||
	    !cli_connect(c, server_n, &ip)) {
		d_printf("Connection to %s failed\n", server_n);
		return NULL;
	}

	c->protocol = max_protocol;
	c->use_kerberos = use_kerberos;
	cli_setup_signing_state(c, signing_state);
		

	if (!cli_session_request(c, &calling, &called)) {
		char *p;
		d_printf("session request to %s failed (%s)\n", 
			 called.name, cli_errstr(c));
		cli_shutdown(c);
		if ((p=strchr_m(called.name, '.'))) {
			*p = 0;
			goto again;
		}
		if (strcmp(called.name, "*SMBSERVER")) {
			make_nmb_name(&called , "*SMBSERVER", 0x20);
			goto again;
		}
		return NULL;
	}

	DEBUG(4,(" session request ok\n"));

	if (!cli_negprot(c)) {
		d_printf("protocol negotiation failed\n");
		cli_shutdown(c);
		return NULL;
	}

	if (!got_pass) {
		char *pass = getpass("Password: "******"", "", 0, "", 0, lp_workgroup())) { 
			d_printf("session setup failed: %s\n", cli_errstr(c));
			if (NT_STATUS_V(cli_nt_error(c)) == 
			    NT_STATUS_V(NT_STATUS_MORE_PROCESSING_REQUIRED))
				d_printf("did you forget to run kinit?\n");
			cli_shutdown(c);
			return NULL;
		}
		d_printf("Anonymous login successful\n");
	}

	if ( show_sessetup ) {
		if (*c->server_domain) {
			DEBUG(0,("Domain=[%s] OS=[%s] Server=[%s]\n",
				c->server_domain,c->server_os,c->server_type));
		} else if (*c->server_os || *c->server_type){
			DEBUG(0,("OS=[%s] Server=[%s]\n",
				 c->server_os,c->server_type));
		}		
	}
	DEBUG(4,(" session setup ok\n"));

	if (!cli_send_tconX(c, sharename, "?????",
			    password, strlen(password)+1)) {
		d_printf("tree connect failed: %s\n", cli_errstr(c));
		cli_shutdown(c);
		return NULL;
	}

	DEBUG(4,(" tconx ok\n"));

	return c;
}
Beispiel #17
0
NTSTATUS remote_password_change(const char *remote_machine, const char *user_name, 
				const char *old_passwd, const char *new_passwd,
				char **err_str)
{
	struct nmb_name calling, called;
	struct cli_state *cli;
	struct rpc_pipe_client *pipe_hnd;
	struct sockaddr_storage ss;

	NTSTATUS result;
	bool pass_must_change = False;

	*err_str = NULL;

	if(!resolve_name( remote_machine, &ss, 0x20)) {
		asprintf(err_str, "Unable to find an IP address for machine "
			 "%s.\n", remote_machine);
		return NT_STATUS_UNSUCCESSFUL;
	}
 
	cli = cli_initialise();
	if (!cli) {
		return NT_STATUS_NO_MEMORY;
	}

	result = cli_connect(cli, remote_machine, &ss);
	if (!NT_STATUS_IS_OK(result)) {
		asprintf(err_str, "Unable to connect to SMB server on "
			 "machine %s. Error was : %s.\n",
			 remote_machine, nt_errstr(result));
		cli_shutdown(cli);
		return result;
	}
  
	make_nmb_name(&calling, global_myname() , 0x0);
	make_nmb_name(&called , remote_machine, 0x20);
	
	if (!cli_session_request(cli, &calling, &called)) {
		asprintf(err_str, "machine %s rejected the session setup. "
			 "Error was : %s.\n",
			 remote_machine, cli_errstr(cli) );
		result = cli_nt_error(cli);
		cli_shutdown(cli);
		return result;
	}
  
	cli->protocol = PROTOCOL_NT1;

	if (!cli_negprot(cli)) {
		asprintf(err_str, "machine %s rejected the negotiate "
			 "protocol. Error was : %s.\n",        
			 remote_machine, cli_errstr(cli) );
		result = cli_nt_error(cli);
		cli_shutdown(cli);
		return result;
	}
  
	/* Given things like SMB signing, restrict anonymous and the like, 
	   try an authenticated connection first */
	result = cli_session_setup(cli, user_name,
				   old_passwd, strlen(old_passwd)+1,
				   old_passwd, strlen(old_passwd)+1, "");

	if (!NT_STATUS_IS_OK(result)) {

		/* Password must change or Password expired are the only valid
		 * error conditions here from where we can proceed, the rest like
		 * account locked out or logon failure will lead to errors later
		 * anyway */

		if (!NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_MUST_CHANGE) &&
		    !NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_EXPIRED)) {
			asprintf(err_str, "Could not connect to machine %s: "
				 "%s\n", remote_machine, cli_errstr(cli));
			cli_shutdown(cli);
			return result;
		}

		pass_must_change = True;

		/*
		 * We should connect as the anonymous user here, in case
		 * the server has "must change password" checked...
		 * Thanks to <*****@*****.**> for this fix.
		 */

		result = cli_session_setup(cli, "", "", 0, "", 0, "");

		if (!NT_STATUS_IS_OK(result)) {
			asprintf(err_str, "machine %s rejected the session "
				 "setup. Error was : %s.\n",        
				 remote_machine, cli_errstr(cli) );
			cli_shutdown(cli);
			return result;
		}

		cli_init_creds(cli, "", "", NULL);
	} else {
		cli_init_creds(cli, user_name, "", old_passwd);
	}

	if (!cli_send_tconX(cli, "IPC$", "IPC", "", 1)) {
		asprintf(err_str, "machine %s rejected the tconX on the IPC$ "
			 "share. Error was : %s.\n",
			 remote_machine, cli_errstr(cli) );
		result = cli_nt_error(cli);
		cli_shutdown(cli);
		return result;
	}

	/* Try not to give the password away too easily */

	if (!pass_must_change) {
		pipe_hnd = cli_rpc_pipe_open_ntlmssp(cli,
						PI_SAMR,
						PIPE_AUTH_LEVEL_PRIVACY,
						"", /* what domain... ? */
						user_name,
						old_passwd,
						&result);
	} else {
		/*
		 * If the user password must be changed the ntlmssp bind will
		 * fail the same way as the session setup above did. The
		 * difference ist that with a pipe bind we don't get a good
		 * error message, the result will be that the rpc call below
		 * will just fail. So we do it anonymously, there's no other
		 * way.
		 */
		pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &result);
	}

	if (!pipe_hnd) {
		if (lp_client_lanman_auth()) {
			/* Use the old RAP method. */
			if (!cli_oem_change_password(cli, user_name, new_passwd, old_passwd)) {
				asprintf(err_str, "machine %s rejected the "
					 "password change: Error was : %s.\n",
					 remote_machine, cli_errstr(cli) );
				result = cli_nt_error(cli);
				cli_shutdown(cli);
				return result;
			}
		} else {
			asprintf(err_str, "SAMR connection to machine %s "
				 "failed. Error was %s, but LANMAN password "
				 "changed are disabled\n",
				 nt_errstr(result), remote_machine);
			result = cli_nt_error(cli);
			cli_shutdown(cli);
			return result;
		}
	}

	if (NT_STATUS_IS_OK(result = rpccli_samr_chgpasswd_user(pipe_hnd, pipe_hnd->mem_ctx, user_name, 
							     new_passwd, old_passwd))) {
		/* Great - it all worked! */
		cli_shutdown(cli);
		return NT_STATUS_OK;

	} else if (!(NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) 
		     || NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL))) {
		/* it failed, but for reasons such as wrong password, too short etc ... */
		
		asprintf(err_str, "machine %s rejected the password change: "
			 "Error was : %s.\n",
			 remote_machine, get_friendly_nt_error_msg(result));
		cli_shutdown(cli);
		return result;
	}

	/* OK, that failed, so try again... */
	cli_rpc_pipe_close(pipe_hnd);
	
	/* Try anonymous NTLMSSP... */
	cli_init_creds(cli, "", "", NULL);
	
	result = NT_STATUS_UNSUCCESSFUL;
	
	/* OK, this is ugly, but... try an anonymous pipe. */
	pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &result);

	if ( pipe_hnd &&
		(NT_STATUS_IS_OK(result = rpccli_samr_chgpasswd_user(pipe_hnd,
						pipe_hnd->mem_ctx,
						user_name, 
						new_passwd,
						old_passwd)))) {
		/* Great - it all worked! */
		cli_shutdown(cli);
		return NT_STATUS_OK;
	} else {
		if (!(NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) 
		      || NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL))) {
			/* it failed, but again it was due to things like new password too short */

			asprintf(err_str, "machine %s rejected the "
				 "(anonymous) password change: Error was : "
				 "%s.\n", remote_machine,
				 get_friendly_nt_error_msg(result));
			cli_shutdown(cli);
			return result;
		}
		
		/* We have failed to change the user's password, and we think the server
		   just might not support SAMR password changes, so fall back */
		
		if (lp_client_lanman_auth()) {
			/* Use the old RAP method. */
			if (cli_oem_change_password(cli, user_name, new_passwd, old_passwd)) {
				/* SAMR failed, but the old LanMan protocol worked! */

				cli_shutdown(cli);
				return NT_STATUS_OK;
			}
			asprintf(err_str, "machine %s rejected the password "
				 "change: Error was : %s.\n",
				 remote_machine, cli_errstr(cli) );
			result = cli_nt_error(cli);
			cli_shutdown(cli);
			return result;
		} else {
			asprintf(err_str, "SAMR connection to machine %s "
				 "failed. Error was %s, but LANMAN password "
				 "changed are disabled\n",
				nt_errstr(result), remote_machine);
			cli_shutdown(cli);
			return NT_STATUS_UNSUCCESSFUL;
		}
	}
}
Beispiel #18
0
static struct cli_state *do_connect( const char *server, const char *share,
                                     BOOL show_sessetup )
{
	struct cli_state *c = NULL;
	struct nmb_name called, calling;
	const char *server_n;
	struct in_addr ip;
	pstring servicename;
	char *sharename;
	fstring newserver, newshare;
	NTSTATUS status;
	
	/* make a copy so we don't modify the global string 'service' */
	pstrcpy(servicename, share);
	sharename = servicename;
	if (*sharename == '\\') {
		server = sharename+2;
		sharename = strchr_m(server,'\\');
		if (!sharename) return NULL;
		*sharename = 0;
		sharename++;
	}

	server_n = server;
	
	zero_ip(&ip);

	make_nmb_name(&calling, global_myname(), 0x0);
	make_nmb_name(&called , server, name_type);

 again:
	zero_ip(&ip);
	if (have_ip) 
		ip = dest_ip;

	/* have to open a new connection */
	if (!(c=cli_initialise()) || (cli_set_port(c, port) != port)) {
		d_printf("Connection to %s failed\n", server_n);
		return NULL;
	}
	status = cli_connect(c, server_n, &ip);
	if (!NT_STATUS_IS_OK(status)) {
		d_printf("Connection to %s failed (Error %s)\n", server_n, nt_errstr(status));
		return NULL;
	}

	c->protocol = max_protocol;
	c->use_kerberos = use_kerberos;
	cli_setup_signing_state(c, signing_state);
		

	if (!cli_session_request(c, &calling, &called, NULL)) {
		char *p;
		d_printf("session request to %s failed (%s)\n", 
			 called.name, cli_errstr(c));
		cli_shutdown(c);
		c = NULL;
		if ((p=strchr_m(called.name, '.'))) {
			*p = 0;
			goto again;
		}
		if (strcmp(called.name, "*SMBSERVER")) {
			make_nmb_name(&called , "*SMBSERVER", 0x20);
			goto again;
		}
		return NULL;
	}

	DEBUG(4,(" session request ok\n"));

	if (!cli_negprot(c)) {
		d_printf("protocol negotiation failed\n");
		cli_shutdown(c);
		return NULL;
	}

	if (!got_pass) {
		char *pass = getpass("Password: "******"", "", 0, "", 0,
						       lp_workgroup()))) { 
			d_printf("session setup failed: %s\n", cli_errstr(c));
			if (NT_STATUS_V(cli_nt_error(c)) == 
			    NT_STATUS_V(NT_STATUS_MORE_PROCESSING_REQUIRED))
				d_printf("did you forget to run kinit?\n");
			cli_shutdown(c);
			return NULL;
		}
		d_printf("Anonymous login successful\n");
	}

	if ( show_sessetup ) {
		if (*c->server_domain) {
			DEBUG(0,("Domain=[%s] OS=[%s] Server=[%s]\n",
				c->server_domain,c->server_os,c->server_type));
		} else if (*c->server_os || *c->server_type){
			DEBUG(0,("OS=[%s] Server=[%s]\n",
				 c->server_os,c->server_type));
		}		
	}
	DEBUG(4,(" session setup ok\n"));

	/* here's the fun part....to support 'msdfs proxy' shares
	   (on Samba or windows) we have to issues a TRANS_GET_DFS_REFERRAL 
	   here before trying to connect to the original share.
	   check_dfs_proxy() will fail if it is a normal share. */

	if ( (c->capabilities & CAP_DFS) && cli_check_msdfs_proxy( c, sharename, newserver, newshare ) ) {
		cli_shutdown(c);
		return do_connect( newserver, newshare, False );
	}

	/* must be a normal share */

	if (!cli_send_tconX(c, sharename, "?????", password, strlen(password)+1)) {
		d_printf("tree connect failed: %s\n", cli_errstr(c));
		cli_shutdown(c);
		return NULL;
	}

	DEBUG(4,(" tconx ok\n"));

	return c;
}
Beispiel #19
0
bool cli_receive_trans(struct cli_state *cli,int trans,
                              char **param, unsigned int *param_len,
                              char **data, unsigned int *data_len)
{
	unsigned int total_data=0;
	unsigned int total_param=0;
	unsigned int this_data,this_param;
	NTSTATUS status;
	bool ret = False;
	uint16_t mid;

	*data_len = *param_len = 0;

	mid = SVAL(cli->outbuf,smb_mid);

	if (!cli_receive_smb(cli)) {
		cli_state_seqnum_remove(cli, mid);
		return False;
	}

	show_msg(cli->inbuf);

	/* sanity check */
	if (CVAL(cli->inbuf,smb_com) != trans) {
		DEBUG(0,("Expected %s response, got command 0x%02x\n",
			 trans==SMBtrans?"SMBtrans":"SMBtrans2",
			 CVAL(cli->inbuf,smb_com)));
		cli_state_seqnum_remove(cli, mid);
		return False;
	}

	/*
	 * An NT RPC pipe call can return ERRDOS, ERRmoredata
	 * to a trans call. This is not an error and should not
	 * be treated as such. Note that STATUS_NO_MORE_FILES is
	 * returned when a trans2 findfirst/next finishes.
	 * When setting up an encrypted transport we can also
	 * see NT_STATUS_MORE_PROCESSING_REQUIRED here.
         *
         * Vista returns NT_STATUS_INACCESSIBLE_SYSTEM_SHORTCUT if the folder
         * "<share>/Users/All Users" is enumerated.  This is a special pseudo
         * folder, and the response does not have parameters (nor a parameter
         * length).
	 */
	status = cli_nt_error(cli);

	if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
		if (NT_STATUS_IS_ERR(status) ||
                    NT_STATUS_EQUAL(status,STATUS_NO_MORE_FILES) ||
                    NT_STATUS_EQUAL(status,NT_STATUS_INACCESSIBLE_SYSTEM_SHORTCUT)) {
			goto out;
		}
	}

	/* parse out the lengths */
	total_data = SVAL(cli->inbuf,smb_tdrcnt);
	total_param = SVAL(cli->inbuf,smb_tprcnt);

	/* allocate it */
	if (total_data!=0) {
		/* We know adding 2 is safe as total_data is an
		 * SVAL <= 0xFFFF. */
		*data = (char *)SMB_REALLOC(*data,total_data+2);
		if (!(*data)) {
			DEBUG(0,("cli_receive_trans: failed to enlarge data buffer\n"));
			goto out;
		}
	}

	if (total_param!=0) {
		/* We know adding 2 is safe as total_param is an
		 * SVAL <= 0xFFFF. */
		*param = (char *)SMB_REALLOC(*param,total_param+2);
		if (!(*param)) {
			DEBUG(0,("cli_receive_trans: failed to enlarge param buffer\n"));
			goto out;
		}
	}

	for (;;)  {
		this_data = SVAL(cli->inbuf,smb_drcnt);
		this_param = SVAL(cli->inbuf,smb_prcnt);

		if (this_data + *data_len > total_data ||
		    this_param + *param_len > total_param) {
			DEBUG(1,("Data overflow in cli_receive_trans\n"));
			goto out;
		}

		if (this_data + *data_len < this_data ||
				this_data + *data_len < *data_len ||
				this_param + *param_len < this_param ||
				this_param + *param_len < *param_len) {
			DEBUG(1,("Data overflow in cli_receive_trans\n"));
			goto out;
		}

		if (this_data) {
			unsigned int data_offset_out = SVAL(cli->inbuf,smb_drdisp);
			unsigned int data_offset_in = SVAL(cli->inbuf,smb_droff);

			if (data_offset_out > total_data ||
					data_offset_out + this_data > total_data ||
					data_offset_out + this_data < data_offset_out ||
					data_offset_out + this_data < this_data) {
				DEBUG(1,("Data overflow in cli_receive_trans\n"));
				goto out;
			}
			if (data_offset_in > cli->bufsize ||
					data_offset_in + this_data >  cli->bufsize ||
					data_offset_in + this_data < data_offset_in ||
					data_offset_in + this_data < this_data) {
				DEBUG(1,("Data overflow in cli_receive_trans\n"));
				goto out;
			}

			memcpy(*data + data_offset_out, smb_base(cli->inbuf) + data_offset_in, this_data);
		}
		if (this_param) {
			unsigned int param_offset_out = SVAL(cli->inbuf,smb_prdisp);
			unsigned int param_offset_in = SVAL(cli->inbuf,smb_proff);

			if (param_offset_out > total_param ||
					param_offset_out + this_param > total_param ||
					param_offset_out + this_param < param_offset_out ||
					param_offset_out + this_param < this_param) {
				DEBUG(1,("Param overflow in cli_receive_trans\n"));
				goto out;
			}
			if (param_offset_in > cli->bufsize ||
					param_offset_in + this_param >  cli->bufsize ||
					param_offset_in + this_param < param_offset_in ||
					param_offset_in + this_param < this_param) {
				DEBUG(1,("Param overflow in cli_receive_trans\n"));
				goto out;
			}

			memcpy(*param + param_offset_out, smb_base(cli->inbuf) + param_offset_in, this_param);
		}
		*data_len += this_data;
		*param_len += this_param;

		if (total_data <= *data_len && total_param <= *param_len) {
			ret = True;
			break;
		}

		if (!cli_receive_smb(cli)) {
			goto out;
		}

		show_msg(cli->inbuf);

		/* sanity check */
		if (CVAL(cli->inbuf,smb_com) != trans) {
			DEBUG(0,("Expected %s response, got command 0x%02x\n",
				 trans==SMBtrans?"SMBtrans":"SMBtrans2", 
				 CVAL(cli->inbuf,smb_com)));
			goto out;
		}
		if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
			if (NT_STATUS_IS_ERR(cli_nt_error(cli))) {
				goto out;
			}
		}

		/* parse out the total lengths again - they can shrink! */
		if (SVAL(cli->inbuf,smb_tdrcnt) < total_data)
			total_data = SVAL(cli->inbuf,smb_tdrcnt);
		if (SVAL(cli->inbuf,smb_tprcnt) < total_param)
			total_param = SVAL(cli->inbuf,smb_tprcnt);

		if (total_data <= *data_len && total_param <= *param_len) {
			ret = True;
			break;
		}
	}

  out:

	cli_state_seqnum_remove(cli, mid);

	if (ret) {
		/* Ensure the last 2 bytes of param and data are 2 null
		 * bytes. These are malloc'ed, but not included in any
		 * length counts. This allows cli_XX string reading functions
		 * to safely null terminate. */
		if (total_data) {
			SSVAL(*data,total_data,0);
		}
		if (total_param) {
			SSVAL(*param,total_param,0);
		}
	}

	return ret;
}
Beispiel #20
0
static struct cli_state 
*smb_complete_connection(const char *myname,
            const char *server,
            int port,
            const char *username, 
            const char *password, 
            const char *workgroup, 
            const char *share,
            int flags)
{
  struct cli_state  *cli;    /* New connection */    
  NTSTATUS nt_status;
  
  /* Start the SMB connection */
  nt_status = cli_start_connection( &cli, myname, server, NULL, port, 
                                    Undefined, flags, NULL);
  if (!NT_STATUS_IS_OK(nt_status)) 
  {
    return NULL;      
  }
    
  /* We pretty much guarentee password must be valid or a pointer
     to a 0 char. */
  if (!password) {
    return NULL;
  }
  
  if ( (username) && (*username) && 
      (strlen(password) == 0 ) && 
       (cli->use_kerberos) ) 
  {
    /* Use kerberos authentication */
    struct passwd *pw;
    char *cache_file;
    
    
    if ( !(pw = sys_getpwnam(username)) ) {
      fprintf(stderr,"ERROR Can not get %s uid\n", username);
      cli_shutdown(cli);
      return NULL;
    }

    /*
     * Get the ticket cache of the user to set KRB5CCNAME env
     * variable
     */
    cache_file = get_ticket_cache( pw->pw_uid );
    if ( cache_file == NULL ) 
    {
      fprintf(stderr, "ERROR: Can not get the ticket cache for %s\n", username);
      cli_shutdown(cli);
      return NULL;
    }

    if ( setenv(KRB5CCNAME, cache_file, OVERWRITE) < 0 ) 
    {
      fprintf(stderr, "ERROR: Can not add KRB5CCNAME to the environment");
      cli_shutdown(cli);
      free(cache_file);
      return NULL;
    }
    free(cache_file);

    /*
     * Change the UID of the process to be able to read the kerberos
     * ticket cache
     */
    setuid(pw->pw_uid);

  }
   
   
  if (!NT_STATUS_IS_OK(cli_session_setup(cli, username,
					 password, strlen(password)+1, 
					 password, strlen(password)+1,
					 workgroup)))
  {
    fprintf(stderr,"ERROR: Session setup failed: %s\n", cli_errstr(cli));
    if (NT_STATUS_V(cli_nt_error(cli)) == 
        NT_STATUS_V(NT_STATUS_MORE_PROCESSING_REQUIRED))
    {
      fprintf(stderr, "did you forget to run kinit?\n");
    }
    cli_shutdown(cli);

    return NULL;
  }
    
  if (!cli_send_tconX(cli, share, "?????", password, strlen(password)+1)) 
  {
    fprintf(stderr, "ERROR: Tree connect failed (%s)\n", cli_errstr(cli));
    cli_shutdown(cli);
    return NULL;
  }
    
  return cli;
}
Beispiel #21
0
static BOOL test_one(struct cli_state *cli[NSERVERS][NCONNECTIONS], 
		     int fnum[NSERVERS][NCONNECTIONS][NFILES],
		     struct record *rec)
{
	unsigned conn = rec->conn;
	unsigned f = rec->f;
	SMB_BIG_UINT start = rec->start;
	SMB_BIG_UINT len = rec->len;
	enum brl_type op = rec->lock_type;
	int server;
	BOOL ret[NSERVERS];
	NTSTATUS status[NSERVERS];

	switch (rec->lock_op) {
	case OP_LOCK:
		/* set a lock */
		for (server=0;server<NSERVERS;server++) {
			ret[server] = cli_lock64(cli[server][conn], 
						 fnum[server][conn][f],
						 start, len, LOCK_TIMEOUT, op);
			status[server] = cli_nt_error(cli[server][conn]);
			if (!exact_error_codes && 
			    NT_STATUS_EQUAL(status[server], 
					    NT_STATUS_FILE_LOCK_CONFLICT)) {
				status[server] = NT_STATUS_LOCK_NOT_GRANTED;
			}
		}
		if (showall || !NT_STATUS_EQUAL(status[0],status[1])) {
			printf("lock   conn=%u f=%u range=%.0f(%.0f) op=%s -> %s:%s\n",
			       conn, f, 
			       (double)start, (double)len,
			       op==READ_LOCK?"READ_LOCK":"WRITE_LOCK",
			       nt_errstr(status[0]), nt_errstr(status[1]));
		}
		if (showall || !NT_STATUS_EQUAL(status[0],status[1])) show_locks();
		if (!NT_STATUS_EQUAL(status[0],status[1])) return False;
		break;
		
	case OP_UNLOCK:
		/* unset a lock */
		for (server=0;server<NSERVERS;server++) {
			ret[server] = cli_unlock64(cli[server][conn], 
						   fnum[server][conn][f],
						   start, len);
			status[server] = cli_nt_error(cli[server][conn]);
		}
		if (showall || 
		    (!hide_unlock_fails && !NT_STATUS_EQUAL(status[0],status[1]))) {
			printf("unlock conn=%u f=%u range=%.0f(%.0f)       -> %s:%s\n",
			       conn, f, 
			       (double)start, (double)len,
			       nt_errstr(status[0]), nt_errstr(status[1]));
		}
		if (showall || !NT_STATUS_EQUAL(status[0],status[1])) show_locks();
		if (!hide_unlock_fails && !NT_STATUS_EQUAL(status[0],status[1])) 
			return False;
		break;

	case OP_REOPEN:
		/* reopen the file */
		for (server=0;server<NSERVERS;server++) {
			cli_close(cli[server][conn], fnum[server][conn][f]);
			fnum[server][conn][f] = -1;
		}
		for (server=0;server<NSERVERS;server++) {
			fnum[server][conn][f] = cli_open(cli[server][conn], FILENAME,
							 O_RDWR|O_CREAT,
							 DENY_NONE);
			if (fnum[server][conn][f] == -1) {
				printf("failed to reopen on share%d\n", server);
				return False;
			}
		}
		if (showall) {
			printf("reopen conn=%u f=%u\n",
			       conn, f);
			show_locks();
		}
		break;
	}

	return True;
}