summaryrefslogtreecommitdiff
path: root/source3/libsmb
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@samba.org>2008-01-05 23:09:38 +0100
committerJelmer Vernooij <jelmer@samba.org>2008-01-05 23:09:38 +0100
commitaaa27706664da2855c09da0691c3717b571edaba (patch)
tree17cc8a7475f7062eb664d0201d660c77bf415a7e /source3/libsmb
parent3ba8fbef29aabfcd78e1170fcbfcf7bc943af6f9 (diff)
parent4a413e4bd177402a1697cffac43d35e94cc55102 (diff)
downloadsamba-aaa27706664da2855c09da0691c3717b571edaba.tar.gz
samba-aaa27706664da2855c09da0691c3717b571edaba.tar.bz2
samba-aaa27706664da2855c09da0691c3717b571edaba.zip
Merge branch 'v3-2-test' of ssh://git.samba.org/data/git/samba into v3-2-test
(This used to be commit 5a30f6377d37d8a5cadce4fb9a2fc19b78fc1709)
Diffstat (limited to 'source3/libsmb')
-rw-r--r--source3/libsmb/cliconnect.c22
-rw-r--r--source3/libsmb/clidfs.c109
-rw-r--r--source3/libsmb/clidgram.c2
-rw-r--r--source3/libsmb/clientgen.c119
-rw-r--r--source3/libsmb/clifile.c44
-rw-r--r--source3/libsmb/clifsinfo.c366
-rw-r--r--source3/libsmb/clilist.c4
-rw-r--r--source3/libsmb/climessage.c6
-rw-r--r--source3/libsmb/clioplock.c2
-rw-r--r--source3/libsmb/cliprint.c4
-rw-r--r--source3/libsmb/cliquota.c4
-rw-r--r--source3/libsmb/clireadwrite.c31
-rw-r--r--source3/libsmb/clisecdesc.c45
-rw-r--r--source3/libsmb/clitrans.c8
-rw-r--r--source3/libsmb/doserr.c4
-rw-r--r--source3/libsmb/errormap.c105
-rw-r--r--source3/libsmb/libsmbclient.c98
-rw-r--r--source3/libsmb/ntlm_check.c5
-rw-r--r--source3/libsmb/ntlmssp.c7
-rw-r--r--source3/libsmb/smb_seal.c497
-rw-r--r--source3/libsmb/smb_signing.c8
-rw-r--r--source3/libsmb/smbencrypt.c20
22 files changed, 1361 insertions, 149 deletions
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 33110c803f..4560521d4a 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -98,7 +98,7 @@ static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli,
/* send a session setup command */
memset(cli->outbuf,'\0',smb_size);
- set_message(cli->outbuf,10, 0, True);
+ cli_set_message(cli->outbuf,10, 0, True);
SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
cli_setup_packet(cli);
@@ -168,7 +168,7 @@ static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
uint32 capabilities = cli_session_setup_capabilities(cli);
memset(cli->outbuf, '\0', smb_size);
- set_message(cli->outbuf,13,0,True);
+ cli_set_message(cli->outbuf,13,0,True);
SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
cli_setup_packet(cli);
@@ -228,7 +228,7 @@ static NTSTATUS cli_session_setup_plaintext(struct cli_state *cli,
fstr_sprintf( lanman, "Samba %s", SAMBA_VERSION_STRING);
memset(cli->outbuf, '\0', smb_size);
- set_message(cli->outbuf,13,0,True);
+ cli_set_message(cli->outbuf,13,0,True);
SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
cli_setup_packet(cli);
@@ -377,7 +377,7 @@ static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
/* send a session setup command */
memset(cli->outbuf,'\0',smb_size);
- set_message(cli->outbuf,13,0,True);
+ cli_set_message(cli->outbuf,13,0,True);
SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
cli_setup_packet(cli);
@@ -457,7 +457,7 @@ static bool cli_session_setup_blob_send(struct cli_state *cli, DATA_BLOB blob)
/* send a session setup command */
memset(cli->outbuf,'\0',smb_size);
- set_message(cli->outbuf,12,0,True);
+ cli_set_message(cli->outbuf,12,0,True);
SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
cli_setup_packet(cli);
@@ -1028,7 +1028,7 @@ NTSTATUS cli_session_setup(struct cli_state *cli,
bool cli_ulogoff(struct cli_state *cli)
{
memset(cli->outbuf,'\0',smb_size);
- set_message(cli->outbuf,2,0,True);
+ cli_set_message(cli->outbuf,2,0,True);
SCVAL(cli->outbuf,smb_com,SMBulogoffX);
cli_setup_packet(cli);
SSVAL(cli->outbuf,smb_vwv0,0xFF);
@@ -1106,7 +1106,7 @@ bool cli_send_tconX(struct cli_state *cli,
slprintf(fullshare, sizeof(fullshare)-1,
"\\\\%s\\%s", cli->desthost, share);
- set_message(cli->outbuf,4, 0, True);
+ cli_set_message(cli->outbuf,4, 0, True);
SCVAL(cli->outbuf,smb_com,SMBtconX);
cli_setup_packet(cli);
@@ -1157,7 +1157,7 @@ bool cli_send_tconX(struct cli_state *cli,
bool cli_tdis(struct cli_state *cli)
{
memset(cli->outbuf,'\0',smb_size);
- set_message(cli->outbuf,0,0,True);
+ cli_set_message(cli->outbuf,0,0,True);
SCVAL(cli->outbuf,smb_com,SMBtdis);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
cli_setup_packet(cli);
@@ -1189,7 +1189,7 @@ void cli_negprot_send(struct cli_state *cli)
memset(cli->outbuf,'\0',smb_size);
/* setup the protocol strings */
- set_message(cli->outbuf,0,0,True);
+ cli_set_message(cli->outbuf,0,0,True);
p = smb_buf(cli->outbuf);
for (numprots=0;
@@ -1229,7 +1229,7 @@ bool cli_negprot(struct cli_state *cli)
numprots++)
plength += strlen(prots[numprots].name)+2;
- set_message(cli->outbuf,0,plength,True);
+ cli_set_message(cli->outbuf,0,plength,True);
p = smb_buf(cli->outbuf);
for (numprots=0;
@@ -1806,7 +1806,7 @@ NTSTATUS cli_raw_tcon(struct cli_state *cli,
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf, 0, 0, True);
+ cli_set_message(cli->outbuf, 0, 0, True);
SCVAL(cli->outbuf,smb_com,SMBtcon);
cli_setup_packet(cli);
diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c
index e0c40b52ed..77419b4a1a 100644
--- a/source3/libsmb/clidfs.c
+++ b/source3/libsmb/clidfs.c
@@ -58,6 +58,52 @@ static struct sockaddr_storage dest_ss;
static struct client_connection *connections;
+static bool cli_check_msdfs_proxy(TALLOC_CTX *ctx,
+ struct cli_state *cli,
+ const char *sharename,
+ char **pp_newserver,
+ char **pp_newshare,
+ bool force_encrypt,
+ const char *username,
+ const char *password,
+ const char *domain);
+
+/********************************************************************
+ Ensure a connection is encrypted.
+********************************************************************/
+
+NTSTATUS cli_cm_force_encryption(struct cli_state *c,
+ const char *username,
+ const char *password,
+ const char *domain,
+ const char *sharename)
+{
+ NTSTATUS status = cli_force_encryption(c,
+ username,
+ password,
+ domain);
+
+ if (NT_STATUS_EQUAL(status,NT_STATUS_NOT_SUPPORTED)) {
+ d_printf("Encryption required and "
+ "server that doesn't support "
+ "UNIX extensions - failing connect\n");
+ } else if (NT_STATUS_EQUAL(status,NT_STATUS_UNKNOWN_REVISION)) {
+ d_printf("Encryption required and "
+ "can't get UNIX CIFS extensions "
+ "version from server.\n");
+ } else if (NT_STATUS_EQUAL(status,NT_STATUS_UNSUPPORTED_COMPRESSION)) {
+ d_printf("Encryption required and "
+ "share %s doesn't support "
+ "encryption.\n", sharename);
+ } else if (!NT_STATUS_IS_OK(status)) {
+ d_printf("Encryption required and "
+ "setup failed with error %s.\n",
+ nt_errstr(status));
+ }
+
+ return status;
+}
+
/********************************************************************
Return a connection to a server.
********************************************************************/
@@ -65,7 +111,8 @@ static struct client_connection *connections;
static struct cli_state *do_connect(TALLOC_CTX *ctx,
const char *server,
const char *share,
- bool show_sessetup)
+ bool show_sessetup,
+ bool force_encrypt)
{
struct cli_state *c = NULL;
struct nmb_name called, calling;
@@ -197,9 +244,14 @@ static struct cli_state *do_connect(TALLOC_CTX *ctx,
if ((c->capabilities & CAP_DFS) &&
cli_check_msdfs_proxy(ctx, c, sharename,
- &newserver, &newshare)) {
+ &newserver, &newshare,
+ force_encrypt,
+ username,
+ password,
+ lp_workgroup())) {
cli_shutdown(c);
- return do_connect(ctx, newserver, newshare, false);
+ return do_connect(ctx, newserver,
+ newshare, false, force_encrypt);
}
/* must be a normal share */
@@ -211,6 +263,18 @@ static struct cli_state *do_connect(TALLOC_CTX *ctx,
return NULL;
}
+ if (force_encrypt) {
+ status = cli_cm_force_encryption(c,
+ username,
+ password,
+ lp_workgroup(),
+ sharename);
+ if (!NT_STATUS_IS_OK(status)) {
+ cli_shutdown(c);
+ return NULL;
+ }
+ }
+
DEBUG(4,(" tconx ok\n"));
return c;
}
@@ -269,7 +333,8 @@ static struct cli_state *cli_cm_connect(TALLOC_CTX *ctx,
struct cli_state *referring_cli,
const char *server,
const char *share,
- bool show_hdr)
+ bool show_hdr,
+ bool force_encrypt)
{
struct client_connection *node;
@@ -279,7 +344,7 @@ static struct cli_state *cli_cm_connect(TALLOC_CTX *ctx,
return NULL;
}
- node->cli = do_connect(ctx, server, share, show_hdr);
+ node->cli = do_connect(ctx, server, share, show_hdr, force_encrypt);
if ( !node->cli ) {
TALLOC_FREE( node );
@@ -331,7 +396,8 @@ struct cli_state *cli_cm_open(TALLOC_CTX *ctx,
struct cli_state *referring_cli,
const char *server,
const char *share,
- bool show_hdr)
+ bool show_hdr,
+ bool force_encrypt)
{
struct cli_state *c;
@@ -339,7 +405,8 @@ struct cli_state *cli_cm_open(TALLOC_CTX *ctx,
c = cli_cm_find(server, share);
if (!c) {
- c = cli_cm_connect(ctx, referring_cli, server, share, show_hdr);
+ c = cli_cm_connect(ctx, referring_cli,
+ server, share, show_hdr, force_encrypt);
}
return c;
@@ -776,7 +843,9 @@ bool cli_resolve_path(TALLOC_CTX *ctx,
/* Check for the referral. */
if (!(cli_ipc = cli_cm_open(ctx, rootcli,
- rootcli->desthost, "IPC$", false))) {
+ rootcli->desthost,
+ "IPC$", false,
+ (rootcli->trans_enc_state != NULL)))) {
return false;
}
@@ -818,7 +887,10 @@ bool cli_resolve_path(TALLOC_CTX *ctx,
/* Open the connection to the target server & share */
if ((*targetcli = cli_cm_open(ctx, rootcli,
- server, share, false)) == NULL) {
+ server,
+ share,
+ false,
+ (rootcli->trans_enc_state != NULL))) == NULL) {
d_printf("Unable to follow dfs referral [\\%s\\%s]\n",
server, share );
return false;
@@ -905,11 +977,15 @@ bool cli_resolve_path(TALLOC_CTX *ctx,
/********************************************************************
********************************************************************/
-bool cli_check_msdfs_proxy(TALLOC_CTX *ctx,
+static bool cli_check_msdfs_proxy(TALLOC_CTX *ctx,
struct cli_state *cli,
const char *sharename,
char **pp_newserver,
- char **pp_newshare )
+ char **pp_newshare,
+ bool force_encrypt,
+ const char *username,
+ const char *password,
+ const char *domain)
{
CLIENT_DFS_REFERRAL *refs = NULL;
size_t num_refs = 0;
@@ -944,6 +1020,17 @@ bool cli_check_msdfs_proxy(TALLOC_CTX *ctx,
return false;
}
+ if (force_encrypt) {
+ NTSTATUS status = cli_cm_force_encryption(cli,
+ username,
+ password,
+ lp_workgroup(),
+ "IPC$");
+ if (!NT_STATUS_IS_OK(status)) {
+ return false;
+ }
+ }
+
res = cli_dfs_get_referral(ctx, cli, fullpath, &refs, &num_refs, &consumed);
if (!cli_tdis(cli)) {
diff --git a/source3/libsmb/clidgram.c b/source3/libsmb/clidgram.c
index 76630bd504..66c6ee1022 100644
--- a/source3/libsmb/clidgram.c
+++ b/source3/libsmb/clidgram.c
@@ -81,7 +81,7 @@ bool cli_send_mailslot(struct messaging_context *msg_ctx,
return False;
}
- set_message(ptr,17,strlen(mailslot) + 1 + len,True);
+ cli_set_message(ptr,17,strlen(mailslot) + 1 + len,True);
memcpy(ptr,tmp,4);
SCVAL(ptr,smb_com,SMBtrans);
diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c
index 0544b3d879..ecef293d07 100644
--- a/source3/libsmb/clientgen.c
+++ b/source3/libsmb/clientgen.c
@@ -20,6 +20,21 @@
#include "includes.h"
+/*******************************************************************
+ Setup the word count and byte count for a client smb message.
+********************************************************************/
+
+int cli_set_message(char *buf,int num_words,int num_bytes,bool zero)
+{
+ if (zero && (num_words || num_bytes)) {
+ memset(buf + smb_size,'\0',num_words*2 + num_bytes);
+ }
+ SCVAL(buf,smb_wct,num_words);
+ SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
+ smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
+ return (smb_size + num_words*2 + num_bytes);
+}
+
/****************************************************************************
Change the timeout (in milliseconds).
****************************************************************************/
@@ -71,6 +86,17 @@ static ssize_t client_receive_smb(struct cli_state *cli, size_t maxlen)
break;
}
}
+
+ if (cli_encryption_on(cli)) {
+ NTSTATUS status = cli_decrypt_message(cli);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("SMB decryption failed on incoming packet! Error %s\n",
+ nt_errstr(status)));
+ cli->smb_rw_error = SMB_READ_BAD_DECRYPT;
+ return -1;
+ }
+ }
+
show_msg(cli->inbuf);
return len;
}
@@ -85,7 +111,7 @@ bool cli_receive_smb(struct cli_state *cli)
/* fd == -1 causes segfaults -- Tom (tom@ninja.nl) */
if (cli->fd == -1)
- return False;
+ return false;
again:
len = client_receive_smb(cli, 0);
@@ -100,7 +126,7 @@ bool cli_receive_smb(struct cli_state *cli)
int fnum = SVAL(cli->inbuf,smb_vwv2);
unsigned char level = CVAL(cli->inbuf,smb_vwv3+1);
if (!cli->oplock_handler(cli, fnum, level)) {
- return False;
+ return false;
}
}
/* try to prevent loops */
@@ -114,7 +140,7 @@ bool cli_receive_smb(struct cli_state *cli)
DEBUG(0, ("Receiving SMB: Server stopped responding\n"));
close(cli->fd);
cli->fd = -1;
- return False;
+ return false;
}
if (!cli_check_sign_mac(cli)) {
@@ -135,16 +161,16 @@ bool cli_receive_smb(struct cli_state *cli)
* Set bad sig but don't close fd.
*/
cli->smb_rw_error = SMB_READ_BAD_SIG;
- return True;
+ return true;
}
DEBUG(0, ("SMB Signature verification failed on incoming packet!\n"));
cli->smb_rw_error = SMB_READ_BAD_SIG;
close(cli->fd);
cli->fd = -1;
- return False;
+ return false;
};
- return True;
+ return true;
}
/****************************************************************************
@@ -164,6 +190,7 @@ ssize_t cli_receive_smb_data(struct cli_state *cli, char *buffer, size_t len)
/****************************************************************************
Read a smb readX header.
+ We can only use this if encryption and signing are off.
****************************************************************************/
bool cli_receive_smb_readX_header(struct cli_state *cli)
@@ -171,7 +198,7 @@ bool cli_receive_smb_readX_header(struct cli_state *cli)
ssize_t len, offset;
if (cli->fd == -1)
- return False;
+ return false;
again:
@@ -199,7 +226,7 @@ bool cli_receive_smb_readX_header(struct cli_state *cli)
if (cli->oplock_handler) {
int fnum = SVAL(cli->inbuf,smb_vwv2);
unsigned char level = CVAL(cli->inbuf,smb_vwv3+1);
- if (!cli->oplock_handler(cli, fnum, level)) return False;
+ if (!cli->oplock_handler(cli, fnum, level)) return false;
}
/* try to prevent loops */
SCVAL(cli->inbuf,smb_com,0xFF);
@@ -238,14 +265,14 @@ bool cli_receive_smb_readX_header(struct cli_state *cli)
}
}
- return True;
+ return true;
read_err:
cli->smb_rw_error = SMB_READ_ERROR;
close(cli->fd);
cli->fd = -1;
- return False;
+ return false;
}
static ssize_t write_socket(int fd, const char *buf, size_t len)
@@ -272,32 +299,54 @@ bool cli_send_smb(struct cli_state *cli)
size_t len;
size_t nwritten=0;
ssize_t ret;
+ char *buf_out = cli->outbuf;
+ bool enc_on = cli_encryption_on(cli);
/* fd == -1 causes segfaults -- Tom (tom@ninja.nl) */
if (cli->fd == -1)
- return False;
+ return false;
cli_calculate_sign_mac(cli);
- len = smb_len(cli->outbuf) + 4;
+ if (enc_on) {
+ NTSTATUS status = cli_encrypt_message(cli, &buf_out);
+ if (!NT_STATUS_IS_OK(status)) {
+ close(cli->fd);
+ cli->fd = -1;
+ cli->smb_rw_error = SMB_WRITE_ERROR;
+ DEBUG(0,("Error in encrypting client message. Error %s\n",
+ nt_errstr(status) ));
+ return false;
+ }
+ }
+
+ len = smb_len(buf_out) + 4;
while (nwritten < len) {
- ret = write_socket(cli->fd,cli->outbuf+nwritten,len - nwritten);
+ ret = write_socket(cli->fd,buf_out+nwritten,len - nwritten);
if (ret <= 0) {
+ if (enc_on) {
+ cli_free_enc_buffer(cli, buf_out);
+ }
close(cli->fd);
cli->fd = -1;
cli->smb_rw_error = SMB_WRITE_ERROR;
DEBUG(0,("Error writing %d bytes to client. %d (%s)\n",
(int)len,(int)ret, strerror(errno) ));
- return False;
+ return false;
}
nwritten += ret;
}
+
+ if (enc_on) {
+ cli_free_enc_buffer(cli, buf_out);
+ }
+
/* Increment the mid so we can tell between responses. */
cli->mid++;
if (!cli->mid)
cli->mid++;
- return True;
+ return true;
}
/****************************************************************************
@@ -347,7 +396,7 @@ bool cli_send_smb_direct_writeX(struct cli_state *cli,
DEBUG(0,("Error writing %d extradata "
"bytes to client. %d (%s)\n",
(int)extradata,(int)ret, strerror(errno) ));
- return False;
+ return false;
}
nwritten += ret;
}
@@ -409,7 +458,7 @@ void cli_init_creds(struct cli_state *cli, const char *username, const char *dom
fstrcpy(cli->user_name, username);
pwd_set_cleartext(&cli->pwd, password);
if (!*username) {
- cli->pwd.null_pwd = True;
+ cli->pwd.null_pwd = true;
}
DEBUG(10,("cli_init_creds: user %s domain %s\n", cli->user_name, cli->domain));
@@ -424,16 +473,16 @@ void cli_setup_signing_state(struct cli_state *cli, int signing_state)
if (signing_state == Undefined)
return;
- if (signing_state == False) {
- cli->sign_info.allow_smb_signing = False;
- cli->sign_info.mandatory_signing = False;
+ if (signing_state == false) {
+ cli->sign_info.allow_smb_signing = false;
+ cli->sign_info.mandatory_signing = false;
return;
}
- cli->sign_info.allow_smb_signing = True;
+ cli->sign_info.allow_smb_signing = true;
if (signing_state == Required)
- cli->sign_info.mandatory_signing = True;
+ cli->sign_info.mandatory_signing = true;
}
/****************************************************************************
@@ -470,7 +519,7 @@ struct cli_state *cli_initialise(void)
cli->outbuf = (char *)SMB_MALLOC(cli->bufsize+SAFETY_MARGIN);
cli->inbuf = (char *)SMB_MALLOC(cli->bufsize+SAFETY_MARGIN);
cli->oplock_handler = cli_oplock_ack;
- cli->case_sensitive = False;
+ cli->case_sensitive = false;
cli->smb_rw_error = SMB_READ_OK;
cli->use_spnego = lp_client_use_spnego();
@@ -481,13 +530,13 @@ struct cli_state *cli_initialise(void)
client routines using DOS errors instead of STATUS32
ones. This intended only as a temporary hack. */
if (getenv("CLI_FORCE_DOSERR"))
- cli->force_dos_errors = True;
+ cli->force_dos_errors = true;
if (lp_client_signing())
- cli->sign_info.allow_smb_signing = True;
+ cli->sign_info.allow_smb_signing = true;
if (lp_client_signing() == Required)
- cli->sign_info.mandatory_signing = True;
+ cli->sign_info.mandatory_signing = true;
if (!cli->outbuf || !cli->inbuf)
goto error;
@@ -522,7 +571,7 @@ struct cli_state *cli_initialise(void)
/****************************************************************************
External interface.
Close an open named pipe over SMB. Free any authentication data.
- Returns False if the cli_close call failed.
+ Returns false if the cli_close call failed.
****************************************************************************/
bool cli_rpc_pipe_close(struct rpc_pipe_client *cli)
@@ -530,7 +579,7 @@ bool cli_rpc_pipe_close(struct rpc_pipe_client *cli)
bool ret;
if (!cli) {
- return False;
+ return false;
}
ret = cli_close(cli->cli, cli->fnum);
@@ -650,15 +699,15 @@ bool cli_send_keepalive(struct cli_state *cli)
{
if (cli->fd == -1) {
DEBUG(3, ("cli_send_keepalive: fd == -1\n"));
- return False;
+ return false;
}
if (!send_keepalive(cli->fd)) {
close(cli->fd);
cli->fd = -1;
DEBUG(0,("Error sending keepalive packet to client.\n"));
- return False;
+ return false;
}
- return True;
+ return true;
}
/****************************************************************************
@@ -674,7 +723,7 @@ bool cli_echo(struct cli_state *cli, uint16 num_echos,
SMB_ASSERT(length < 1024);
memset(cli->outbuf,'\0',smb_size);
- set_message(cli->outbuf,1,length,True);
+ cli_set_message(cli->outbuf,1,length,true);
SCVAL(cli->outbuf,smb_com,SMBecho);
SSVAL(cli->outbuf,smb_tid,65535);
SSVAL(cli->outbuf,smb_vwv0,num_echos);
@@ -689,13 +738,13 @@ bool cli_echo(struct cli_state *cli, uint16 num_echos,
for (i=0; i<num_echos; i++) {
if (!cli_receive_smb(cli)) {
- return False;
+ return false;
}
if (cli_is_error(cli)) {
- return False;
+ return false;
}
}
- return True;
+ return true;
}
diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c
index 001a42d4b9..9b4c380d40 100644
--- a/source3/libsmb/clifile.c
+++ b/source3/libsmb/clifile.c
@@ -429,7 +429,7 @@ bool cli_rename(struct cli_state *cli, const char *fname_src, const char *fname_
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,1, 0, true);
+ cli_set_message(cli->outbuf,1, 0, true);
SCVAL(cli->outbuf,smb_com,SMBmv);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -470,7 +470,7 @@ bool cli_ntrename(struct cli_state *cli, const char *fname_src, const char *fnam
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf, 4, 0, true);
+ cli_set_message(cli->outbuf, 4, 0, true);
SCVAL(cli->outbuf,smb_com,SMBntrename);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -512,7 +512,7 @@ bool cli_nt_hardlink(struct cli_state *cli, const char *fname_src, const char *f
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf, 4, 0, true);
+ cli_set_message(cli->outbuf, 4, 0, true);
SCVAL(cli->outbuf,smb_com,SMBntrename);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -554,7 +554,7 @@ bool cli_unlink_full(struct cli_state *cli, const char *fname, uint16 attrs)
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,1, 0, true);
+ cli_set_message(cli->outbuf,1, 0, true);
SCVAL(cli->outbuf,smb_com,SMBunlink);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -600,7 +600,7 @@ bool cli_mkdir(struct cli_state *cli, const char *dname)
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,0, 0, true);
+ cli_set_message(cli->outbuf,0, 0, true);
SCVAL(cli->outbuf,smb_com,SMBmkdir);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -636,7 +636,7 @@ bool cli_rmdir(struct cli_state *cli, const char *dname)
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,0, 0, true);
+ cli_set_message(cli->outbuf,0, 0, true);
SCVAL(cli->outbuf,smb_com,SMBrmdir);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -719,7 +719,7 @@ int cli_nt_create_full(struct cli_state *cli, const char *fname,
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,24,0, true);
+ cli_set_message(cli->outbuf,24,0, true);
SCVAL(cli->outbuf,smb_com,SMBntcreateX);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -815,7 +815,7 @@ int cli_open(struct cli_state *cli, const char *fname, int flags, int share_mode
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,15,0, true);
+ cli_set_message(cli->outbuf,15,0, true);
SCVAL(cli->outbuf,smb_com,SMBopenX);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -863,7 +863,7 @@ bool cli_close(struct cli_state *cli, int fnum)
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,3,0,True);
+ cli_set_message(cli->outbuf,3,0,True);
SCVAL(cli->outbuf,smb_com,SMBclose);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -896,7 +896,7 @@ NTSTATUS cli_locktype(struct cli_state *cli, int fnum,
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0', smb_size);
- set_message(cli->outbuf,8,0,True);
+ cli_set_message(cli->outbuf,8,0,True);
SCVAL(cli->outbuf,smb_com,SMBlockingX);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -948,7 +948,7 @@ bool cli_lock(struct cli_state *cli, int fnum,
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0', smb_size);
- set_message(cli->outbuf,8,0,True);
+ cli_set_message(cli->outbuf,8,0,True);
SCVAL(cli->outbuf,smb_com,SMBlockingX);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -1001,7 +1001,7 @@ bool cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len)
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,8,0,True);
+ cli_set_message(cli->outbuf,8,0,True);
SCVAL(cli->outbuf,smb_com,SMBlockingX);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -1053,7 +1053,7 @@ bool cli_lock64(struct cli_state *cli, int fnum,
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0', smb_size);
- set_message(cli->outbuf,8,0,True);
+ cli_set_message(cli->outbuf,8,0,True);
SCVAL(cli->outbuf,smb_com,SMBlockingX);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -1108,7 +1108,7 @@ bool cli_unlock64(struct cli_state *cli, int fnum, SMB_BIG_UINT offset, SMB_BIG_
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,8,0,True);
+ cli_set_message(cli->outbuf,8,0,True);
SCVAL(cli->outbuf,smb_com,SMBlockingX);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -1255,7 +1255,7 @@ bool cli_getattrE(struct cli_state *cli, int fd,
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,1,0,True);
+ cli_set_message(cli->outbuf,1,0,True);
SCVAL(cli->outbuf,smb_com,SMBgetattrE);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -1307,7 +1307,7 @@ bool cli_getatr(struct cli_state *cli, const char *fname,
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,0,0,True);
+ cli_set_message(cli->outbuf,0,0,True);
SCVAL(cli->outbuf,smb_com,SMBgetatr);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -1359,7 +1359,7 @@ bool cli_setattrE(struct cli_state *cli, int fd,
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,7,0,True);
+ cli_set_message(cli->outbuf,7,0,True);
SCVAL(cli->outbuf,smb_com,SMBsetattrE);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -1398,7 +1398,7 @@ bool cli_setatr(struct cli_state *cli, const char *fname, uint16 attr, time_t t)
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,8,0,True);
+ cli_set_message(cli->outbuf,8,0,True);
SCVAL(cli->outbuf,smb_com,SMBsetatr);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -1452,7 +1452,7 @@ bool cli_chkpath(struct cli_state *cli, const char *path)
}
memset(cli->outbuf,'\0',smb_size);
- set_message(cli->outbuf,0,0,True);
+ cli_set_message(cli->outbuf,0,0,True);
SCVAL(cli->outbuf,smb_com,SMBcheckpath);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
cli_setup_packet(cli);
@@ -1483,7 +1483,7 @@ bool cli_chkpath(struct cli_state *cli, const char *path)
bool cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail)
{
memset(cli->outbuf,'\0',smb_size);
- set_message(cli->outbuf,0,0,True);
+ cli_set_message(cli->outbuf,0,0,True);
SCVAL(cli->outbuf,smb_com,SMBdskattr);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
cli_setup_packet(cli);
@@ -1512,7 +1512,7 @@ int cli_ctemp(struct cli_state *cli, const char *path, char **tmp_path)
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,3,0,True);
+ cli_set_message(cli->outbuf,3,0,True);
SCVAL(cli->outbuf,smb_com,SMBctemp);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -1565,7 +1565,7 @@ NTSTATUS cli_raw_ioctl(struct cli_state *cli, int fnum, uint32 code, DATA_BLOB *
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf, 3, 0, True);
+ cli_set_message(cli->outbuf, 3, 0, True);
SCVAL(cli->outbuf,smb_com,SMBioctl);
cli_setup_packet(cli);
diff --git a/source3/libsmb/clifsinfo.c b/source3/libsmb/clifsinfo.c
index 1a75d144b2..fb923378ab 100644
--- a/source3/libsmb/clifsinfo.c
+++ b/source3/libsmb/clifsinfo.c
@@ -2,6 +2,7 @@
Unix SMB/CIFS implementation.
FS info functions
Copyright (C) Stefan (metze) Metzmacher 2003
+ Copyright (C) Jeremy Allison 2007
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
@@ -301,3 +302,368 @@ cleanup:
return ret;
}
+
+/******************************************************************************
+ Send/receive the request encryption blob.
+******************************************************************************/
+
+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;
+}
+
+/******************************************************************************
+ Make a client state struct.
+******************************************************************************/
+
+static struct smb_trans_enc_state *make_cli_enc_state(enum smb_trans_enc_type smb_enc_type)
+{
+ struct smb_trans_enc_state *es = NULL;
+ es = SMB_MALLOC_P(struct smb_trans_enc_state);
+ if (!es) {
+ return NULL;
+ }
+ ZERO_STRUCTP(es);
+ es->smb_enc_type = smb_enc_type;
+
+ if (smb_enc_type == SMB_TRANS_ENC_GSS) {
+#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
+ es->s.gss_state = SMB_MALLOC_P(struct smb_tran_enc_state_gss);
+ if (!es->s.gss_state) {
+ SAFE_FREE(es);
+ return NULL;
+ }
+ ZERO_STRUCTP(es->s.gss_state);
+#else
+ DEBUG(0,("make_cli_enc_state: no krb5 compiled.\n"));
+ SAFE_FREE(es);
+ return NULL;
+#endif
+ }
+ return es;
+}
+
+/******************************************************************************
+ Start a raw ntlmssp encryption.
+******************************************************************************/
+
+NTSTATUS cli_raw_ntlm_smb_encryption_start(struct cli_state *cli,
+ const char *user,
+ const char *pass,
+ const char *domain)
+{
+ DATA_BLOB blob_in = data_blob_null;
+ DATA_BLOB blob_out = data_blob_null;
+ DATA_BLOB param_out = data_blob_null;
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+ struct smb_trans_enc_state *es = make_cli_enc_state(SMB_TRANS_ENC_NTLM);
+
+ if (!es) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ status = ntlmssp_client_start(&es->s.ntlmssp_state);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto fail;
+ }
+
+ ntlmssp_want_feature(es->s.ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
+ es->s.ntlmssp_state->neg_flags |= (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL);
+
+ if (!NT_STATUS_IS_OK(status = ntlmssp_set_username(es->s.ntlmssp_state, user))) {
+ goto fail;
+ }
+ if (!NT_STATUS_IS_OK(status = ntlmssp_set_domain(es->s.ntlmssp_state, domain))) {
+ goto fail;
+ }
+ if (!NT_STATUS_IS_OK(status = ntlmssp_set_password(es->s.ntlmssp_state, pass))) {
+ goto fail;
+ }
+
+ do {
+ status = ntlmssp_update(es->s.ntlmssp_state, blob_in, &blob_out);
+ data_blob_free(&blob_in);
+ data_blob_free(&param_out);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) || NT_STATUS_IS_OK(status)) {
+ NTSTATUS trans_status = enc_blob_send_receive(cli,
+ &blob_out,
+ &blob_in,
+ &param_out);
+ if (!NT_STATUS_EQUAL(trans_status,
+ NT_STATUS_MORE_PROCESSING_REQUIRED) &&
+ !NT_STATUS_IS_OK(trans_status)) {
+ status = trans_status;
+ } else {
+ if (param_out.length == 2) {
+ es->enc_ctx_num = SVAL(param_out.data, 0);
+ }
+ }
+ }
+ data_blob_free(&blob_out);
+ } while (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED));
+
+ data_blob_free(&blob_in);
+
+ if (NT_STATUS_IS_OK(status)) {
+ /* Replace the old state, if any. */
+ if (cli->trans_enc_state) {
+ common_free_encryption_state(&cli->trans_enc_state);
+ }
+ cli->trans_enc_state = es;
+ cli->trans_enc_state->enc_on = True;
+ es = NULL;
+ }
+
+ fail:
+
+ common_free_encryption_state(&es);
+ return status;
+}
+
+#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
+
+#ifndef SMB_GSS_REQUIRED_FLAGS
+#define SMB_GSS_REQUIRED_FLAGS (GSS_C_CONF_FLAG|GSS_C_INTEG_FLAG|GSS_C_MUTUAL_FLAG|GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)
+#endif
+
+/******************************************************************************
+ Get client gss blob to send to a server.
+******************************************************************************/
+
+static NTSTATUS make_cli_gss_blob(struct smb_trans_enc_state *es,
+ const char *service,
+ const char *host,
+ NTSTATUS status_in,
+ DATA_BLOB spnego_blob_in,
+ DATA_BLOB *p_blob_out)
+{
+ const char *krb_mechs[] = {OID_KERBEROS5, NULL};
+ OM_uint32 ret;
+ OM_uint32 min;
+ gss_name_t srv_name;
+ gss_buffer_desc input_name;
+ gss_buffer_desc *p_tok_in;
+ gss_buffer_desc tok_out, tok_in;
+ DATA_BLOB blob_out = data_blob_null;
+ DATA_BLOB blob_in = data_blob_null;
+ char *host_princ_s = NULL;
+ OM_uint32 ret_flags = 0;
+ NTSTATUS status = NT_STATUS_OK;
+
+ gss_OID_desc nt_hostbased_service =
+ {10, CONST_DISCARD(char *,"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04")};
+
+ memset(&tok_out, '\0', sizeof(tok_out));
+
+ /* Get a ticket for the service@host */
+ asprintf(&host_princ_s, "%s@%s", service, host);
+ if (host_princ_s == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ input_name.value = host_princ_s;
+ input_name.length = strlen(host_princ_s) + 1;
+
+ ret = gss_import_name(&min,
+ &input_name,
+ &nt_hostbased_service,
+ &srv_name);
+
+ if (ret != GSS_S_COMPLETE) {
+ SAFE_FREE(host_princ_s);
+ return map_nt_error_from_gss(ret, min);
+ }
+
+ if (spnego_blob_in.length == 0) {
+ p_tok_in = GSS_C_NO_BUFFER;
+ } else {
+ /* Remove the SPNEGO wrapper */
+ if (!spnego_parse_auth_response(spnego_blob_in, status_in, OID_KERBEROS5, &blob_in)) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto fail;
+ }
+ tok_in.value = blob_in.data;
+ tok_in.length = blob_in.length;
+ p_tok_in = &tok_in;
+ }
+
+ ret = gss_init_sec_context(&min,
+ GSS_C_NO_CREDENTIAL, /* Use our default cred. */
+ &es->s.gss_state->gss_ctx,
+ srv_name,
+ GSS_C_NO_OID, /* default OID. */
+ GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG,
+ GSS_C_INDEFINITE, /* requested ticket lifetime. */
+ NULL, /* no channel bindings */
+ p_tok_in,
+ NULL, /* ignore mech type */
+ &tok_out,
+ &ret_flags,
+ NULL); /* ignore time_rec */
+
+ status = map_nt_error_from_gss(ret, min);
+ if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ ADS_STATUS adss = ADS_ERROR_GSS(ret, min);
+ DEBUG(10,("make_cli_gss_blob: gss_init_sec_context failed with %s\n",
+ ads_errstr(adss)));
+ goto fail;
+ }
+
+ if ((ret_flags & SMB_GSS_REQUIRED_FLAGS) != SMB_GSS_REQUIRED_FLAGS) {
+ status = NT_STATUS_ACCESS_DENIED;
+ }
+
+ blob_out = data_blob(tok_out.value, tok_out.length);
+
+ /* Wrap in an SPNEGO wrapper */
+ *p_blob_out = gen_negTokenTarg(krb_mechs, blob_out);
+
+ fail:
+
+ data_blob_free(&blob_out);
+ data_blob_free(&blob_in);
+ SAFE_FREE(host_princ_s);
+ gss_release_name(&min, &srv_name);
+ if (tok_out.value) {
+ gss_release_buffer(&min, &tok_out);
+ }
+ return status;
+}
+
+/******************************************************************************
+ Start a SPNEGO gssapi encryption context.
+******************************************************************************/
+
+NTSTATUS cli_gss_smb_encryption_start(struct cli_state *cli)
+{
+ DATA_BLOB blob_recv = data_blob_null;
+ DATA_BLOB blob_send = data_blob_null;
+ DATA_BLOB param_out = data_blob_null;
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+ fstring fqdn;
+ const char *servicename;
+ struct smb_trans_enc_state *es = make_cli_enc_state(SMB_TRANS_ENC_GSS);
+
+ if (!es) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ name_to_fqdn(fqdn, cli->desthost);
+ strlower_m(fqdn);
+
+ servicename = "cifs";
+ status = make_cli_gss_blob(es, servicename, fqdn, NT_STATUS_OK, blob_recv, &blob_send);
+ if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ servicename = "host";
+ status = make_cli_gss_blob(es, servicename, fqdn, NT_STATUS_OK, blob_recv, &blob_send);
+ if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ goto fail;
+ }
+ }
+
+ do {
+ data_blob_free(&blob_recv);
+ status = enc_blob_send_receive(cli, &blob_send, &blob_recv, &param_out);
+ if (param_out.length == 2) {
+ es->enc_ctx_num = SVAL(param_out.data, 0);
+ }
+ data_blob_free(&blob_send);
+ status = make_cli_gss_blob(es, servicename, fqdn, status, blob_recv, &blob_send);
+ } while (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED));
+ data_blob_free(&blob_recv);
+
+ if (NT_STATUS_IS_OK(status)) {
+ /* Replace the old state, if any. */
+ if (cli->trans_enc_state) {
+ common_free_encryption_state(&cli->trans_enc_state);
+ }
+ cli->trans_enc_state = es;
+ cli->trans_enc_state->enc_on = True;
+ es = NULL;
+ }
+
+ fail:
+
+ common_free_encryption_state(&es);
+ return status;
+}
+#else
+NTSTATUS cli_gss_smb_encryption_start(struct cli_state *cli)
+{
+ return NT_STATUS_NOT_SUPPORTED;
+}
+#endif
+
+/********************************************************************
+ Ensure a connection is encrypted.
+********************************************************************/
+
+NTSTATUS cli_force_encryption(struct cli_state *c,
+ const char *username,
+ const char *password,
+ const char *domain)
+{
+ uint16 major, minor;
+ uint32 caplow, caphigh;
+
+ if (!SERVER_HAS_UNIX_CIFS(c)) {
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+
+ if (!cli_unix_extensions_version(c, &major, &minor, &caplow, &caphigh)) {
+ return NT_STATUS_UNKNOWN_REVISION;
+ }
+
+ if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
+ return NT_STATUS_UNSUPPORTED_COMPRESSION;
+ }
+
+ if (c->use_kerberos) {
+ return cli_gss_smb_encryption_start(c);
+ }
+ return cli_raw_ntlm_smb_encryption_start(c,
+ username,
+ password,
+ domain);
+}
diff --git a/source3/libsmb/clilist.c b/source3/libsmb/clilist.c
index 2e4c360507..d5c7db09e9 100644
--- a/source3/libsmb/clilist.c
+++ b/source3/libsmb/clilist.c
@@ -521,7 +521,7 @@ int cli_list_old(struct cli_state *cli,const char *Mask,uint16 attribute,
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,2,0,True);
+ cli_set_message(cli->outbuf,2,0,True);
SCVAL(cli->outbuf,smb_com,SMBsearch);
@@ -581,7 +581,7 @@ int cli_list_old(struct cli_state *cli,const char *Mask,uint16 attribute,
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,2,0,True);
+ cli_set_message(cli->outbuf,2,0,True);
SCVAL(cli->outbuf,smb_com,SMBfclose);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
cli_setup_packet(cli);
diff --git a/source3/libsmb/climessage.c b/source3/libsmb/climessage.c
index 13ef1d43d4..00c25aa725 100644
--- a/source3/libsmb/climessage.c
+++ b/source3/libsmb/climessage.c
@@ -29,7 +29,7 @@ int cli_message_start_build(struct cli_state *cli, const char *host, const char
/* construct a SMBsendstrt command */
memset(cli->outbuf,'\0',smb_size);
- set_message(cli->outbuf,0,0,True);
+ cli_set_message(cli->outbuf,0,0,True);
SCVAL(cli->outbuf,smb_com,SMBsendstrt);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
cli_setup_packet(cli);
@@ -75,7 +75,7 @@ int cli_message_text_build(struct cli_state *cli, const char *msg, int len, int
char *p;
memset(cli->outbuf,'\0',smb_size);
- set_message(cli->outbuf,1,0,True);
+ cli_set_message(cli->outbuf,1,0,True);
SCVAL(cli->outbuf,smb_com,SMBsendtxt);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
cli_setup_packet(cli);
@@ -132,7 +132,7 @@ int cli_message_end_build(struct cli_state *cli, int grp)
char *p;
memset(cli->outbuf,'\0',smb_size);
- set_message(cli->outbuf,1,0,True);
+ cli_set_message(cli->outbuf,1,0,True);
SCVAL(cli->outbuf,smb_com,SMBsendend);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
diff --git a/source3/libsmb/clioplock.c b/source3/libsmb/clioplock.c
index 2e54f5a781..ef8b396461 100644
--- a/source3/libsmb/clioplock.c
+++ b/source3/libsmb/clioplock.c
@@ -32,7 +32,7 @@ bool cli_oplock_ack(struct cli_state *cli, int fnum, unsigned char level)
cli->outbuf = buf;
memset(buf,'\0',smb_size);
- set_message(buf,8,0,True);
+ cli_set_message(buf,8,0,True);
SCVAL(buf,smb_com,SMBlockingX);
SSVAL(buf,smb_tid, cli->cnum);
diff --git a/source3/libsmb/cliprint.c b/source3/libsmb/cliprint.c
index 7fbdb97c01..223ddb4186 100644
--- a/source3/libsmb/cliprint.c
+++ b/source3/libsmb/cliprint.c
@@ -195,7 +195,7 @@ int cli_spl_open(struct cli_state *cli, const char *fname, int flags, int share_
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,15,0,True);
+ cli_set_message(cli->outbuf,15,0,True);
SCVAL(cli->outbuf,smb_com,SMBsplopen);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -242,7 +242,7 @@ bool cli_spl_close(struct cli_state *cli, int fnum)
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,3,0,True);
+ cli_set_message(cli->outbuf,3,0,True);
SCVAL(cli->outbuf,smb_com,SMBsplclose);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
diff --git a/source3/libsmb/cliquota.c b/source3/libsmb/cliquota.c
index 206576f040..f369d28dff 100644
--- a/source3/libsmb/cliquota.c
+++ b/source3/libsmb/cliquota.c
@@ -150,7 +150,7 @@ bool cli_get_user_quota(struct cli_state *cli, int quota_fnum, SMB_NTQUOTA_STRUC
SIVAL(params, 8,0x00000000);
SIVAL(params,12,0x00000024);
- sid_len = sid_size(&pqt->sid);
+ sid_len = ndr_size_dom_sid(&pqt->sid, 0);
data_len = sid_len+8;
SIVAL(data, 0, 0x00000000);
SIVAL(data, 4, sid_len);
@@ -213,7 +213,7 @@ bool cli_set_user_quota(struct cli_state *cli, int quota_fnum, SMB_NTQUOTA_STRUC
SSVAL(params,0,quota_fnum);
- sid_len = sid_size(&pqt->sid);
+ sid_len = ndr_size_dom_sid(&pqt->sid, 0);
SIVAL(data,0,0);
SIVAL(data,4,sid_len);
SBIG_UINT(data, 8,(SMB_BIG_UINT)0);
diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c
index d77875bae5..0b33e43563 100644
--- a/source3/libsmb/clireadwrite.c
+++ b/source3/libsmb/clireadwrite.c
@@ -34,7 +34,7 @@ static bool cli_issue_read(struct cli_state *cli, int fnum, off_t offset,
if ((SMB_BIG_UINT)offset >> 32)
bigoffset = True;
- set_message(cli->outbuf,bigoffset ? 12 : 10,0,True);
+ cli_set_message(cli->outbuf,bigoffset ? 12 : 10,0,True);
SCVAL(cli->outbuf,smb_com,SMBreadX);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -65,8 +65,8 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_
size_t size2;
size_t readsize;
ssize_t total = 0;
- /* We can only do direct reads if not signing. */
- bool direct_reads = !client_is_signing_on(cli);
+ /* We can only do direct reads if not signing or encrypting. */
+ bool direct_reads = !client_is_signing_on(cli) && !cli_encryption_on(cli);
if (size == 0)
return 0;
@@ -76,7 +76,9 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_
* rounded down to a multiple of 1024.
*/
- if (client_is_signing_on(cli) == False && (cli->posix_capabilities & CIFS_UNIX_LARGE_READ_CAP)) {
+ if (client_is_signing_on(cli) == false &&
+ cli_encryption_on(cli) == false &&
+ (cli->posix_capabilities & CIFS_UNIX_LARGE_READ_CAP)) {
readsize = CLI_SAMBA_MAX_POSIX_LARGE_READX_SIZE;
} else if (cli->capabilities & CAP_LARGE_READX) {
if (cli->is_samba) {
@@ -203,7 +205,7 @@ static bool cli_issue_readraw(struct cli_state *cli, int fnum, off_t offset,
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,10,0,True);
+ cli_set_message(cli->outbuf,10,0,True);
SCVAL(cli->outbuf,smb_com,SMBreadbraw);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -295,8 +297,8 @@ static bool cli_issue_write(struct cli_state *cli,
{
char *p;
bool large_writex = false;
- /* We can only do direct writes if not signing. */
- bool direct_writes = !client_is_signing_on(cli);
+ /* We can only do direct writes if not signing and not encrypting. */
+ bool direct_writes = !client_is_signing_on(cli) && !cli_encryption_on(cli);
if (!direct_writes && size + 1 > cli->bufsize) {
cli->outbuf = (char *)SMB_REALLOC(cli->outbuf, size + 1024);
@@ -319,9 +321,9 @@ static bool cli_issue_write(struct cli_state *cli,
}
if (large_writex) {
- set_message(cli->outbuf,14,0,True);
+ cli_set_message(cli->outbuf,14,0,True);
} else {
- set_message(cli->outbuf,12,0,True);
+ cli_set_message(cli->outbuf,12,0,True);
}
SCVAL(cli->outbuf,smb_com,SMBwriteX);
@@ -404,16 +406,17 @@ ssize_t cli_write(struct cli_state *cli,
if (write_mode == 0 &&
!client_is_signing_on(cli) &&
+ !cli_encryption_on(cli) &&
(cli->posix_capabilities & CIFS_UNIX_LARGE_WRITE_CAP) &&
(cli->capabilities & CAP_LARGE_FILES)) {
/* Only do massive writes if we can do them direct
- * with no signing - not on a pipe. */
+ * with no signing or encrypting - not on a pipe. */
writesize = CLI_SAMBA_MAX_POSIX_LARGE_WRITEX_SIZE;
- } else if (cli->capabilities & CAP_LARGE_READX) {
+ } else if (cli->capabilities & CAP_LARGE_WRITEX) {
if (cli->is_samba) {
- writesize = CLI_SAMBA_MAX_LARGE_READX_SIZE;
+ writesize = CLI_SAMBA_MAX_LARGE_WRITEX_SIZE;
} else {
- writesize = CLI_WINDOWS_MAX_LARGE_READX_SIZE;
+ writesize = CLI_WINDOWS_MAX_LARGE_WRITEX_SIZE;
}
} else {
writesize = (cli->max_xmit - (smb_size+32)) & ~1023;
@@ -471,7 +474,7 @@ ssize_t cli_smbwrite(struct cli_state *cli,
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,5, 0,True);
+ cli_set_message(cli->outbuf,5, 0,True);
SCVAL(cli->outbuf,smb_com,SMBwrite);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
diff --git a/source3/libsmb/clisecdesc.c b/source3/libsmb/clisecdesc.c
index 46a6609415..adc6fba9af 100644
--- a/source3/libsmb/clisecdesc.c
+++ b/source3/libsmb/clisecdesc.c
@@ -28,9 +28,8 @@ SEC_DESC *cli_query_secdesc(struct cli_state *cli, int fnum,
char param[8];
char *rparam=NULL, *rdata=NULL;
unsigned int rparam_count=0, rdata_count=0;
- prs_struct pd;
- bool pd_initialized = False;
SEC_DESC *psd = NULL;
+ NTSTATUS status;
SIVAL(param, 0, fnum);
SIVAL(param, 4, 0x7);
@@ -56,15 +55,12 @@ SEC_DESC *cli_query_secdesc(struct cli_state *cli, int fnum,
if (cli_is_error(cli))
goto cleanup;
- if (!prs_init(&pd, rdata_count, mem_ctx, UNMARSHALL)) {
- goto cleanup;
- }
- pd_initialized = True;
- prs_copy_data_in(&pd, rdata, rdata_count);
- prs_set_offset(&pd,0);
+ status = unmarshall_sec_desc(mem_ctx, (uint8 *)rdata, rdata_count,
+ &psd);
- if (!sec_io_desc("sd data", &psd, &pd, 1)) {
- DEBUG(1,("Failed to parse secdesc\n"));
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("unmarshall_sec_desc failed: %s\n",
+ nt_errstr(status)));
goto cleanup;
}
@@ -73,8 +69,6 @@ SEC_DESC *cli_query_secdesc(struct cli_state *cli, int fnum,
SAFE_FREE(rparam);
SAFE_FREE(rdata);
- if (pd_initialized)
- prs_mem_free(&pd);
return psd;
}
@@ -87,20 +81,16 @@ bool cli_set_secdesc(struct cli_state *cli, int fnum, SEC_DESC *sd)
char *rparam=NULL, *rdata=NULL;
unsigned int rparam_count=0, rdata_count=0;
uint32 sec_info = 0;
- TALLOC_CTX *mem_ctx;
- prs_struct pd;
+ TALLOC_CTX *frame = talloc_stackframe();
bool ret = False;
-
- if ((mem_ctx = talloc_init("cli_set_secdesc")) == NULL) {
- DEBUG(0,("talloc_init failed.\n"));
- goto cleanup;
- }
-
- prs_init(&pd, 0, mem_ctx, MARSHALL);
- prs_give_memory(&pd, NULL, 0, True);
-
- if (!sec_io_desc("sd data", &sd, &pd, 1)) {
- DEBUG(1,("Failed to marshall secdesc\n"));
+ uint8 *data;
+ size_t len;
+ NTSTATUS status;
+
+ status = marshall_sec_desc(talloc_tos(), sd, &data, &len);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("marshall_sec_desc failed: %s\n",
+ nt_errstr(status)));
goto cleanup;
}
@@ -119,7 +109,7 @@ bool cli_set_secdesc(struct cli_state *cli, int fnum, SEC_DESC *sd)
0,
NULL, 0, 0,
param, 8, 0,
- prs_data_p(&pd), prs_offset(&pd), 0)) {
+ (char *)data, len, 0)) {
DEBUG(1,("Failed to send NT_TRANSACT_SET_SECURITY_DESC\n"));
goto cleanup;
}
@@ -139,8 +129,7 @@ bool cli_set_secdesc(struct cli_state *cli, int fnum, SEC_DESC *sd)
SAFE_FREE(rparam);
SAFE_FREE(rdata);
- talloc_destroy(mem_ctx);
+ TALLOC_FREE(frame);
- prs_mem_free(&pd);
return ret;
}
diff --git a/source3/libsmb/clitrans.c b/source3/libsmb/clitrans.c
index a6f7f7fec1..bfb31fdb74 100644
--- a/source3/libsmb/clitrans.c
+++ b/source3/libsmb/clitrans.c
@@ -43,7 +43,7 @@ bool cli_send_trans(struct cli_state *cli, int trans,
this_ldata = MIN(ldata,cli->max_xmit - (500+lsetup*2+this_lparam));
memset(cli->outbuf,'\0',smb_size);
- set_message(cli->outbuf,14+lsetup,0,True);
+ cli_set_message(cli->outbuf,14+lsetup,0,True);
SCVAL(cli->outbuf,smb_com,trans);
SSVAL(cli->outbuf,smb_tid, cli->cnum);
cli_setup_packet(cli);
@@ -107,7 +107,7 @@ bool cli_send_trans(struct cli_state *cli, int trans,
this_lparam = MIN(lparam-tot_param,cli->max_xmit - 500); /* hack */
this_ldata = MIN(ldata-tot_data,cli->max_xmit - (500+this_lparam));
- set_message(cli->outbuf,trans==SMBtrans?8:9,0,True);
+ cli_set_message(cli->outbuf,trans==SMBtrans?8:9,0,True);
SCVAL(cli->outbuf,smb_com,(trans==SMBtrans ? SMBtranss : SMBtranss2));
outparam = smb_buf(cli->outbuf);
@@ -368,7 +368,7 @@ bool cli_send_nt_trans(struct cli_state *cli,
this_ldata = MIN(ldata,cli->max_xmit - (500+lsetup*2+this_lparam));
memset(cli->outbuf,'\0',smb_size);
- set_message(cli->outbuf,19+lsetup,0,True);
+ cli_set_message(cli->outbuf,19+lsetup,0,True);
SCVAL(cli->outbuf,smb_com,SMBnttrans);
SSVAL(cli->outbuf,smb_tid, cli->cnum);
cli_setup_packet(cli);
@@ -424,7 +424,7 @@ bool cli_send_nt_trans(struct cli_state *cli,
this_lparam = MIN(lparam-tot_param,cli->max_xmit - 500); /* hack */
this_ldata = MIN(ldata-tot_data,cli->max_xmit - (500+this_lparam));
- set_message(cli->outbuf,18,0,True);
+ cli_set_message(cli->outbuf,18,0,True);
SCVAL(cli->outbuf,smb_com,SMBnttranss);
/* XXX - these should probably be aligned */
diff --git a/source3/libsmb/doserr.c b/source3/libsmb/doserr.c
index dd556bba5a..79445a2410 100644
--- a/source3/libsmb/doserr.c
+++ b/source3/libsmb/doserr.c
@@ -63,6 +63,7 @@ werror_code_struct dos_errs[] =
{ "WERR_JOB_NOT_FOUND", WERR_JOB_NOT_FOUND },
{ "WERR_DEST_NOT_FOUND", WERR_DEST_NOT_FOUND },
{ "WERR_NOT_LOCAL_DOMAIN", WERR_NOT_LOCAL_DOMAIN },
+ { "WERR_USER_EXISTS", WERR_USER_EXISTS },
{ "WERR_NO_LOGON_SERVERS", WERR_NO_LOGON_SERVERS },
{ "WERR_NO_SUCH_LOGON_SESSION", WERR_NO_SUCH_LOGON_SESSION },
{ "WERR_PRINTER_DRIVER_IN_USE", WERR_PRINTER_DRIVER_IN_USE },
@@ -77,6 +78,7 @@ werror_code_struct dos_errs[] =
{ "WERR_SETUP_NOT_JOINED", WERR_SETUP_NOT_JOINED },
{ "WERR_SETUP_ALREADY_JOINED", WERR_SETUP_ALREADY_JOINED },
{ "WERR_SETUP_DOMAIN_CONTROLLER", WERR_SETUP_DOMAIN_CONTROLLER },
+ { "WERR_DEFAULT_JOIN_REQUIRED", WERR_DEFAULT_JOIN_REQUIRED },
{ "WERR_DEVICE_NOT_AVAILABLE", WERR_DEVICE_NOT_AVAILABLE },
{ "WERR_LOGON_FAILURE", WERR_LOGON_FAILURE },
{ "WERR_NO_SUCH_DOMAIN", WERR_NO_SUCH_DOMAIN },
@@ -90,6 +92,7 @@ werror_code_struct dos_errs[] =
{ "WERR_REG_CORRUPT", WERR_REG_CORRUPT },
{ "WERR_REG_IO_FAILURE", WERR_REG_IO_FAILURE },
{ "WERR_REG_FILE_INVALID", WERR_REG_FILE_INVALID },
+ { "WERR_NO_SUCH_SERVICE", WERR_NO_SUCH_SERVICE },
{ "WERR_SERVICE_DISABLED", WERR_SERVICE_DISABLED },
{ "WERR_CAN_NOT_COMPLETE", WERR_CAN_NOT_COMPLETE},
{ "WERR_INVALID_FLAGS", WERR_INVALID_FLAGS},
@@ -110,6 +113,7 @@ werror_str_struct dos_err_strs[] = {
{ WERR_SETUP_ALREADY_JOINED, "Machine is already joined" },
{ WERR_SETUP_DOMAIN_CONTROLLER, "Machine is a Domain Controller" },
{ WERR_LOGON_FAILURE, "Invalid logon credentials" },
+ { WERR_USER_EXISTS, "User account already exists" },
};
/*****************************************************************************
diff --git a/source3/libsmb/errormap.c b/source3/libsmb/errormap.c
index ce826ae999..4ec30f7e17 100644
--- a/source3/libsmb/errormap.c
+++ b/source3/libsmb/errormap.c
@@ -1502,3 +1502,108 @@ WERROR ntstatus_to_werror(NTSTATUS error)
/* a lame guess */
return W_ERROR(NT_STATUS_V(error) & 0xffff);
}
+
+#if defined(HAVE_GSSAPI)
+/*******************************************************************************
+ Map between gssapi errors and NT status. I made these up :-(. JRA.
+*******************************************************************************/
+
+static const struct {
+ unsigned long gss_err;
+ NTSTATUS ntstatus;
+} gss_to_ntstatus_errormap[] = {
+#if defined(GSS_S_CALL_INACCESSIBLE_READ)
+ {GSS_S_CALL_INACCESSIBLE_READ, NT_STATUS_INVALID_PARAMETER},
+#endif
+#if defined(GSS_S_CALL_INACCESSIBLE_WRITE)
+ {GSS_S_CALL_INACCESSIBLE_WRITE, NT_STATUS_INVALID_PARAMETER},
+#endif
+#if defined(GSS_S_CALL_BAD_STRUCTURE)
+ {GSS_S_CALL_BAD_STRUCTURE, NT_STATUS_INVALID_PARAMETER},
+#endif
+#if defined(GSS_S_BAD_MECH)
+ {GSS_S_BAD_MECH, NT_STATUS_INVALID_PARAMETER},
+#endif
+#if defined(GSS_S_BAD_NAME)
+ {GSS_S_BAD_NAME, NT_STATUS_INVALID_ACCOUNT_NAME},
+#endif
+#if defined(GSS_S_BAD_NAMETYPE)
+ {GSS_S_BAD_NAMETYPE, NT_STATUS_INVALID_PARAMETER},
+#endif
+#if defined(GSS_S_BAD_BINDINGS)
+ {GSS_S_BAD_BINDINGS, NT_STATUS_INVALID_PARAMETER},
+#endif
+#if defined(GSS_S_BAD_STATUS)
+ {GSS_S_BAD_STATUS, NT_STATUS_UNSUCCESSFUL},
+#endif
+#if defined(GSS_S_BAD_SIG)
+ {GSS_S_BAD_SIG, NT_STATUS_ACCESS_DENIED},
+#endif
+#if defined(GSS_S_NO_CRED)
+ {GSS_S_NO_CRED, NT_STATUS_ACCESS_DENIED},
+#endif
+#if defined(GSS_S_NO_CONTEXT)
+ {GSS_S_NO_CONTEXT, NT_STATUS_ACCESS_DENIED},
+#endif
+#if defined(GSS_S_DEFECTIVE_TOKEN)
+ {GSS_S_DEFECTIVE_TOKEN, NT_STATUS_ACCESS_DENIED},
+#endif
+#if defined(GSS_S_DEFECTIVE_CREDENTIAL)
+ {GSS_S_DEFECTIVE_CREDENTIAL, NT_STATUS_ACCESS_DENIED},
+#endif
+#if defined(GSS_S_CREDENTIALS_EXPIRED)
+ {GSS_S_CREDENTIALS_EXPIRED, NT_STATUS_PASSWORD_EXPIRED},
+#endif
+#if defined(GSS_S_CONTEXT_EXPIRED)
+ {GSS_S_CONTEXT_EXPIRED, NT_STATUS_PASSWORD_EXPIRED},
+#endif
+#if defined(GSS_S_BAD_QOP)
+ {GSS_S_BAD_QOP, NT_STATUS_ACCESS_DENIED},
+#endif
+#if defined(GSS_S_UNAUTHORIZED)
+ {GSS_S_UNAUTHORIZED, NT_STATUS_ACCESS_DENIED},
+#endif
+#if defined(GSS_S_UNAVAILABLE)
+ {GSS_S_UNAVAILABLE, NT_STATUS_UNSUCCESSFUL},
+#endif
+#if defined(GSS_S_DUPLICATE_ELEMENT)
+ {GSS_S_DUPLICATE_ELEMENT, NT_STATUS_INVALID_PARAMETER},
+#endif
+#if defined(GSS_S_NAME_NOT_MN)
+ {GSS_S_NAME_NOT_MN, NT_STATUS_INVALID_PARAMETER},
+#endif
+ { 0, NT_STATUS_OK }
+};
+
+/*********************************************************************
+ Map an NT error code from a gssapi error code.
+*********************************************************************/
+
+NTSTATUS map_nt_error_from_gss(uint32 gss_maj, uint32 minor)
+{
+ int i = 0;
+
+ if (gss_maj == GSS_S_COMPLETE) {
+ return NT_STATUS_OK;
+ }
+
+ if (gss_maj == GSS_S_CONTINUE_NEEDED) {
+ return NT_STATUS_MORE_PROCESSING_REQUIRED;
+ }
+
+ if (gss_maj == GSS_S_FAILURE) {
+ return map_nt_error_from_unix((int)minor);
+ }
+
+ /* Look through list */
+ while(gss_to_ntstatus_errormap[i].gss_err != 0) {
+ if (gss_to_ntstatus_errormap[i].gss_err == gss_maj) {
+ return gss_to_ntstatus_errormap[i].ntstatus;
+ }
+ i++;
+ }
+
+ /* Default return */
+ return NT_STATUS_ACCESS_DENIED;
+}
+#endif
diff --git a/source3/libsmb/libsmbclient.c b/source3/libsmb/libsmbclient.c
index 2ff2830256..da8f1e332b 100644
--- a/source3/libsmb/libsmbclient.c
+++ b/source3/libsmb/libsmbclient.c
@@ -6,6 +6,7 @@
Copyright (C) John Terpstra 2000
Copyright (C) Tom Jansen (Ninja ISD) 2002
Copyright (C) Derrell Lipman 2003, 2004
+ Copyright (C) Jeremy Allison 2007, 2008
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
@@ -739,6 +740,12 @@ smbc_server(SMBCCTX *context,
password, strlen(password)+1);
}
+ /*
+ * We don't need to renegotiate encryption
+ * here as the encryption context is not per
+ * tid.
+ */
+
if (! cli_send_tconX(srv->cli, share, "?????",
password, strlen(password)+1)) {
@@ -903,6 +910,30 @@ smbc_server(SMBCCTX *context,
DEBUG(4,(" tconx ok\n"));
+ if (context->internal->_smb_encryption_level) {
+ /* Attempt UNIX smb encryption. */
+ if (!NT_STATUS_IS_OK(cli_force_encryption(c,
+ username_used,
+ password,
+ workgroup))) {
+
+ /*
+ * context->internal->_smb_encryption_level == 1
+ * means don't fail if encryption can't be negotiated,
+ * == 2 means fail if encryption can't be negotiated.
+ */
+
+ DEBUG(4,(" SMB encrypt failed\n"));
+
+ if (context->internal->_smb_encryption_level == 2) {
+ cli_shutdown(c);
+ errno = EPERM;
+ return NULL;
+ }
+ }
+ DEBUG(4,(" SMB encrypt ok\n"));
+ }
+
/*
* Ok, we have got a nice connection
* Let's allocate a server structure.
@@ -1019,6 +1050,30 @@ smbc_attr_server(SMBCCTX *context,
return NULL;
}
+ if (context->internal->_smb_encryption_level) {
+ /* Attempt UNIX smb encryption. */
+ if (!NT_STATUS_IS_OK(cli_force_encryption(ipc_cli,
+ username,
+ password,
+ workgroup))) {
+
+ /*
+ * context->internal->_smb_encryption_level == 1
+ * means don't fail if encryption can't be negotiated,
+ * == 2 means fail if encryption can't be negotiated.
+ */
+
+ DEBUG(4,(" SMB encrypt failed on IPC$\n"));
+
+ if (context->internal->_smb_encryption_level == 2) {
+ cli_shutdown(ipc_cli);
+ errno = EPERM;
+ return NULL;
+ }
+ }
+ DEBUG(4,(" SMB encrypt ok on IPC$\n"));
+ }
+
ipc_srv = SMB_MALLOC_P(SMBCSRV);
if (!ipc_srv) {
errno = ENOMEM;
@@ -6724,6 +6779,7 @@ smbc_option_set(SMBCCTX *context,
bool b;
smbc_get_auth_data_with_context_fn auth_fn;
void *v;
+ const char *s;
} option_value;
va_start(ap, option_name);
@@ -6772,6 +6828,19 @@ smbc_option_set(SMBCCTX *context,
*/
option_value.v = va_arg(ap, void *);
context->internal->_user_data = option_value.v;
+ } else if (strcmp(option_name, "smb_encrypt_level") == 0) {
+ /*
+ * Save an encoded value for encryption level.
+ * 0 = off, 1 = attempt, 2 = required.
+ */
+ option_value.s = va_arg(ap, const char *);
+ if (strcmp(option_value.s, "none") == 0) {
+ context->internal->_smb_encryption_level = 0;
+ } else if (strcmp(option_value.s, "request") == 0) {
+ context->internal->_smb_encryption_level = 1;
+ } else if (strcmp(option_value.s, "require") == 0) {
+ context->internal->_smb_encryption_level = 2;
+ }
}
va_end(ap);
@@ -6821,6 +6890,35 @@ smbc_option_get(SMBCCTX *context,
* with smbc_option_get()
*/
return context->internal->_user_data;
+ } else if (strcmp(option_name, "smb_encrypt_level") == 0) {
+ /*
+ * Return the current smb encrypt negotiate option as a string.
+ */
+ switch (context->internal->_smb_encryption_level) {
+ case 0:
+ return (void *) "none";
+ case 1:
+ return (void *) "request";
+ case 2:
+ return (void *) "require";
+ }
+ } else if (strcmp(option_name, "smb_encrypt_on") == 0) {
+ /*
+ * Return the current smb encrypt status option as a bool.
+ * false = off, true = on. We don't know what server is
+ * being requested, so we only return true if all servers
+ * are using an encrypted connection.
+ */
+ SMBCSRV *s;
+ unsigned int num_servers = 0;
+
+ for (s = context->internal->_servers; s; s = s->next) {
+ num_servers++;
+ if (s->cli->trans_enc_state == NULL) {
+ return (void *)false;
+ }
+ }
+ return (void *) (bool) (num_servers > 0);
}
return NULL;
diff --git a/source3/libsmb/ntlm_check.c b/source3/libsmb/ntlm_check.c
index f8ed044f8a..ae10d7373d 100644
--- a/source3/libsmb/ntlm_check.c
+++ b/source3/libsmb/ntlm_check.c
@@ -182,7 +182,10 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx,
DATA_BLOB *user_sess_key,
DATA_BLOB *lm_sess_key)
{
- static const unsigned char zeros[8] = { 0, };
+ unsigned char zeros[8];
+
+ ZERO_STRUCT(zeros);
+
if (nt_pw == NULL) {
DEBUG(3,("ntlm_password_check: NO NT password stored for user %s.\n",
username));
diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c
index ed08e8102b..35c20ed647 100644
--- a/source3/libsmb/ntlmssp.c
+++ b/source3/libsmb/ntlmssp.c
@@ -823,7 +823,8 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
session_key.data);
DEBUG(10,("ntlmssp_server_auth: Created NTLM session key.\n"));
} else {
- static const uint8 zeros[24] = { 0, };
+ uint8 zeros[24];
+ ZERO_STRUCT(zeros);
session_key = data_blob_talloc(
ntlmssp_state->mem_ctx, NULL, 16);
if (session_key.data == NULL) {
@@ -1066,9 +1067,11 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state,
}
if (!ntlmssp_state->nt_hash || !ntlmssp_state->lm_hash) {
- static const uchar zeros[16] = { 0, };
+ uchar zeros[16];
/* do nothing - blobs are zero length */
+ ZERO_STRUCT(zeros);
+
/* session key is all zeros */
session_key = data_blob_talloc(ntlmssp_state->mem_ctx, zeros, 16);
diff --git a/source3/libsmb/smb_seal.c b/source3/libsmb/smb_seal.c
new file mode 100644
index 0000000000..b5befbf7cd
--- /dev/null
+++ b/source3/libsmb/smb_seal.c
@@ -0,0 +1,497 @@
+/*
+ Unix SMB/CIFS implementation.
+ SMB Transport encryption (sealing) code.
+ Copyright (C) Jeremy Allison 2007.
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+
+/******************************************************************************
+ Pull out the encryption context for this packet. 0 means global context.
+******************************************************************************/
+
+NTSTATUS get_enc_ctx_num(const uint8_t *buf, uint16 *p_enc_ctx_num)
+{
+ if (smb_len(buf) < 8) {
+ return NT_STATUS_INVALID_BUFFER_SIZE;
+ }
+
+ if (buf[4] == 0xFF) {
+ if (buf[5] == 'S' && buf [6] == 'M' && buf[7] == 'B') {
+ /* Not an encrypted buffer. */
+ return NT_STATUS_NOT_FOUND;
+ }
+ if (buf[5] == 'E') {
+ *p_enc_ctx_num = SVAL(buf,6);
+ return NT_STATUS_OK;
+ }
+ }
+ return NT_STATUS_INVALID_NETWORK_RESPONSE;
+}
+
+/******************************************************************************
+ Generic code for client and server.
+ Is encryption turned on ?
+******************************************************************************/
+
+bool common_encryption_on(struct smb_trans_enc_state *es)
+{
+ return ((es != NULL) && es->enc_on);
+}
+
+/******************************************************************************
+ Generic code for client and server.
+ NTLM decrypt an incoming buffer.
+ Abartlett tells me that SSPI puts the signature first before the encrypted
+ output, so cope with the same for compatibility.
+******************************************************************************/
+
+NTSTATUS common_ntlm_decrypt_buffer(NTLMSSP_STATE *ntlmssp_state, char *buf)
+{
+ NTSTATUS status;
+ size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */
+ size_t data_len;
+ char *inbuf;
+ DATA_BLOB sig;
+
+ if (buf_len < 8 + NTLMSSP_SIG_SIZE) {
+ return NT_STATUS_BUFFER_TOO_SMALL;
+ }
+
+ inbuf = (char *)smb_xmemdup(buf, buf_len);
+
+ /* Adjust for the signature. */
+ data_len = buf_len - 8 - NTLMSSP_SIG_SIZE;
+
+ /* Point at the signature. */
+ sig = data_blob_const(inbuf+8, NTLMSSP_SIG_SIZE);
+
+ status = ntlmssp_unseal_packet(ntlmssp_state,
+ (unsigned char *)inbuf + 8 + NTLMSSP_SIG_SIZE, /* 4 byte len + 0xFF 'E' <enc> <ctx> */
+ data_len,
+ (unsigned char *)inbuf + 8 + NTLMSSP_SIG_SIZE,
+ data_len,
+ &sig);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ SAFE_FREE(inbuf);
+ return status;
+ }
+
+ memcpy(buf + 8, inbuf + 8 + NTLMSSP_SIG_SIZE, data_len);
+
+ /* Reset the length and overwrite the header. */
+ smb_setlen(buf,data_len + 4);
+
+ SAFE_FREE(inbuf);
+ return NT_STATUS_OK;
+}
+
+/******************************************************************************
+ Generic code for client and server.
+ NTLM encrypt an outgoing buffer. Return the encrypted pointer in ppbuf_out.
+ Abartlett tells me that SSPI puts the signature first before the encrypted
+ output, so do the same for compatibility.
+******************************************************************************/
+
+NTSTATUS common_ntlm_encrypt_buffer(NTLMSSP_STATE *ntlmssp_state,
+ uint16 enc_ctx_num,
+ char *buf,
+ char **ppbuf_out)
+{
+ NTSTATUS status;
+ char *buf_out;
+ size_t data_len = smb_len(buf) - 4; /* Ignore the 0xFF SMB bytes. */
+ DATA_BLOB sig;
+
+ *ppbuf_out = NULL;
+
+ if (data_len == 0) {
+ return NT_STATUS_BUFFER_TOO_SMALL;
+ }
+
+ /*
+ * We know smb_len can't return a value > 128k, so no int overflow
+ * check needed.
+ */
+
+ buf_out = SMB_XMALLOC_ARRAY(char, 8 + NTLMSSP_SIG_SIZE + data_len);
+
+ /* Copy the data from the original buffer. */
+
+ memcpy(buf_out + 8 + NTLMSSP_SIG_SIZE, buf + 8, data_len);
+
+ smb_set_enclen(buf_out, smb_len(buf) + NTLMSSP_SIG_SIZE, enc_ctx_num);
+
+ sig = data_blob(NULL, NTLMSSP_SIG_SIZE);
+
+ status = ntlmssp_seal_packet(ntlmssp_state,
+ (unsigned char *)buf_out + 8 + NTLMSSP_SIG_SIZE, /* 4 byte len + 0xFF 'S' <enc> <ctx> */
+ data_len,
+ (unsigned char *)buf_out + 8 + NTLMSSP_SIG_SIZE,
+ data_len,
+ &sig);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ data_blob_free(&sig);
+ SAFE_FREE(buf_out);
+ return status;
+ }
+
+ /* First 16 data bytes are signature for SSPI compatibility. */
+ memcpy(buf_out + 8, sig.data, NTLMSSP_SIG_SIZE);
+ *ppbuf_out = buf_out;
+ return NT_STATUS_OK;
+}
+
+/******************************************************************************
+ Generic code for client and server.
+ gss-api decrypt an incoming buffer. We insist that the size of the
+ unwrapped buffer must be smaller or identical to the incoming buffer.
+******************************************************************************/
+
+#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
+static NTSTATUS common_gss_decrypt_buffer(struct smb_tran_enc_state_gss *gss_state, char *buf)
+{
+ gss_ctx_id_t gss_ctx = gss_state->gss_ctx;
+ OM_uint32 ret = 0;
+ OM_uint32 minor = 0;
+ int flags_got = 0;
+ gss_buffer_desc in_buf, out_buf;
+ size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */
+
+ if (buf_len < 8) {
+ return NT_STATUS_BUFFER_TOO_SMALL;
+ }
+
+ in_buf.value = buf + 8;
+ in_buf.length = buf_len - 8;
+
+ ret = gss_unwrap(&minor,
+ gss_ctx,
+ &in_buf,
+ &out_buf,
+ &flags_got, /* did we get sign+seal ? */
+ (gss_qop_t *) NULL);
+
+ if (ret != GSS_S_COMPLETE) {
+ ADS_STATUS adss = ADS_ERROR_GSS(ret, minor);
+ DEBUG(0,("common_gss_encrypt_buffer: gss_unwrap failed. Error %s\n",
+ ads_errstr(adss) ));
+ return map_nt_error_from_gss(ret, minor);
+ }
+
+ if (out_buf.length > in_buf.length) {
+ DEBUG(0,("common_gss_encrypt_buffer: gss_unwrap size (%u) too large (%u) !\n",
+ (unsigned int)out_buf.length,
+ (unsigned int)in_buf.length ));
+ gss_release_buffer(&minor, &out_buf);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ memcpy(buf + 8, out_buf.value, out_buf.length);
+ /* Reset the length and overwrite the header. */
+ smb_setlen(buf, out_buf.length + 4);
+
+ gss_release_buffer(&minor, &out_buf);
+ return NT_STATUS_OK;
+}
+
+/******************************************************************************
+ Generic code for client and server.
+ gss-api encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
+******************************************************************************/
+
+static NTSTATUS common_gss_encrypt_buffer(struct smb_tran_enc_state_gss *gss_state,
+ uint16 enc_ctx_num,
+ char *buf,
+ char **ppbuf_out)
+{
+ gss_ctx_id_t gss_ctx = gss_state->gss_ctx;
+ OM_uint32 ret = 0;
+ OM_uint32 minor = 0;
+ int flags_got = 0;
+ gss_buffer_desc in_buf, out_buf;
+ size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */
+
+ *ppbuf_out = NULL;
+
+ if (buf_len < 8) {
+ return NT_STATUS_BUFFER_TOO_SMALL;
+ }
+
+ in_buf.value = buf + 8;
+ in_buf.length = buf_len - 8;
+
+ ret = gss_wrap(&minor,
+ gss_ctx,
+ true, /* we want sign+seal. */
+ GSS_C_QOP_DEFAULT,
+ &in_buf,
+ &flags_got, /* did we get sign+seal ? */
+ &out_buf);
+
+ if (ret != GSS_S_COMPLETE) {
+ ADS_STATUS adss = ADS_ERROR_GSS(ret, minor);
+ DEBUG(0,("common_gss_encrypt_buffer: gss_wrap failed. Error %s\n",
+ ads_errstr(adss) ));
+ return map_nt_error_from_gss(ret, minor);
+ }
+
+ if (!flags_got) {
+ /* Sign+seal not supported. */
+ gss_release_buffer(&minor, &out_buf);
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+
+ /* Ya see - this is why I *hate* gss-api. I don't
+ * want to have to malloc another buffer of the
+ * same size + 8 bytes just to get a continuous
+ * header + buffer, but gss won't let me pass in
+ * a pre-allocated buffer. Bastards (and you know
+ * who you are....). I might fix this by
+ * going to "encrypt_and_send" passing in a file
+ * descriptor and doing scatter-gather write with
+ * TCP cork on Linux. But I shouldn't have to
+ * bother :-*(. JRA.
+ */
+
+ *ppbuf_out = (char *)SMB_MALLOC(out_buf.length + 8); /* We know this can't wrap. */
+ if (!*ppbuf_out) {
+ gss_release_buffer(&minor, &out_buf);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ memcpy(*ppbuf_out+8, out_buf.value, out_buf.length);
+ smb_set_enclen(*ppbuf_out, out_buf.length + 4, enc_ctx_num);
+
+ gss_release_buffer(&minor, &out_buf);
+ return NT_STATUS_OK;
+}
+#endif
+
+/******************************************************************************
+ Generic code for client and server.
+ Encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
+******************************************************************************/
+
+NTSTATUS common_encrypt_buffer(struct smb_trans_enc_state *es, char *buffer, char **buf_out)
+{
+ if (!common_encryption_on(es)) {
+ /* Not encrypting. */
+ *buf_out = buffer;
+ return NT_STATUS_OK;
+ }
+
+ switch (es->smb_enc_type) {
+ case SMB_TRANS_ENC_NTLM:
+ return common_ntlm_encrypt_buffer(es->s.ntlmssp_state, es->enc_ctx_num, buffer, buf_out);
+#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
+ case SMB_TRANS_ENC_GSS:
+ return common_gss_encrypt_buffer(es->s.gss_state, es->enc_ctx_num, buffer, buf_out);
+#endif
+ default:
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+}
+
+/******************************************************************************
+ Generic code for client and server.
+ Decrypt an incoming SMB buffer. Replaces the data within it.
+ New data must be less than or equal to the current length.
+******************************************************************************/
+
+NTSTATUS common_decrypt_buffer(struct smb_trans_enc_state *es, char *buf)
+{
+ if (!common_encryption_on(es)) {
+ /* Not decrypting. */
+ return NT_STATUS_OK;
+ }
+
+ switch (es->smb_enc_type) {
+ case SMB_TRANS_ENC_NTLM:
+ return common_ntlm_decrypt_buffer(es->s.ntlmssp_state, buf);
+#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
+ case SMB_TRANS_ENC_GSS:
+ return common_gss_decrypt_buffer(es->s.gss_state, buf);
+#endif
+ default:
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+}
+
+#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
+/******************************************************************************
+ Shutdown a gss encryption state.
+******************************************************************************/
+
+static void common_free_gss_state(struct smb_tran_enc_state_gss **pp_gss_state)
+{
+ OM_uint32 minor = 0;
+ struct smb_tran_enc_state_gss *gss_state = *pp_gss_state;
+
+ if (gss_state->creds != GSS_C_NO_CREDENTIAL) {
+ gss_release_cred(&minor, &gss_state->creds);
+ }
+ if (gss_state->gss_ctx != GSS_C_NO_CONTEXT) {
+ gss_delete_sec_context(&minor, &gss_state->gss_ctx, NULL);
+ }
+ SAFE_FREE(*pp_gss_state);
+}
+#endif
+
+/******************************************************************************
+ Shutdown an encryption state.
+******************************************************************************/
+
+void common_free_encryption_state(struct smb_trans_enc_state **pp_es)
+{
+ struct smb_trans_enc_state *es = *pp_es;
+
+ if (es == NULL) {
+ return;
+ }
+
+ if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
+ if (es->s.ntlmssp_state) {
+ ntlmssp_end(&es->s.ntlmssp_state);
+ }
+ }
+#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
+ if (es->smb_enc_type == SMB_TRANS_ENC_GSS) {
+ /* Free the gss context handle. */
+ if (es->s.gss_state) {
+ common_free_gss_state(&es->s.gss_state);
+ }
+ }
+#endif
+ SAFE_FREE(es);
+ *pp_es = NULL;
+}
+
+/******************************************************************************
+ Free an encryption-allocated buffer.
+******************************************************************************/
+
+void common_free_enc_buffer(struct smb_trans_enc_state *es, char *buf)
+{
+ if (!common_encryption_on(es)) {
+ return;
+ }
+
+ if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
+ SAFE_FREE(buf);
+ return;
+ }
+
+#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
+ if (es->smb_enc_type == SMB_TRANS_ENC_GSS) {
+ OM_uint32 min;
+ gss_buffer_desc rel_buf;
+ rel_buf.value = buf;
+ rel_buf.length = smb_len(buf) + 4;
+ gss_release_buffer(&min, &rel_buf);
+ }
+#endif
+}
+
+/******************************************************************************
+ Client side encryption.
+******************************************************************************/
+
+/******************************************************************************
+ Is client encryption on ?
+******************************************************************************/
+
+bool cli_encryption_on(struct cli_state *cli)
+{
+ /* If we supported multiple encrytion contexts
+ * here we'd look up based on tid.
+ */
+ return common_encryption_on(cli->trans_enc_state);
+}
+
+/******************************************************************************
+ Shutdown a client encryption state.
+******************************************************************************/
+
+void cli_free_encryption_context(struct cli_state *cli)
+{
+ common_free_encryption_state(&cli->trans_enc_state);
+}
+
+/******************************************************************************
+ Free an encryption-allocated buffer.
+******************************************************************************/
+
+void cli_free_enc_buffer(struct cli_state *cli, char *buf)
+{
+ /* We know this is an smb buffer, and we
+ * didn't malloc, only copy, for a keepalive,
+ * so ignore non-session messages. */
+
+ if(CVAL(buf,0)) {
+ return;
+ }
+
+ /* If we supported multiple encrytion contexts
+ * here we'd look up based on tid.
+ */
+ common_free_enc_buffer(cli->trans_enc_state, buf);
+}
+
+/******************************************************************************
+ Decrypt an incoming buffer.
+******************************************************************************/
+
+NTSTATUS cli_decrypt_message(struct cli_state *cli)
+{
+ NTSTATUS status;
+ uint16 enc_ctx_num;
+
+ /* Ignore non-session messages. */
+ if(CVAL(cli->inbuf,0)) {
+ return NT_STATUS_OK;
+ }
+
+ status = get_enc_ctx_num((const uint8_t *)cli->inbuf, &enc_ctx_num);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ if (enc_ctx_num != cli->trans_enc_state->enc_ctx_num) {
+ return NT_STATUS_INVALID_HANDLE;
+ }
+
+ return common_decrypt_buffer(cli->trans_enc_state, cli->inbuf);
+}
+
+/******************************************************************************
+ Encrypt an outgoing buffer. Return the encrypted pointer in buf_out.
+******************************************************************************/
+
+NTSTATUS cli_encrypt_message(struct cli_state *cli, char **buf_out)
+{
+ /* Ignore non-session messages. */
+ if(CVAL(cli->outbuf,0)) {
+ return NT_STATUS_OK;
+ }
+
+ /* If we supported multiple encrytion contexts
+ * here we'd look up based on tid.
+ */
+ return common_encrypt_buffer(cli->trans_enc_state, cli->outbuf, buf_out);
+}
diff --git a/source3/libsmb/smb_signing.c b/source3/libsmb/smb_signing.c
index d5cbe3b125..f03c21bd0e 100644
--- a/source3/libsmb/smb_signing.c
+++ b/source3/libsmb/smb_signing.c
@@ -745,8 +745,8 @@ bool srv_oplock_set_signing(bool onoff)
bool srv_check_sign_mac(const char *inbuf, bool must_be_ok)
{
- /* Check if it's a session keepalive. */
- if(CVAL(inbuf,0) == SMBkeepalive) {
+ /* Check if it's a non-session message. */
+ if(CVAL(inbuf,0)) {
return True;
}
@@ -759,8 +759,8 @@ bool srv_check_sign_mac(const char *inbuf, bool must_be_ok)
void srv_calculate_sign_mac(char *outbuf)
{
- /* Check if it's a session keepalive. */
- if(CVAL(outbuf,0) == SMBkeepalive) {
+ /* Check if it's a non-session message. */
+ if(CVAL(outbuf,0)) {
return;
}
diff --git a/source3/libsmb/smbencrypt.c b/source3/libsmb/smbencrypt.c
index 9e37d1d6cf..d7f6f604f7 100644
--- a/source3/libsmb/smbencrypt.c
+++ b/source3/libsmb/smbencrypt.c
@@ -704,16 +704,22 @@ char *decrypt_trustdom_secret(const char *pass, DATA_BLOB *data_in)
void encode_wkssvc_join_password_buffer(TALLOC_CTX *mem_ctx,
const char *pwd,
DATA_BLOB *session_key,
- struct wkssvc_PasswordBuffer *pwd_buf)
+ struct wkssvc_PasswordBuffer **pwd_buf)
{
uint8_t buffer[516];
struct MD5Context ctx;
-
- DATA_BLOB confounded_session_key = data_blob_talloc(mem_ctx, NULL, 16);
-
+ struct wkssvc_PasswordBuffer *my_pwd_buf = NULL;
+ DATA_BLOB confounded_session_key;
int confounder_len = 8;
uint8_t confounder[8];
+ my_pwd_buf = talloc_zero(mem_ctx, struct wkssvc_PasswordBuffer);
+ if (!my_pwd_buf) {
+ return;
+ }
+
+ confounded_session_key = data_blob_talloc(mem_ctx, NULL, 16);
+
encode_pw_buffer(buffer, pwd, STR_UNICODE);
generate_random_buffer((uint8_t *)confounder, confounder_len);
@@ -725,10 +731,12 @@ void encode_wkssvc_join_password_buffer(TALLOC_CTX *mem_ctx,
SamOEMhashBlob(buffer, 516, &confounded_session_key);
- memcpy(&pwd_buf->data[0], confounder, confounder_len);
- memcpy(&pwd_buf->data[8], buffer, 516);
+ memcpy(&my_pwd_buf->data[0], confounder, confounder_len);
+ memcpy(&my_pwd_buf->data[8], buffer, 516);
data_blob_free(&confounded_session_key);
+
+ *pwd_buf = my_pwd_buf;
}
WERROR decode_wkssvc_join_password_buffer(TALLOC_CTX *mem_ctx,