mirror of
https://github.com/samba-team/samba.git
synced 2025-08-04 08:22:08 +03:00
A rewrite of the error handling in the libsmb client code. I've separated
out the error handling into a bunch of separate functions rather than all being handled in one big function. Fetch error codes from the last received packet: void cli_dos_error(struct cli_state *cli, uint8 *eclass, uint32 *num); uint32 cli_nt_error(struct cli_state *); Convert errors to UNIX errno values: int cli_errno_from_dos(uint8 eclass, uint32 num); int cli_errno_from_nt(uint32 status); int cli_errno(struct cli_state *cli); Detect different kinds of errors: BOOL cli_is_dos_error(struct cli_state *cli); BOOL cli_is_nt_error(struct cli_state *cli); BOOL cli_is_error(struct cli_state *cli); This also means we now support CAP_STATUS32 as we can decode and understand NT errors instead of just DOS errors. Yay! Ported a whole bunch of files in libsmb to use this new API instead of the just the DOS error.
This commit is contained in:
@ -143,6 +143,15 @@ BOOL cli_session_setup(struct cli_state *cli,
|
|||||||
uint32 capabilities;
|
uint32 capabilities;
|
||||||
|
|
||||||
capabilities = CAP_NT_SMBS;
|
capabilities = CAP_NT_SMBS;
|
||||||
|
|
||||||
|
/* Set the CLI_FORCE_DOSERR environment variable to test
|
||||||
|
client routines using DOS errors instead of STATUS32
|
||||||
|
ones. This intended only as a temporary hack. */
|
||||||
|
|
||||||
|
if (!getenv("CLI_FORCE_DOSERR")) {
|
||||||
|
capabilities |= CAP_STATUS32;
|
||||||
|
}
|
||||||
|
|
||||||
if (cli->use_level_II_oplocks) {
|
if (cli->use_level_II_oplocks) {
|
||||||
capabilities |= CAP_LEVEL_II_OPLOCKS;
|
capabilities |= CAP_LEVEL_II_OPLOCKS;
|
||||||
}
|
}
|
||||||
|
@ -104,7 +104,6 @@ setup basics in a outgoing packet
|
|||||||
void cli_setup_packet(struct cli_state *cli)
|
void cli_setup_packet(struct cli_state *cli)
|
||||||
{
|
{
|
||||||
cli->rap_error = 0;
|
cli->rap_error = 0;
|
||||||
cli->nt_error = 0;
|
|
||||||
SSVAL(cli->outbuf,smb_pid,cli->pid);
|
SSVAL(cli->outbuf,smb_pid,cli->pid);
|
||||||
SSVAL(cli->outbuf,smb_uid,cli->vuid);
|
SSVAL(cli->outbuf,smb_uid,cli->vuid);
|
||||||
SSVAL(cli->outbuf,smb_mid,cli->mid);
|
SSVAL(cli->outbuf,smb_mid,cli->mid);
|
||||||
|
@ -23,10 +23,8 @@
|
|||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
|
|
||||||
|
|
||||||
extern int DEBUGLEVEL;
|
extern int DEBUGLEVEL;
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************
|
/*****************************************************
|
||||||
RAP error codes - a small start but will be extended.
|
RAP error codes - a small start but will be extended.
|
||||||
*******************************************************/
|
*******************************************************/
|
||||||
@ -63,134 +61,119 @@ static char *cli_smb_errstr(struct cli_state *cli)
|
|||||||
return smb_errstr(cli->inbuf);
|
return smb_errstr(cli->inbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************
|
/***************************************************************************
|
||||||
Return an error message - either an SMB error or a RAP
|
Return an error message - either an NT error, SMB error or a RAP error.
|
||||||
error.
|
Note some of the NT errors are actually warnings or "informational" errors
|
||||||
*******************************************************/
|
in which case they can be safely ignored.
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
char *cli_errstr(struct cli_state *cli)
|
char *cli_errstr(struct cli_state *cli)
|
||||||
{
|
{
|
||||||
static fstring error_message;
|
static fstring error_message;
|
||||||
uint8 errclass;
|
uint32 flgs2 = SVAL(cli->inbuf,smb_flg2), errnum;
|
||||||
uint32 errnum;
|
uint8 errclass;
|
||||||
uint32 nt_rpc_error;
|
int i;
|
||||||
int i;
|
|
||||||
|
|
||||||
/*
|
/* Case #1: 32-bit NT errors */
|
||||||
* Errors are of three kinds - smb errors,
|
|
||||||
* dealt with by cli_smb_errstr, NT errors,
|
|
||||||
* whose code is in cli.nt_error, and rap
|
|
||||||
* errors, whose error code is in cli.rap_error.
|
|
||||||
*/
|
|
||||||
|
|
||||||
cli_error(cli, &errclass, &errnum, &nt_rpc_error);
|
if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) {
|
||||||
|
uint32 status = IVAL(cli->inbuf,smb_rcls);
|
||||||
|
|
||||||
if (errclass != 0)
|
return get_nt_error_msg(status);
|
||||||
{
|
}
|
||||||
return cli_smb_errstr(cli);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
cli_dos_error(cli, &errclass, &errnum);
|
||||||
* Was it an NT error ?
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (nt_rpc_error)
|
/* Case #2: SMB error */
|
||||||
{
|
|
||||||
char *nt_msg = (char *)get_nt_error_msg(nt_rpc_error);
|
|
||||||
|
|
||||||
if (nt_msg == NULL)
|
if (errclass != 0)
|
||||||
{
|
return cli_smb_errstr(cli);
|
||||||
slprintf(error_message, sizeof(fstring) - 1, "NT code %d", nt_rpc_error);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fstrcpy(error_message, nt_msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
return error_message;
|
/* Case #3: RAP error */
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
for (i = 0; rap_errmap[i].message != NULL; i++) {
|
||||||
* Must have been a rap error.
|
if (rap_errmap[i].err == cli->rap_error) {
|
||||||
*/
|
return rap_errmap[i].message;
|
||||||
|
|
||||||
slprintf(error_message, sizeof(error_message) - 1, "code %d", cli->rap_error);
|
|
||||||
|
|
||||||
for (i = 0; rap_errmap[i].message != NULL; i++)
|
|
||||||
{
|
|
||||||
if (rap_errmap[i].err == cli->rap_error)
|
|
||||||
{
|
|
||||||
fstrcpy(error_message, rap_errmap[i].message);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
slprintf(error_message, sizeof(error_message) - 1, "code %d",
|
||||||
|
cli->rap_error);
|
||||||
|
|
||||||
return error_message;
|
return error_message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return the 32-bit NT status code from the last packet */
|
||||||
|
|
||||||
/****************************************************************************
|
uint32 cli_nt_error(struct cli_state *cli)
|
||||||
return error codes for the last packet
|
{
|
||||||
returns 0 if there was no error and the best approx of a unix errno
|
int flgs2 = SVAL(cli->inbuf,smb_flg2);
|
||||||
otherwise
|
|
||||||
|
|
||||||
for 32 bit "warnings", a return code of 0 is expected.
|
if (!(flgs2 & FLAGS2_32_BIT_ERROR_CODES)) {
|
||||||
|
|
||||||
****************************************************************************/
|
/* Eek! We've requested a NT error when the packet that
|
||||||
int cli_error(struct cli_state *cli, uint8 *eclass, uint32 *num, uint32 *nt_rpc_error)
|
came back does not contain one. What do we return
|
||||||
|
here? */
|
||||||
|
|
||||||
|
DEBUG(1, ("ERROR: cli_error() called to read a status code "
|
||||||
|
"from a packet that does not contain one!\n"));
|
||||||
|
|
||||||
|
return NT_STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return IVAL(cli->inbuf,smb_rcls);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the DOS error from the last packet - an error class and an error
|
||||||
|
code. */
|
||||||
|
|
||||||
|
void cli_dos_error(struct cli_state *cli, uint8 *eclass, uint32 *num)
|
||||||
{
|
{
|
||||||
int flgs2;
|
int flgs2;
|
||||||
char rcls;
|
char rcls;
|
||||||
int code;
|
int code;
|
||||||
|
|
||||||
if (eclass) *eclass = 0;
|
if (eclass)
|
||||||
if (num ) *num = 0;
|
*eclass = 0;
|
||||||
if (nt_rpc_error) *nt_rpc_error = 0;
|
|
||||||
|
if (num)
|
||||||
|
*num = 0;
|
||||||
|
|
||||||
if(!cli->initialised)
|
if(!cli->initialised)
|
||||||
return EINVAL;
|
return;
|
||||||
|
|
||||||
if(!cli->inbuf)
|
if(!cli->inbuf)
|
||||||
return ENOMEM;
|
return;
|
||||||
|
|
||||||
flgs2 = SVAL(cli->inbuf,smb_flg2);
|
flgs2 = SVAL(cli->inbuf,smb_flg2);
|
||||||
if (nt_rpc_error) *nt_rpc_error = cli->nt_error;
|
|
||||||
|
|
||||||
if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) {
|
if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) {
|
||||||
/* 32 bit error codes detected */
|
/* Eek! We've requested a DOS error when the packet that
|
||||||
uint32 nt_err = IVAL(cli->inbuf,smb_rcls);
|
came back does not contain one. What do we return
|
||||||
if (num) *num = nt_err;
|
here? */
|
||||||
DEBUG(10,("cli_error: 32 bit codes: code=%08x\n", nt_err));
|
|
||||||
if (!(nt_err & 0xc0000000))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
switch (nt_err) {
|
DEBUG(1, ("ERROR: cli_error() called to read a dos error code "
|
||||||
case NT_STATUS_ACCESS_VIOLATION: return EACCES;
|
"from a packet that does not contain one!\n"));
|
||||||
case NT_STATUS_NO_SUCH_FILE: return ENOENT;
|
|
||||||
case NT_STATUS_NO_SUCH_DEVICE: return ENODEV;
|
|
||||||
case NT_STATUS_INVALID_HANDLE: return EBADF;
|
|
||||||
case NT_STATUS_NO_MEMORY: return ENOMEM;
|
|
||||||
case NT_STATUS_ACCESS_DENIED: return EACCES;
|
|
||||||
case NT_STATUS_OBJECT_NAME_NOT_FOUND: return ENOENT;
|
|
||||||
case NT_STATUS_SHARING_VIOLATION: return EBUSY;
|
|
||||||
case NT_STATUS_OBJECT_PATH_INVALID: return ENOTDIR;
|
|
||||||
case NT_STATUS_OBJECT_NAME_COLLISION: return EEXIST;
|
|
||||||
case NT_STATUS_PATH_NOT_COVERED: return ENOENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* for all other cases - a default code */
|
return;
|
||||||
return EINVAL;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
rcls = CVAL(cli->inbuf,smb_rcls);
|
rcls = CVAL(cli->inbuf,smb_rcls);
|
||||||
code = SVAL(cli->inbuf,smb_err);
|
code = SVAL(cli->inbuf,smb_err);
|
||||||
if (rcls == 0) return 0;
|
|
||||||
|
if (rcls == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
if (eclass) *eclass = rcls;
|
if (eclass) *eclass = rcls;
|
||||||
if (num ) *num = code;
|
if (num ) *num = code;
|
||||||
|
}
|
||||||
|
|
||||||
if (rcls == ERRDOS) {
|
/* Return a UNIX errno from a dos error class, error number tuple */
|
||||||
switch (code) {
|
|
||||||
|
int cli_errno_from_dos(uint8 eclass, uint32 num)
|
||||||
|
{
|
||||||
|
if (eclass == ERRDOS) {
|
||||||
|
switch (num) {
|
||||||
case ERRbadfile: return ENOENT;
|
case ERRbadfile: return ENOENT;
|
||||||
case ERRbadpath: return ENOTDIR;
|
case ERRbadpath: return ENOTDIR;
|
||||||
case ERRnoaccess: return EACCES;
|
case ERRnoaccess: return EACCES;
|
||||||
@ -198,12 +181,13 @@ int cli_error(struct cli_state *cli, uint8 *eclass, uint32 *num, uint32 *nt_rpc_
|
|||||||
case ERRrename: return EEXIST;
|
case ERRrename: return EEXIST;
|
||||||
case ERRbadshare: return EBUSY;
|
case ERRbadshare: return EBUSY;
|
||||||
case ERRlock: return EBUSY;
|
case ERRlock: return EBUSY;
|
||||||
case ERROR_INVALID_NAME: return ENOENT;
|
case ERRinvalidname: return ENOENT;
|
||||||
case ERRnosuchshare: return ENODEV;
|
case ERRnosuchshare: return ENODEV;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rcls == ERRSRV) {
|
|
||||||
switch (code) {
|
if (eclass == ERRSRV) {
|
||||||
|
switch (num) {
|
||||||
case ERRbadpw: return EPERM;
|
case ERRbadpw: return EPERM;
|
||||||
case ERRaccess: return EACCES;
|
case ERRaccess: return EACCES;
|
||||||
case ERRnoresource: return ENOMEM;
|
case ERRnoresource: return ENOMEM;
|
||||||
@ -211,7 +195,88 @@ int cli_error(struct cli_state *cli, uint8 *eclass, uint32 *num, uint32 *nt_rpc_
|
|||||||
case ERRinvnetname: return ENODEV;
|
case ERRinvnetname: return ENODEV;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* for other cases */
|
/* for other cases */
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return a UNIX errno from a NT status code */
|
||||||
|
|
||||||
|
int cli_errno_from_nt(uint32 status)
|
||||||
|
{
|
||||||
|
DEBUG(10,("cli_errno_from_nt: 32 bit codes: code=%08x\n", status));
|
||||||
|
|
||||||
|
/* Status codes without this bit set are not errors */
|
||||||
|
|
||||||
|
if (!(status & 0xc0000000))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch (status) {
|
||||||
|
case NT_STATUS_ACCESS_VIOLATION: return EACCES;
|
||||||
|
case NT_STATUS_NO_SUCH_FILE: return ENOENT;
|
||||||
|
case NT_STATUS_NO_SUCH_DEVICE: return ENODEV;
|
||||||
|
case NT_STATUS_INVALID_HANDLE: return EBADF;
|
||||||
|
case NT_STATUS_NO_MEMORY: return ENOMEM;
|
||||||
|
case NT_STATUS_ACCESS_DENIED: return EACCES;
|
||||||
|
case NT_STATUS_OBJECT_NAME_NOT_FOUND: return ENOENT;
|
||||||
|
case NT_STATUS_SHARING_VIOLATION: return EBUSY;
|
||||||
|
case NT_STATUS_OBJECT_PATH_INVALID: return ENOTDIR;
|
||||||
|
case NT_STATUS_OBJECT_NAME_COLLISION: return EEXIST;
|
||||||
|
case NT_STATUS_PATH_NOT_COVERED: return ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* for all other cases - a default code */
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return a UNIX errno appropriate for the error received in the last
|
||||||
|
packet. */
|
||||||
|
|
||||||
|
int cli_errno(struct cli_state *cli)
|
||||||
|
{
|
||||||
|
uint32 status;
|
||||||
|
|
||||||
|
if (cli_is_dos_error) {
|
||||||
|
uint8 eclass;
|
||||||
|
uint32 ecode;
|
||||||
|
|
||||||
|
cli_dos_error(cli, &eclass, &ecode);
|
||||||
|
return cli_errno_from_dos(eclass, ecode);
|
||||||
|
}
|
||||||
|
|
||||||
|
status = cli_nt_error(cli);
|
||||||
|
|
||||||
|
return cli_errno_from_nt(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return true if the last packet was in error */
|
||||||
|
|
||||||
|
BOOL cli_is_error(struct cli_state *cli)
|
||||||
|
{
|
||||||
|
uint32 flgs2 = SVAL(cli->inbuf,smb_flg2), rcls = 0;
|
||||||
|
|
||||||
|
if (flgs2 & FLAGS2_32_BIT_ERROR_CODES)
|
||||||
|
rcls = IVAL(cli->inbuf, smb_rcls);
|
||||||
|
else
|
||||||
|
rcls = CVAL(cli->inbuf, smb_rcls);
|
||||||
|
|
||||||
|
return (rcls == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return true if the last error was an NT error */
|
||||||
|
|
||||||
|
BOOL cli_is_nt_error(struct cli_state *cli)
|
||||||
|
{
|
||||||
|
uint32 flgs2 = SVAL(cli->inbuf,smb_flg2);
|
||||||
|
|
||||||
|
return cli_is_error(cli) && (flgs2 & FLAGS2_32_BIT_ERROR_CODES);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return true if the last error was a DOS error */
|
||||||
|
|
||||||
|
BOOL cli_is_dos_error(struct cli_state *cli)
|
||||||
|
{
|
||||||
|
uint32 flgs2 = SVAL(cli->inbuf,smb_flg2);
|
||||||
|
|
||||||
|
return cli_is_error(cli) && !(flgs2 & FLAGS2_32_BIT_ERROR_CODES);
|
||||||
|
}
|
||||||
|
@ -745,7 +745,7 @@ BOOL cli_chkpath(struct cli_state *cli, char *path)
|
|||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cli_error(cli, NULL, NULL, NULL)) return False;
|
if (cli_is_error(cli)) return False;
|
||||||
|
|
||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
|
@ -204,12 +204,13 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
|
|||||||
|
|
||||||
if (!cli_receive_trans(cli, SMBtrans2,
|
if (!cli_receive_trans(cli, SMBtrans2,
|
||||||
&rparam, ¶m_len,
|
&rparam, ¶m_len,
|
||||||
&rdata, &data_len)) {
|
&rdata, &data_len) &&
|
||||||
|
cli_is_dos_error(cli)) {
|
||||||
/* we need to work around a Win95 bug - sometimes
|
/* we need to work around a Win95 bug - sometimes
|
||||||
it gives ERRSRV/ERRerror temprarily */
|
it gives ERRSRV/ERRerror temprarily */
|
||||||
uint8 eclass;
|
uint8 eclass;
|
||||||
uint32 ecode;
|
uint32 ecode;
|
||||||
cli_error(cli, &eclass, &ecode, NULL);
|
cli_dos_error(cli, &eclass, &ecode);
|
||||||
if (eclass != ERRSRV || ecode != ERRerror) break;
|
if (eclass != ERRSRV || ecode != ERRerror) break;
|
||||||
msleep(100);
|
msleep(100);
|
||||||
continue;
|
continue;
|
||||||
|
@ -53,7 +53,7 @@ BOOL cli_message_start(struct cli_state *cli, char *host, char *username,
|
|||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cli_error(cli, NULL, NULL, NULL)) return False;
|
if (cli_is_error(cli)) return False;
|
||||||
|
|
||||||
*grp = SVAL(cli->inbuf,smb_vwv0);
|
*grp = SVAL(cli->inbuf,smb_vwv0);
|
||||||
|
|
||||||
@ -89,7 +89,7 @@ BOOL cli_message_text(struct cli_state *cli, char *msg, int len, int grp)
|
|||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cli_error(cli, NULL, NULL, NULL)) return False;
|
if (cli_is_error(cli)) return False;
|
||||||
|
|
||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
@ -114,7 +114,7 @@ BOOL cli_message_end(struct cli_state *cli, int grp)
|
|||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cli_error(cli, NULL, NULL, NULL)) return False;
|
if (cli_is_error(cli)) return False;
|
||||||
|
|
||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
|
@ -329,7 +329,7 @@ BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char
|
|||||||
|
|
||||||
clistr_push(cli, dos_new_password, new_password, -1, STR_TERMINATE);
|
clistr_push(cli, dos_new_password, new_password, -1, STR_TERMINATE);
|
||||||
|
|
||||||
if (!make_oem_passwd_hash(dos_new_password, old_pw_hash, False, data))
|
if (!make_oem_passwd_hash( data, dos_new_password, old_pw_hash, False))
|
||||||
return False;
|
return False;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -408,12 +408,12 @@ BOOL cli_qpathinfo(struct cli_state *cli, const char *fname,
|
|||||||
cli_receive_trans(cli, SMBtrans2,
|
cli_receive_trans(cli, SMBtrans2,
|
||||||
&rparam, ¶m_len,
|
&rparam, ¶m_len,
|
||||||
&rdata, &data_len));
|
&rdata, &data_len));
|
||||||
if (!ret) {
|
if (!ret && cli_is_dos_error(cli)) {
|
||||||
/* we need to work around a Win95 bug - sometimes
|
/* we need to work around a Win95 bug - sometimes
|
||||||
it gives ERRSRV/ERRerror temprarily */
|
it gives ERRSRV/ERRerror temprarily */
|
||||||
uint8 eclass;
|
uint8 eclass;
|
||||||
uint32 ecode;
|
uint32 ecode;
|
||||||
cli_error(cli, &eclass, &ecode, NULL);
|
cli_dos_error(cli, &eclass, &ecode);
|
||||||
if (eclass != ERRSRV || ecode != ERRerror) break;
|
if (eclass != ERRSRV || ecode != ERRerror) break;
|
||||||
msleep(100);
|
msleep(100);
|
||||||
}
|
}
|
||||||
|
@ -55,8 +55,6 @@ static BOOL cli_issue_read(struct cli_state *cli, int fnum, off_t offset,
|
|||||||
|
|
||||||
ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t size)
|
ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t size)
|
||||||
{
|
{
|
||||||
uint32 ecode;
|
|
||||||
uint8 eclass;
|
|
||||||
char *p;
|
char *p;
|
||||||
int size2;
|
int size2;
|
||||||
int readsize;
|
int readsize;
|
||||||
@ -83,15 +81,21 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_
|
|||||||
if (!cli_receive_smb(cli))
|
if (!cli_receive_smb(cli))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/*
|
/* Check for error. Make sure to check for DOS and NT
|
||||||
* Check for error. Because the client library doesn't support
|
errors. */
|
||||||
* STATUS32, we need to check for and ignore the more data error
|
|
||||||
* for pipe support.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (cli_error(cli, &eclass, &ecode, NULL) &&
|
if (cli_is_error(cli)) {
|
||||||
(eclass != ERRDOS && ecode != ERRmoredata)) {
|
uint32 status = 0;
|
||||||
return -1;
|
uint8 eclass = 0;
|
||||||
|
|
||||||
|
if (cli_is_nt_error(cli))
|
||||||
|
status = cli_nt_error(cli);
|
||||||
|
else
|
||||||
|
cli_dos_error(cli, &eclass, &status);
|
||||||
|
|
||||||
|
if ((eclass == ERRDOS && status == ERRmoredata) ||
|
||||||
|
status == STATUS_MORE_ENTRIES)
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
size2 = SVAL(cli->inbuf, smb_vwv5);
|
size2 = SVAL(cli->inbuf, smb_vwv5);
|
||||||
|
@ -169,12 +169,14 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
|
|||||||
* be treated as such.
|
* be treated as such.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (cli_error(cli, &eclass, &ecode, NULL))
|
if (cli_is_dos_error(cli))
|
||||||
{
|
{
|
||||||
if(cli->nt_pipe_fnum == 0)
|
cli_dos_error(cli, &eclass, &ecode);
|
||||||
|
|
||||||
|
if(cli->nt_pipe_fnum == 0)
|
||||||
return(False);
|
return(False);
|
||||||
|
|
||||||
if(!(eclass == ERRDOS && ecode == ERRmoredata)) {
|
if(!(eclass == ERRDOS && ecode == ERRmoredata)) {
|
||||||
if (eclass != 0 && (ecode != (0x80000000 | STATUS_BUFFER_OVERFLOW)))
|
if (eclass != 0 && (ecode != (0x80000000 | STATUS_BUFFER_OVERFLOW)))
|
||||||
return(False);
|
return(False);
|
||||||
}
|
}
|
||||||
@ -228,9 +230,10 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
|
|||||||
CVAL(cli->inbuf,smb_com)));
|
CVAL(cli->inbuf,smb_com)));
|
||||||
return(False);
|
return(False);
|
||||||
}
|
}
|
||||||
if (cli_error(cli, &eclass, &ecode, NULL))
|
if (cli_is_dos_error(cli)) {
|
||||||
{
|
cli_dos_error(cli, &eclass, &ecode);
|
||||||
if(cli->nt_pipe_fnum == 0 || !(eclass == ERRDOS && ecode == ERRmoredata))
|
if(cli->nt_pipe_fnum == 0 ||
|
||||||
|
!(eclass == ERRDOS && ecode == ERRmoredata))
|
||||||
return(False);
|
return(False);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -375,7 +378,8 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
|
|||||||
* to a trans call. This is not an error and should not
|
* to a trans call. This is not an error and should not
|
||||||
* be treated as such.
|
* be treated as such.
|
||||||
*/
|
*/
|
||||||
if (cli_error(cli, &eclass, &ecode, NULL)) {
|
if (cli_is_dos_error(cli)) {
|
||||||
|
cli_dos_error(cli, &eclass, &ecode);
|
||||||
if (cli->nt_pipe_fnum == 0 || !(eclass == ERRDOS && ecode == ERRmoredata))
|
if (cli->nt_pipe_fnum == 0 || !(eclass == ERRDOS && ecode == ERRmoredata))
|
||||||
return(False);
|
return(False);
|
||||||
}
|
}
|
||||||
@ -427,8 +431,10 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
|
|||||||
CVAL(cli->inbuf,smb_com)));
|
CVAL(cli->inbuf,smb_com)));
|
||||||
return(False);
|
return(False);
|
||||||
}
|
}
|
||||||
if (cli_error(cli, &eclass, &ecode, NULL)) {
|
if (cli_is_dos_error(cli)) {
|
||||||
if(cli->nt_pipe_fnum == 0 || !(eclass == ERRDOS && ecode == ERRmoredata))
|
cli_dos_error(cli, &eclass, &ecode);
|
||||||
|
if(cli->nt_pipe_fnum == 0 ||
|
||||||
|
!(eclass == ERRDOS && ecode == ERRmoredata))
|
||||||
return(False);
|
return(False);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -195,16 +195,27 @@ smbc_parse_path(const char *fname, char *server, char *share, char *path,
|
|||||||
|
|
||||||
int smbc_errno(struct cli_state *c)
|
int smbc_errno(struct cli_state *c)
|
||||||
{
|
{
|
||||||
uint8 eclass;
|
|
||||||
uint32 ecode;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = cli_error(c, &eclass, &ecode, NULL);
|
if (cli_is_dos_error(c)) {
|
||||||
|
uint8 eclass;
|
||||||
|
uint32 ecode;
|
||||||
|
|
||||||
|
cli_dos_error(c, &eclass, &ecode);
|
||||||
|
ret = cli_errno_from_dos(eclass, ecode);
|
||||||
|
|
||||||
|
DEBUG(3,("smbc_error %d %d (0x%x) -> %d\n",
|
||||||
|
(int)eclass, (int)ecode, (int)ecode, ret));
|
||||||
|
} else {
|
||||||
|
uint32 status;
|
||||||
|
|
||||||
|
cli_nt_error(c, &status);
|
||||||
|
ret = cli_errno_from_nt(status);
|
||||||
|
|
||||||
|
DEBUG(3,("smbc errno 0x%08x -> %d\n",
|
||||||
|
status, ret));
|
||||||
|
}
|
||||||
|
|
||||||
if (ret) {
|
|
||||||
DEBUG(3,("smbc_error %d %d (0x%x) -> %d\n",
|
|
||||||
(int)eclass, (int)ecode, (int)ecode, ret));
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1445,8 +1456,6 @@ int smbc_opendir(const char *fname)
|
|||||||
struct smbc_server *srv = NULL;
|
struct smbc_server *srv = NULL;
|
||||||
struct in_addr rem_ip;
|
struct in_addr rem_ip;
|
||||||
int slot = 0;
|
int slot = 0;
|
||||||
uint8 eclass;
|
|
||||||
uint32 ecode;
|
|
||||||
|
|
||||||
if (!smbc_initialized) {
|
if (!smbc_initialized) {
|
||||||
|
|
||||||
@ -1570,7 +1579,7 @@ int smbc_opendir(const char *fname)
|
|||||||
free(smbc_file_table[slot]);
|
free(smbc_file_table[slot]);
|
||||||
}
|
}
|
||||||
smbc_file_table[slot] = NULL;
|
smbc_file_table[slot] = NULL;
|
||||||
errno = cli_error(&srv->cli, &eclass, &ecode, NULL);
|
errno = cli_errno(dos_error(&srv->cli);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1641,7 +1650,7 @@ int smbc_opendir(const char *fname)
|
|||||||
free(smbc_file_table[slot]);
|
free(smbc_file_table[slot]);
|
||||||
}
|
}
|
||||||
smbc_file_table[slot] = NULL;
|
smbc_file_table[slot] = NULL;
|
||||||
errno = cli_error(&srv->cli, &eclass, &ecode, NULL);
|
errno = cli_error(&srv->cli);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1675,7 +1684,7 @@ int smbc_opendir(const char *fname)
|
|||||||
if (cli_RNetShareEnum(&srv->cli, list_fn,
|
if (cli_RNetShareEnum(&srv->cli, list_fn,
|
||||||
(void *)smbc_file_table[slot]) < 0) {
|
(void *)smbc_file_table[slot]) < 0) {
|
||||||
|
|
||||||
errno = cli_error(&srv->cli, &eclass, &ecode, NULL);
|
errno = cli_errno(&srv->cli);
|
||||||
if (smbc_file_table[slot]) {
|
if (smbc_file_table[slot]) {
|
||||||
if (smbc_file_table[slot]->fname) free(smbc_file_table[slot]->fname);
|
if (smbc_file_table[slot]->fname) free(smbc_file_table[slot]->fname);
|
||||||
free(smbc_file_table[slot]);
|
free(smbc_file_table[slot]);
|
||||||
|
@ -1,3 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Unix SMB/Netbios implementation.
|
||||||
|
* Version 1.9.
|
||||||
|
* RPC Pipe client / server routines
|
||||||
|
* Copyright (C) Luke Kenneth Casson Leighton 1997-2001.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
/* NT error codes. please read nterr.h */
|
/* NT error codes. please read nterr.h */
|
||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
@ -516,36 +537,23 @@ nt_err_code_struct nt_errs[] =
|
|||||||
{ NULL, 0 }
|
{ NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
returns an NT error message. not amazingly helpful, but better than a number.
|
|
||||||
*****************************************************************************/
|
|
||||||
BOOL get_safe_nt_error_msg(uint32 nt_code,char *msg, size_t len)
|
|
||||||
{
|
|
||||||
int idx = 0;
|
|
||||||
|
|
||||||
slprintf(msg, len-1, "NT code 0x%08x", nt_code);
|
|
||||||
|
|
||||||
while (nt_errs[idx].nt_errstr != NULL)
|
|
||||||
{
|
|
||||||
if ((nt_errs[idx].nt_errcode & 0xFFFFFF) == (nt_code & 0xFFFFFF))
|
|
||||||
{
|
|
||||||
safe_strcpy(msg, nt_errs[idx].nt_errstr, len);
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
idx++;
|
|
||||||
}
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
returns an NT error message. not amazingly helpful, but better than a number.
|
returns an NT error message. not amazingly helpful, but better than a number.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
char *get_nt_error_msg(uint32 nt_code)
|
char *get_nt_error_msg(uint32 nt_code)
|
||||||
{
|
{
|
||||||
static pstring msg;
|
static pstring msg;
|
||||||
|
int idx = 0;
|
||||||
|
|
||||||
|
slprintf(msg, sizeof(msg), "NT code 0x%08x", nt_code);
|
||||||
|
|
||||||
|
while (nt_errs[idx].nt_errstr != NULL) {
|
||||||
|
if ((nt_errs[idx].nt_errcode & 0xFFFFFF) ==
|
||||||
|
(nt_code & 0xFFFFFF)) {
|
||||||
|
return nt_errs[idx].nt_errstr;
|
||||||
|
}
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
|
||||||
get_safe_nt_error_msg(nt_code, msg, sizeof(msg));
|
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -187,8 +187,7 @@ void SMBNTencrypt(uchar *passwd, uchar *c8, uchar *p24)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL make_oem_passwd_hash(const char *passwd, uchar old_pw_hash[16],
|
BOOL make_oem_passwd_hash(char data[516], const char *passwd, uchar old_pw_hash[16], BOOL unicode)
|
||||||
BOOL unicode, char data[516])
|
|
||||||
{
|
{
|
||||||
int new_pw_len = strlen(passwd) * (unicode ? 2 : 1);
|
int new_pw_len = strlen(passwd) * (unicode ? 2 : 1);
|
||||||
|
|
||||||
|
@ -36,34 +36,35 @@ typedef struct
|
|||||||
|
|
||||||
/* Dos Error Messages */
|
/* Dos Error Messages */
|
||||||
err_code_struct dos_msgs[] = {
|
err_code_struct dos_msgs[] = {
|
||||||
{"ERRbadfunc",1,"Invalid function."},
|
{"ERRbadfunc",ERRbadfunc,"Invalid function."},
|
||||||
{"ERRbadfile",2,"File not found."},
|
{"ERRbadfile",ERRbadfile,"File not found."},
|
||||||
{"ERRbadpath",3,"Directory invalid."},
|
{"ERRbadpath",ERRbadpath,"Directory invalid."},
|
||||||
{"ERRnofids",4,"No file descriptors available"},
|
{"ERRnofids",ERRnofids,"No file descriptors available"},
|
||||||
{"ERRnoaccess",5,"Access denied."},
|
{"ERRnoaccess",ERRnoaccess,"Access denied."},
|
||||||
{"ERRbadfid",6,"Invalid file handle."},
|
{"ERRbadfid",ERRbadfid,"Invalid file handle."},
|
||||||
{"ERRbadmcb",7,"Memory control blocks destroyed."},
|
{"ERRbadmcb",7,"Memory control blocks destroyed."},
|
||||||
{"ERRnomem",8,"Insufficient server memory to perform the requested function."},
|
{"ERRnomem",ERRnomem,"Insufficient server memory to perform the requested function."},
|
||||||
{"ERRbadmem",9,"Invalid memory block address."},
|
{"ERRbadmem",ERRbadmem,"Invalid memory block address."},
|
||||||
{"ERRbadenv",10,"Invalid environment."},
|
{"ERRbadenv",ERRbadenv,"Invalid environment."},
|
||||||
{"ERRbadformat",11,"Invalid format."},
|
{"ERRbadformat",11,"Invalid format."},
|
||||||
{"ERRbadaccess",12,"Invalid open mode."},
|
{"ERRbadaccess",ERRbadaccess,"Invalid open mode."},
|
||||||
{"ERRbaddata",13,"Invalid data."},
|
{"ERRbaddata",ERRbaddata,"Invalid data."},
|
||||||
{"ERR",14,"reserved."},
|
{"ERR",ERRres,"reserved."},
|
||||||
{"ERRbaddrive",15,"Invalid drive specified."},
|
{"ERRbaddrive",ERRbaddrive,"Invalid drive specified."},
|
||||||
{"ERRremcd",16,"A Delete Directory request attempted to remove the server's current directory."},
|
{"ERRremcd",ERRremcd,"A Delete Directory request attempted to remove the server's current directory."},
|
||||||
{"ERRdiffdevice",17,"Not same device."},
|
{"ERRdiffdevice",ERRdiffdevice,"Not same device."},
|
||||||
{"ERRnofiles",18,"A File Search command can find no more files matching the specified criteria."},
|
{"ERRnofiles",ERRnofiles,"A File Search command can find no more files matching the specified criteria."},
|
||||||
{"ERRbadshare",32,"The sharing mode specified for an Open conflicts with existing FIDs on the file."},
|
{"ERRbadshare",ERRbadshare,"The sharing mode specified for an Open conflicts with existing FIDs on the file."},
|
||||||
{"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."},
|
{"ERRlock",ERRlock,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."},
|
||||||
{"ERRunsup", 50, "The operation is unsupported"},
|
{"ERRunsup", ERRunsup, "The operation is unsupported"},
|
||||||
{"ERRnosuchshare", 67, "You specified an invalid share name"},
|
{"ERRnosuchshare", ERRnosuchshare, "You specified an invalid share name"},
|
||||||
{"ERRfilexists",80,"The file named in a Create Directory, Make New File or Link request already exists."},
|
{"ERRfilexists",ERRfilexists,"The file named in a Create Directory, Make New File or Link request already exists."},
|
||||||
{"ERRbadpipe",230,"Pipe invalid."},
|
{"ERRinvalidname",ERRinvalidname, "Invalid name"},
|
||||||
{"ERRpipebusy",231,"All instances of the requested pipe are busy."},
|
{"ERRbadpipe",ERRbadpipe,"Pipe invalid."},
|
||||||
{"ERRpipeclosing",232,"Pipe close in progress."},
|
{"ERRpipebusy",ERRpipebusy,"All instances of the requested pipe are busy."},
|
||||||
{"ERRnotconnected",233,"No process on other end of pipe."},
|
{"ERRpipeclosing",ERRpipeclosing,"Pipe close in progress."},
|
||||||
{"ERRmoredata",234,"There is more data to be returned."},
|
{"ERRnotconnected",ERRnotconnected,"No process on other end of pipe."},
|
||||||
|
{"ERRmoredata",ERRmoredata,"There is more data to be returned."},
|
||||||
{"ERRinvgroup",2455,"Invalid workgroup (try the -W option)"},
|
{"ERRinvgroup",2455,"Invalid workgroup (try the -W option)"},
|
||||||
{NULL,-1,NULL}};
|
{NULL,-1,NULL}};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user