summaryrefslogtreecommitdiff
path: root/source/libsmb
diff options
context:
space:
mode:
Diffstat (limited to 'source/libsmb')
-rw-r--r--source/libsmb/asn1.c6
-rw-r--r--source/libsmb/cliconnect.c132
-rw-r--r--source/libsmb/clientgen.c32
-rw-r--r--source/libsmb/clierror.c3
-rw-r--r--source/libsmb/clikrb5.c41
-rw-r--r--source/libsmb/clilist.c45
-rw-r--r--source/libsmb/cliprint.c17
-rw-r--r--source/libsmb/clirap.c10
-rw-r--r--source/libsmb/clirap2.c63
-rw-r--r--source/libsmb/clireadwrite.c2
-rw-r--r--source/libsmb/clisecdesc.c4
-rw-r--r--source/libsmb/clispnego.c11
-rw-r--r--source/libsmb/clitrans.c96
-rw-r--r--source/libsmb/errormap.c1
-rw-r--r--source/libsmb/namequery_dc.c16
-rw-r--r--source/libsmb/nmblib.c14
-rw-r--r--source/libsmb/ntlmssp.c75
-rw-r--r--source/libsmb/ntlmssp_parse.c5
-rw-r--r--source/libsmb/ntlmssp_sign.c24
-rw-r--r--source/libsmb/smb_signing.c760
-rw-r--r--source/libsmb/smbencrypt.c4
-rw-r--r--source/libsmb/spnego.c343
-rw-r--r--source/libsmb/trustdom_cache.c2
-rw-r--r--source/libsmb/trusts_util.c2
24 files changed, 1381 insertions, 327 deletions
diff --git a/source/libsmb/asn1.c b/source/libsmb/asn1.c
index 09d4fbb6c9a..576491dd3bc 100644
--- a/source/libsmb/asn1.c
+++ b/source/libsmb/asn1.c
@@ -322,9 +322,9 @@ BOOL asn1_read_OID(ASN1_DATA *data, char **OID)
asn1_read_uint8(data, &b);
oid[0] = 0;
- snprintf(el, sizeof(el), "%u", b/40);
+ fstr_sprintf(el, "%u", b/40);
pstrcat(oid, el);
- snprintf(el, sizeof(el), " %u", b%40);
+ fstr_sprintf(el, " %u", b%40);
pstrcat(oid, el);
while (asn1_tag_remaining(data) > 0) {
@@ -333,7 +333,7 @@ BOOL asn1_read_OID(ASN1_DATA *data, char **OID)
asn1_read_uint8(data, &b);
v = (v<<7) | (b&0x7f);
} while (!data->has_error && b & 0x80);
- snprintf(el, sizeof(el), " %u", v);
+ fstr_sprintf(el, " %u", v);
pstrcat(oid, el);
}
diff --git a/source/libsmb/cliconnect.c b/source/libsmb/cliconnect.c
index 0dcc9e28459..010aa4d1bb4 100644
--- a/source/libsmb/cliconnect.c
+++ b/source/libsmb/cliconnect.c
@@ -131,55 +131,6 @@ static uint32 cli_session_setup_capabilities(struct cli_state *cli)
}
/****************************************************************************
- Do a NT1 guest session setup.
-****************************************************************************/
-
-static BOOL cli_session_setup_guest(struct cli_state *cli)
-{
- char *p;
- uint32 capabilities = cli_session_setup_capabilities(cli);
-
- set_message(cli->outbuf,13,0,True);
- SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
- cli_setup_packet(cli);
-
- SCVAL(cli->outbuf,smb_vwv0,0xFF);
- SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
- SSVAL(cli->outbuf,smb_vwv3,2);
- SSVAL(cli->outbuf,smb_vwv4,cli->pid);
- SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
- SSVAL(cli->outbuf,smb_vwv7,0);
- SSVAL(cli->outbuf,smb_vwv8,0);
- SIVAL(cli->outbuf,smb_vwv11,capabilities);
- p = smb_buf(cli->outbuf);
- p += clistr_push(cli, p, "", -1, STR_TERMINATE); /* username */
- p += clistr_push(cli, p, "", -1, STR_TERMINATE); /* workgroup */
- p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
- p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
- cli_setup_bcc(cli, p);
-
- cli_send_smb(cli);
- if (!cli_receive_smb(cli))
- return False;
-
- show_msg(cli->inbuf);
-
- if (cli_is_error(cli))
- return False;
-
- cli->vuid = SVAL(cli->inbuf,smb_uid);
-
- p = smb_buf(cli->inbuf);
- p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
- p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
- p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);
-
- fstrcpy(cli->user_name, "");
-
- return True;
-}
-
-/****************************************************************************
Do a NT1 plaintext session setup.
****************************************************************************/
@@ -190,7 +141,7 @@ static BOOL cli_session_setup_plaintext(struct cli_state *cli, const char *user,
char *p;
fstring lanman;
- snprintf( lanman, sizeof(lanman), "Samba %s", VERSION );
+ fstr_sprintf( lanman, "Samba %s", VERSION );
set_message(cli->outbuf,13,0,True);
SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
@@ -267,8 +218,10 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user,
BOOL ret = False;
char *p;
- if (passlen != 24) {
- if (lp_client_ntlmv2_auth()) {
+ if (passlen == 0) {
+ /* do nothing - guest login */
+ } else if (passlen != 24) {
+ if ((cli->capabilities & CAP_EXTENDED_SECURITY) && lp_client_ntlmv2_auth()) {
DATA_BLOB server_chal;
DATA_BLOB names_blob;
server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8));
@@ -472,6 +425,7 @@ static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
/****************************************************************************
Use in-memory credentials cache
****************************************************************************/
+
static void use_in_memory_ccache(void) {
setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
}
@@ -483,18 +437,23 @@ static void use_in_memory_ccache(void) {
static BOOL cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup)
{
DATA_BLOB blob2, negTokenTarg;
-
+ unsigned char session_key_krb5[16];
+ DATA_BLOB null_blob = data_blob(NULL, 0);
+
DEBUG(2,("Doing kerberos session setup\n"));
/* generate the encapsulated kerberos5 ticket */
- negTokenTarg = spnego_gen_negTokenTarg(principal, 0);
+ negTokenTarg = spnego_gen_negTokenTarg(principal, 0, session_key_krb5);
- if (!negTokenTarg.data) return False;
+ if (!negTokenTarg.data)
+ return False;
#if 0
file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length);
#endif
+ cli_simple_set_signing(cli, session_key_krb5, null_blob);
+
blob2 = cli_session_setup_blob(cli, negTokenTarg);
/* we don't need this blob for kerberos */
@@ -551,7 +510,7 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
blob_in, &blob_out);
data_blob_free(&blob_in);
if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- DATA_BLOB null = data_blob(NULL, 0);
+ DATA_BLOB null_blob = data_blob(NULL, 0);
if (turn == 1) {
/* and wrap it in a SPNEGO wrapper */
msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out);
@@ -562,7 +521,7 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
cli_simple_set_signing(cli,
ntlmssp_state->session_key.data,
- null);
+ null_blob);
/* now send that blob on its way */
if (!cli_session_setup_blob_send(cli, msg1)) {
@@ -604,6 +563,7 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
} while (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED));
if (NT_STATUS_IS_OK(nt_status)) {
+ fstrcpy(cli->server_domain, ntlmssp_state->server_domain);
set_cli_session_key(cli, ntlmssp_state->session_key);
}
@@ -630,7 +590,7 @@ static BOOL cli_session_setup_spnego(struct cli_state *cli, const char *user,
BOOL got_kerberos_mechanism = False;
DATA_BLOB blob;
- DEBUG(2,("Doing spnego session setup (blob length=%d)\n", cli->secblob.length));
+ DEBUG(2,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
/* the server might not even do spnego */
if (cli->secblob.length <= 16) {
@@ -671,7 +631,7 @@ static BOOL cli_session_setup_spnego(struct cli_state *cli, const char *user,
* and do not store results */
if (got_kerberos_mechanism && cli->use_kerberos) {
- if (*pass) {
+ if (pass && *pass) {
int ret;
use_in_memory_ccache();
@@ -744,12 +704,6 @@ BOOL cli_session_setup(struct cli_state *cli,
return cli_session_setup_lanman2(cli, user, pass, passlen, workgroup);
}
- /* if no user is supplied then we have to do an anonymous connection.
- passwords are ignored */
-
- if (!user || !*user)
- return cli_session_setup_guest(cli);
-
/* if the server is share level then send a plaintext null
password at this point. The password is sent in the tree
connect */
@@ -757,6 +711,17 @@ BOOL cli_session_setup(struct cli_state *cli,
if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
return cli_session_setup_plaintext(cli, user, "", workgroup);
+ /* if no user is supplied then we have to do an anonymous connection.
+ passwords are ignored */
+
+ if (!user || !*user) {
+ user = "";
+ pass = NULL;
+ ntpass = NULL;
+ passlen = 0;
+ ntpasslen = 0;
+ }
+
/* if the server doesn't support encryption then we have to use
plaintext. The second password is ignored */
@@ -989,6 +954,11 @@ BOOL cli_negprot(struct cli_state *cli)
cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;
+ if ((cli->protocol < PROTOCOL_NT1) && cli->sign_info.mandatory_signing) {
+ DEBUG(1,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
+ return False;
+ }
+
if (cli->protocol >= PROTOCOL_NT1) {
/* NT protocol */
cli->sec_mode = CVAL(cli->inbuf,smb_vwv1);
@@ -1013,22 +983,27 @@ BOOL cli_negprot(struct cli_state *cli)
smb_buflen(cli->inbuf)-8, STR_UNICODE|STR_NOALIGN);
}
- if ((cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED)) {
- /* Fail if signing is mandatory and we don't want to support it. */
- if (!lp_client_signing()) {
+ /*
+ * As signing is slow we only turn it on if either the client or
+ * the server require it. JRA.
+ */
+
+ if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
+ /* Fail if server says signing is mandatory and we don't want to support it. */
+ if (!cli->sign_info.allow_smb_signing) {
DEBUG(1,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
return False;
}
cli->sign_info.negotiated_smb_signing = True;
- }
-
- if ((cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) && cli->sign_info.allow_smb_signing)
+ cli->sign_info.mandatory_signing = True;
+ } else if (cli->sign_info.mandatory_signing && cli->sign_info.allow_smb_signing) {
+ /* Fail if client says signing is mandatory and the server doesn't support it. */
+ if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
+ DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
+ return False;
+ }
cli->sign_info.negotiated_smb_signing = True;
-
- /* Fail if signing is mandatory and the server doesn't support it. */
- if (cli->sign_info.mandatory_signing && !(cli->sign_info.negotiated_smb_signing)) {
- DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
- return False;
+ cli->sign_info.mandatory_signing = True;
}
} else if (cli->protocol >= PROTOCOL_LANMAN1) {
@@ -1248,6 +1223,7 @@ NTSTATUS cli_full_connection(struct cli_state **output_cli,
const char *service, const char *service_type,
const char *user, const char *domain,
const char *password, int flags,
+ int signing_state,
BOOL *retry)
{
struct ntuser_creds creds;
@@ -1310,6 +1286,8 @@ again:
return NT_STATUS_UNSUCCESSFUL;
}
+ cli_setup_signing_state(cli, signing_state);
+
if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
cli->use_spnego = False;
else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
@@ -1480,7 +1458,7 @@ struct cli_state *get_ipc_connect(char *server, struct in_addr *server_ip,
nt_status = cli_full_connection(&cli, myname, server, server_ip, 0, "IPC$", "IPC",
user_info->username, lp_workgroup(), user_info->password,
- CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK, NULL);
+ CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK, Undefined, NULL);
if (NT_STATUS_IS_OK(nt_status)) {
return cli;
diff --git a/source/libsmb/clientgen.c b/source/libsmb/clientgen.c
index cd9edb1cc93..5838f301c49 100644
--- a/source/libsmb/clientgen.c
+++ b/source/libsmb/clientgen.c
@@ -157,6 +157,10 @@ BOOL cli_send_smb(struct cli_state *cli)
}
nwritten += ret;
}
+ /* Increment the mid so we can tell between responses. */
+ cli->mid++;
+ if (!cli->mid)
+ cli->mid++;
return True;
}
@@ -209,6 +213,27 @@ void cli_init_creds(struct cli_state *cli, const struct ntuser_creds *usr)
}
/****************************************************************************
+ Set the signing state (used from the command line).
+****************************************************************************/
+
+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;
+ return;
+ }
+
+ cli->sign_info.allow_smb_signing = True;
+
+ if (signing_state == Required)
+ cli->sign_info.mandatory_signing = True;
+}
+
+/****************************************************************************
Initialise a client structure.
****************************************************************************/
@@ -314,7 +339,9 @@ void cli_nt_session_close(struct cli_state *cli)
ntlmssp_client_end(&cli->ntlmssp_pipe_state);
}
- cli_close(cli, cli->nt_pipe_fnum);
+ if (cli->nt_pipe_fnum != 0)
+ cli_close(cli, cli->nt_pipe_fnum);
+
cli->nt_pipe_fnum = 0;
cli->pipe_idx = -1;
}
@@ -337,6 +364,9 @@ void cli_nt_netlogon_netsec_session_close(struct cli_state *cli)
void cli_close_connection(struct cli_state *cli)
{
+ if ( !cli )
+ return;
+
cli_nt_session_close(cli);
cli_nt_netlogon_netsec_session_close(cli);
diff --git a/source/libsmb/clierror.c b/source/libsmb/clierror.c
index 656671823c4..c27e1955e20 100644
--- a/source/libsmb/clierror.c
+++ b/source/libsmb/clierror.c
@@ -371,6 +371,9 @@ BOOL cli_is_error(struct cli_state *cli)
{
uint32 flgs2 = SVAL(cli->inbuf,smb_flg2), rcls = 0;
+ if (cli->fd == -1 && cli->smb_rw_error != 0)
+ return True;
+
if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) {
/* Return error is error bits are set */
rcls = IVAL(cli->inbuf, smb_rcls);
diff --git a/source/libsmb/clikrb5.c b/source/libsmb/clikrb5.c
index ba8ba11368a..1fccc04a013 100644
--- a/source/libsmb/clikrb5.c
+++ b/source/libsmb/clikrb5.c
@@ -74,7 +74,7 @@
{
pkaddr->addrtype = ADDRTYPE_INET;
pkaddr->length = sizeof(((struct sockaddr_in *)paddr)->sin_addr);
- pkaddr->contents = (char *)&(((struct sockaddr_in *)paddr)->sin_addr);
+ pkaddr->contents = (krb5_octet *)&(((struct sockaddr_in *)paddr)->sin_addr);
}
#else
__ERROR__XX__UNKNOWN_ADDRTYPE
@@ -97,7 +97,9 @@
return ret;
}
krb5_use_enctype(context, &eblock, enctype);
- return krb5_string_to_key(context, &eblock, key, password, &salt);
+ ret = krb5_string_to_key(context, &eblock, key, password, &salt);
+ SAFE_FREE(salt.data);
+ return ret;
}
#elif defined(HAVE_KRB5_GET_PW_SALT) && defined(HAVE_KRB5_STRING_TO_KEY_SALT)
int create_kerberos_key_from_string(krb5_context context,
@@ -305,7 +307,7 @@ cleanup_princ:
/*
get a kerberos5 ticket for the given service
*/
-DATA_BLOB cli_krb5_get_ticket(const char *principal, time_t time_offset)
+DATA_BLOB cli_krb5_get_ticket(const char *principal, time_t time_offset, unsigned char session_key_krb5[16])
{
krb5_error_code retval;
krb5_data packet;
@@ -345,13 +347,15 @@ DATA_BLOB cli_krb5_get_ticket(const char *principal, time_t time_offset)
}
if ((retval = ads_krb5_mk_req(context,
- &auth_context,
- 0,
- principal,
- ccdef, &packet))) {
+ &auth_context,
+ AP_OPTS_USE_SUBKEY,
+ principal,
+ ccdef, &packet))) {
goto failed;
}
+ get_krb5_smb_session_key(context, auth_context, session_key_krb5, False);
+
ret = data_blob(packet.data, packet.length);
/* Hmm, heimdal dooesn't have this - what's the correct call? */
/* krb5_free_data_contents(context, &packet); */
@@ -365,26 +369,29 @@ failed:
return data_blob(NULL, 0);
}
- BOOL get_krb5_smb_session_key(krb5_context context, krb5_auth_context auth_context, uint8 session_key[16])
+ BOOL get_krb5_smb_session_key(krb5_context context, krb5_auth_context auth_context, uint8 session_key[16], BOOL remote)
{
-#ifdef ENCTYPE_ARCFOUR_HMAC
krb5_keyblock *skey;
-#endif
+ krb5_error_code err;
BOOL ret = False;
memset(session_key, 0, 16);
-#ifdef ENCTYPE_ARCFOUR_HMAC
- if (krb5_auth_con_getremotesubkey(context, auth_context, &skey) == 0 && skey != NULL) {
- if (KRB5_KEY_TYPE(skey) ==
- ENCTYPE_ARCFOUR_HMAC
- && KRB5_KEY_LENGTH(skey) == 16) {
+ if (remote)
+ err = krb5_auth_con_getremotesubkey(context, auth_context, &skey);
+ else
+ err = krb5_auth_con_getlocalsubkey(context, auth_context, &skey);
+ if (err == 0 && skey != NULL) {
+ DEBUG(10, ("Got KRB5 session key of length %d\n", KRB5_KEY_LENGTH(skey)));
+ if (KRB5_KEY_LENGTH(skey) == 16) {
memcpy(session_key, KRB5_KEY_DATA(skey), KRB5_KEY_LENGTH(skey));
+ dump_data_pw("KRB5 Session Key:\n", session_key, 16);
ret = True;
}
krb5_free_keyblock(context, skey);
+ } else {
+ DEBUG(10, ("KRB5 error getting session key %d\n", err));
}
-#endif /* ENCTYPE_ARCFOUR_HMAC */
return ret;
}
@@ -403,7 +410,7 @@ failed:
#else /* HAVE_KRB5 */
/* this saves a few linking headaches */
-DATA_BLOB cli_krb5_get_ticket(const char *principal, time_t time_offset)
+DATA_BLOB cli_krb5_get_ticket(const char *principal, time_t time_offset, unsigned char session_key_krb5[16])
{
DEBUG(0,("NO KERBEROS SUPPORT\n"));
return data_blob(NULL, 0);
diff --git a/source/libsmb/clilist.c b/source/libsmb/clilist.c
index 5bd1283ab7b..7822987ada8 100644
--- a/source/libsmb/clilist.c
+++ b/source/libsmb/clilist.c
@@ -101,13 +101,20 @@ static int interpret_long_filename(struct cli_state *cli,
cheap to calculate, I suppose, as
no DST tables will be needed */
- finfo->ctime = interpret_long_date(p); p += 8;
- finfo->atime = interpret_long_date(p); p += 8;
- finfo->mtime = interpret_long_date(p); p += 8; p += 8;
- finfo->size = IVAL2_TO_SMB_BIG_UINT(p,0); p += 8;
+ finfo->ctime = interpret_long_date(p);
+ p += 8;
+ finfo->atime = interpret_long_date(p);
+ p += 8;
+ finfo->mtime = interpret_long_date(p);
+ p += 8;
+ p += 8;
+ finfo->size = IVAL2_TO_SMB_BIG_UINT(p,0);
+ p += 8;
p += 8; /* alloc size */
- finfo->mode = CVAL(p,0); p += 4;
- namelen = IVAL(p,0); p += 4;
+ finfo->mode = CVAL(p,0);
+ p += 4;
+ namelen = IVAL(p,0);
+ p += 4;
p += 4; /* EA size */
slen = SVAL(p, 0);
p += 2;
@@ -138,7 +145,11 @@ static int interpret_long_filename(struct cli_state *cli,
int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
void (*fn)(file_info *, const char *, void *), void *state)
{
+#if 0
+ int max_matches = 1366; /* Match W2k - was 512. */
+#else
int max_matches = 512;
+#endif
int info_level;
char *p, *p2;
pstring mask;
@@ -200,7 +211,12 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
&setup, 1, 0, /* setup, length, max */
param, param_len, 10, /* param, length, max */
NULL, 0,
- cli->max_xmit /* data, length, max */
+#if 0
+ /* w2k value. */
+ MIN(16384,cli->max_xmit) /* data, length, max. */
+#else
+ cli->max_xmit /* data, length, max. */
+#endif
)) {
break;
}
@@ -214,7 +230,8 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
uint8 eclass;
uint32 ecode;
cli_dos_error(cli, &eclass, &ecode);
- if (eclass != ERRSRV || ecode != ERRerror) break;
+ if (eclass != ERRSRV || ecode != ERRerror)
+ break;
msleep(100);
continue;
}
@@ -222,7 +239,8 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
if (cli_is_error(cli) || !rdata || !rparam)
break;
- if (total_received == -1) total_received = 0;
+ if (total_received == -1)
+ total_received = 0;
/* parse out some important return info */
p = rparam;
@@ -245,8 +263,7 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
/* we might need the lastname for continuations */
if (ff_lastname > 0) {
- switch(info_level)
- {
+ switch(info_level) {
case 260:
clistr_pull(cli, mask, p+ff_lastname,
sizeof(mask),
@@ -270,8 +287,9 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
if (!tdl) {
DEBUG(0,("cli_list_new: Failed to expand dirlist\n"));
break;
+ } else {
+ dirlist = tdl;
}
- else dirlist = tdl;
/* put in a length for the last entry, to ensure we can chain entries
into the next packet */
@@ -291,7 +309,8 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
DEBUG(3,("received %d entries (eos=%d)\n",
ff_searchcount,ff_eos));
- if (ff_searchcount > 0) loop_count = 0;
+ if (ff_searchcount > 0)
+ loop_count = 0;
First = False;
}
diff --git a/source/libsmb/cliprint.c b/source/libsmb/cliprint.c
index bfa33bc5146..2fb0e59acac 100644
--- a/source/libsmb/cliprint.c
+++ b/source/libsmb/cliprint.c
@@ -55,7 +55,7 @@ int cli_print_queue(struct cli_state *cli,
char *rparam = NULL;
char *rdata = NULL;
char *p;
- int rdrcnt, rprcnt;
+ unsigned int rdrcnt, rprcnt;
pstring param;
int result_code=0;
int i = -1;
@@ -65,16 +65,16 @@ int cli_print_queue(struct cli_state *cli,
p = param;
SSVAL(p,0,76); /* API function number 76 (DosPrintJobEnum) */
p += 2;
- pstrcpy(p,"zWrLeh"); /* parameter description? */
+ pstrcpy_base(p,"zWrLeh", param); /* parameter description? */
p = skip_string(p,1);
- pstrcpy(p,"WWzWWDDzz"); /* returned data format */
+ pstrcpy_base(p,"WWzWWDDzz", param); /* returned data format */
p = skip_string(p,1);
- pstrcpy(p,cli->share); /* name of queue */
+ pstrcpy_base(p,cli->share, param); /* name of queue */
p = skip_string(p,1);
SSVAL(p,0,2); /* API function level 2, PRJINFO_2 data structure */
SSVAL(p,2,1000); /* size of bytes of returned data buffer */
p += 4;
- pstrcpy(p,""); /* subformat */
+ pstrcpy_base(p,"", param); /* subformat */
p = skip_string(p,1);
DEBUG(4,("doing cli_print_queue for %s\n", cli->share));
@@ -125,7 +125,8 @@ int cli_printjob_del(struct cli_state *cli, int job)
char *rparam = NULL;
char *rdata = NULL;
char *p;
- int rdrcnt,rprcnt, ret = -1;
+ unsigned int rdrcnt,rprcnt;
+ int ret = -1;
pstring param;
memset(param,'\0',sizeof(param));
@@ -133,9 +134,9 @@ int cli_printjob_del(struct cli_state *cli, int job)
p = param;
SSVAL(p,0,81); /* DosPrintJobDel() */
p += 2;
- pstrcpy(p,"W");
+ pstrcpy_base(p,"W", param);
p = skip_string(p,1);
- pstrcpy(p,"");
+ pstrcpy_base(p,"", param);
p = skip_string(p,1);
SSVAL(p,0,job);
p += 2;
diff --git a/source/libsmb/clirap.c b/source/libsmb/clirap.c
index a307ac6ccf8..79ad38fc8c3 100644
--- a/source/libsmb/clirap.c
+++ b/source/libsmb/clirap.c
@@ -76,7 +76,7 @@ BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation)
char *rparam = NULL;
char *rdata = NULL;
char *p;
- int rdrcnt,rprcnt;
+ unsigned int rdrcnt,rprcnt;
pstring param;
memset(param, 0, sizeof(param));
@@ -137,7 +137,7 @@ int cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, co
char *rparam = NULL;
char *rdata = NULL;
char *p;
- int rdrcnt,rprcnt;
+ unsigned int rdrcnt,rprcnt;
pstring param;
int count = -1;
@@ -211,7 +211,7 @@ BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
{
char *rparam = NULL;
char *rdata = NULL;
- int rdrcnt,rprcnt;
+ unsigned int rdrcnt,rprcnt;
char *p;
pstring param;
int uLevel = 1;
@@ -256,7 +256,7 @@ BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
const char *cmnt = comment_offset?(rdata+comment_offset):"";
pstring s1, s2;
- if (comment_offset < 0 || comment_offset > rdrcnt) continue;
+ if (comment_offset < 0 || comment_offset > (int)rdrcnt) continue;
stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
@@ -290,7 +290,7 @@ BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char
unsigned int param_len = 0;
char *rparam = NULL;
char *rdata = NULL;
- int rprcnt, rdrcnt;
+ unsigned int rprcnt, rdrcnt;
pstring dos_new_password;
if (strlen(user) >= sizeof(fstring)-1) {
diff --git a/source/libsmb/clirap2.c b/source/libsmb/clirap2.c
index 669b33860da..12a3d63aff3 100644
--- a/source/libsmb/clirap2.c
+++ b/source/libsmb/clirap2.c
@@ -153,7 +153,8 @@ int cli_NetGroupDelete(struct cli_state *cli, const char *group_name )
char *rparam = NULL;
char *rdata = NULL;
char *p;
- int rdrcnt,rprcnt, res;
+ unsigned int rdrcnt,rprcnt;
+ int res;
char param[WORDSIZE /* api number */
+sizeof(RAP_NetGroupDel_REQ) /* parm string */
+1 /* no ret string */
@@ -204,7 +205,8 @@ int cli_NetGroupAdd(struct cli_state *cli, RAP_GROUP_INFO_1 * grinfo )
char *rparam = NULL;
char *rdata = NULL;
char *p;
- int rdrcnt,rprcnt,res;
+ unsigned int rdrcnt,rprcnt;
+ int res;
char param[WORDSIZE /* api number */
+sizeof(RAP_NetGroupAdd_REQ) /* req string */
+sizeof(RAP_GROUP_INFO_L1) /* return string */
@@ -272,7 +274,7 @@ int cli_RNetGroupEnum(struct cli_state *cli, void (*fn)(const char *, const char
char *p;
char *rparam = NULL;
char *rdata = NULL;
- int rprcnt, rdrcnt;
+ unsigned int rprcnt, rdrcnt;
int res = -1;
@@ -332,7 +334,8 @@ int cli_NetGroupDelUser(struct cli_state * cli, const char *group_name, const ch
char *rparam = NULL;
char *rdata = NULL;
char *p;
- int rdrcnt,rprcnt,res;
+ unsigned int rdrcnt,rprcnt;
+ int res;
char param[WORDSIZE /* api number */
+sizeof(RAP_NetGroupDelUser_REQ) /* parm string */
+1 /* no ret string */
@@ -390,7 +393,8 @@ int cli_NetGroupAddUser(struct cli_state * cli, const char *group_name, const ch
char *rparam = NULL;
char *rdata = NULL;
char *p;
- int rdrcnt,rprcnt,res;
+ unsigned int rdrcnt,rprcnt;
+ int res;
char param[WORDSIZE /* api number */
+sizeof(RAP_NetGroupAddUser_REQ) /* parm string */
+1 /* no ret string */
@@ -446,7 +450,7 @@ int cli_NetGroupGetUsers(struct cli_state * cli, const char *group_name, void (*
char *rparam = NULL;
char *rdata = NULL;
char *p;
- int rdrcnt,rprcnt;
+ unsigned int rdrcnt,rprcnt;
int res = -1;
char param[WORDSIZE /* api number */
+sizeof(RAP_NetGroupGetUsers_REQ)/* parm string */
@@ -501,7 +505,7 @@ int cli_NetUserGetGroups(struct cli_state * cli, const char *user_name, void (*f
char *rparam = NULL;
char *rdata = NULL;
char *p;
- int rdrcnt,rprcnt;
+ unsigned int rdrcnt,rprcnt;
int res = -1;
char param[WORDSIZE /* api number */
+sizeof(RAP_NetUserGetGroups_REQ)/* parm string */
@@ -560,7 +564,8 @@ int cli_NetUserDelete(struct cli_state *cli, const char * user_name )
char *rparam = NULL;
char *rdata = NULL;
char *p;
- int rdrcnt,rprcnt, res;
+ unsigned int rdrcnt,rprcnt;
+ int res;
char param[WORDSIZE /* api number */
+sizeof(RAP_NetGroupDel_REQ) /* parm string */
+1 /* no ret string */
@@ -614,7 +619,8 @@ int cli_NetUserAdd(struct cli_state *cli, RAP_USER_INFO_1 * userinfo )
char *rparam = NULL;
char *rdata = NULL;
char *p;
- int rdrcnt,rprcnt,res;
+ unsigned int rdrcnt,rprcnt;
+ int res;
char param[WORDSIZE /* api number */
+sizeof(RAP_NetUserAdd2_REQ) /* req string */
+sizeof(RAP_USER_INFO_L1) /* data string */
@@ -702,7 +708,7 @@ int cli_RNetUserEnum(struct cli_state *cli, void (*fn)(const char *, const char
char *p;
char *rparam = NULL;
char *rdata = NULL;
- int rprcnt, rdrcnt;
+ unsigned int rprcnt, rdrcnt;
int res = -1;
@@ -770,7 +776,7 @@ int cli_NetFileClose(struct cli_state *cli, uint32 file_id )
char *rparam = NULL;
char *rdata = NULL;
char *p;
- int rdrcnt,rprcnt;
+ unsigned int rdrcnt,rprcnt;
char param[WORDSIZE /* api number */
+sizeof(RAP_WFileClose2_REQ) /* req string */
+1 /* no ret string */
@@ -816,7 +822,8 @@ int cli_NetFileGetInfo(struct cli_state *cli, uint32 file_id, void (*fn)(const c
char *rparam = NULL;
char *rdata = NULL;
char *p;
- int rdrcnt,rprcnt, res;
+ unsigned int rdrcnt,rprcnt;
+ int res;
char param[WORDSIZE /* api number */
+sizeof(RAP_WFileGetInfo2_REQ) /* req string */
+sizeof(RAP_FILE_INFO_L3) /* return string */
@@ -893,7 +900,7 @@ int cli_NetFileEnum(struct cli_state *cli, char * user, char * base_path, void (
char *rparam = NULL;
char *rdata = NULL;
char *p;
- int rdrcnt,rprcnt;
+ unsigned int rdrcnt,rprcnt;
char param[WORDSIZE /* api number */
+sizeof(RAP_WFileEnum2_REQ) /* req string */
+sizeof(RAP_FILE_INFO_L3) /* return string */
@@ -965,7 +972,8 @@ int cli_NetShareAdd(struct cli_state *cli, RAP_SHARE_INFO_2 * sinfo )
char *rparam = NULL;
char *rdata = NULL;
char *p;
- int rdrcnt,rprcnt,res;
+ unsigned int rdrcnt,rprcnt;
+ int res;
char param[WORDSIZE /* api number */
+sizeof(RAP_WShareAdd_REQ) /* req string */
+sizeof(RAP_SHARE_INFO_L2) /* return string */
@@ -1035,7 +1043,8 @@ int cli_NetShareDelete(struct cli_state *cli, const char * share_name )
char *rparam = NULL;
char *rdata = NULL;
char *p;
- int rdrcnt,rprcnt, res;
+ unsigned int rdrcnt,rprcnt;
+ int res;
char param[WORDSIZE /* api number */
+sizeof(RAP_WShareDel_REQ) /* req string */
+1 /* no ret string */
@@ -1097,7 +1106,7 @@ BOOL cli_get_pdc_name(struct cli_state *cli, char *workgroup, char *pdc_name)
{
char *rparam = NULL;
char *rdata = NULL;
- int rdrcnt,rprcnt;
+ unsigned int rdrcnt,rprcnt;
char *p;
char param[WORDSIZE /* api number */
+sizeof(RAP_NetServerEnum2_REQ) /* req string */
@@ -1177,7 +1186,7 @@ BOOL cli_get_server_domain(struct cli_state *cli)
{
char *rparam = NULL;
char *rdata = NULL;
- int rdrcnt,rprcnt;
+ unsigned int rdrcnt,rprcnt;
char *p;
char param[WORDSIZE /* api number */
+sizeof(RAP_WWkstaGetInfo_REQ) /* req string */
@@ -1242,7 +1251,7 @@ BOOL cli_get_server_type(struct cli_state *cli, uint32 *pstype)
{
char *rparam = NULL;
char *rdata = NULL;
- int rdrcnt,rprcnt;
+ unsigned int rdrcnt,rprcnt;
char *p;
char param[WORDSIZE /* api number */
+sizeof(RAP_WserverGetInfo_REQ) /* req string */
@@ -1309,7 +1318,7 @@ BOOL cli_ns_check_server_type(struct cli_state *cli, char *workgroup, uint32 sty
{
char *rparam = NULL;
char *rdata = NULL;
- int rdrcnt,rprcnt;
+ unsigned int rdrcnt,rprcnt;
char *p;
char param[WORDSIZE /* api number */
+sizeof(RAP_NetServerEnum2_REQ) /* req string */
@@ -1378,7 +1387,7 @@ BOOL cli_NetWkstaUserLogoff(struct cli_state *cli,char *user, char *workstation)
char *rparam = NULL;
char *rdata = NULL;
char *p;
- int rdrcnt,rprcnt;
+ unsigned int rdrcnt,rprcnt;
char param[WORDSIZE /* api number */
+sizeof(RAP_NetWkstaUserLogoff_REQ) /* req string */
+sizeof(RAP_USER_LOGOFF_INFO_L1) /* return string */
@@ -1436,7 +1445,7 @@ int cli_NetPrintQEnum(struct cli_state *cli,
char *p;
char *rparam = NULL;
char *rdata = NULL;
- int rprcnt, rdrcnt;
+ unsigned int rprcnt, rdrcnt;
int res = -1;
@@ -1540,7 +1549,7 @@ int cli_NetPrintQGetInfo(struct cli_state *cli, const char *printer,
char *p;
char *rparam = NULL;
char *rdata = NULL;
- int rprcnt, rdrcnt;
+ unsigned int rprcnt, rdrcnt;
int res = -1;
@@ -1639,7 +1648,7 @@ int cli_RNetServiceEnum(struct cli_state *cli, void (*fn)(const char *, const ch
char *p;
char *rparam = NULL;
char *rdata = NULL;
- int rprcnt, rdrcnt;
+ unsigned int rprcnt, rdrcnt;
int res = -1;
@@ -1708,7 +1717,7 @@ int cli_NetSessionEnum(struct cli_state *cli, void (*fn)(char *, char *, uint16,
char *p;
char *rparam = NULL;
char *rdata = NULL;
- int rprcnt, rdrcnt;
+ unsigned int rprcnt, rdrcnt;
int res = -1;
memset(param, '\0', sizeof(param));
@@ -1784,7 +1793,7 @@ int cli_NetSessionGetInfo(struct cli_state *cli, const char *workstation, void (
char *p;
char *rparam = NULL;
char *rdata = NULL;
- int rprcnt, rdrcnt;
+ unsigned int rprcnt, rdrcnt;
int res = -1;
@@ -1858,7 +1867,7 @@ int cli_NetSessionDel(struct cli_state *cli, const char *workstation)
char *p;
char *rparam = NULL;
char *rdata = NULL;
- int rprcnt, rdrcnt;
+ unsigned int rprcnt, rdrcnt;
int res;
memset(param, '\0', sizeof(param));
@@ -1903,7 +1912,7 @@ int cli_NetConnectionEnum(struct cli_state *cli, const char *qualifier, void (*f
char *p;
char *rparam = NULL;
char *rdata = NULL;
- int rprcnt, rdrcnt;
+ unsigned int rprcnt, rdrcnt;
int res = -1;
memset(param, '\0', sizeof(param));
diff --git a/source/libsmb/clireadwrite.c b/source/libsmb/clireadwrite.c
index 0715aa7f1a5..8eac7d07d8b 100644
--- a/source/libsmb/clireadwrite.c
+++ b/source/libsmb/clireadwrite.c
@@ -326,7 +326,7 @@ ssize_t cli_write(struct cli_state *cli,
int issued = 0;
int received = 0;
int mpx = MAX(cli->max_mux-1, 1);
- int block = (cli->max_xmit - (smb_size+32)) & ~1023;
+ int block = cli->max_xmit - (smb_size+32);
int blocks = (size + (block-1)) / block;
while (received < blocks) {
diff --git a/source/libsmb/clisecdesc.c b/source/libsmb/clisecdesc.c
index d86a9022a69..548cd6ec187 100644
--- a/source/libsmb/clisecdesc.c
+++ b/source/libsmb/clisecdesc.c
@@ -28,7 +28,7 @@ SEC_DESC *cli_query_secdesc(struct cli_state *cli, int fnum,
{
char param[8];
char *rparam=NULL, *rdata=NULL;
- int rparam_count=0, rdata_count=0;
+ unsigned int rparam_count=0, rdata_count=0;
prs_struct pd;
SEC_DESC *psd = NULL;
@@ -78,7 +78,7 @@ BOOL cli_set_secdesc(struct cli_state *cli, int fnum, SEC_DESC *sd)
{
char param[8];
char *rparam=NULL, *rdata=NULL;
- int rparam_count=0, rdata_count=0;
+ unsigned int rparam_count=0, rdata_count=0;
uint32 sec_info = 0;
TALLOC_CTX *mem_ctx;
prs_struct pd;
diff --git a/source/libsmb/clispnego.c b/source/libsmb/clispnego.c
index bb48f579151..63076a1a1ce 100644
--- a/source/libsmb/clispnego.c
+++ b/source/libsmb/clispnego.c
@@ -2,7 +2,7 @@
Unix SMB/CIFS implementation.
simple kerberos5/SPNEGO routines
Copyright (C) Andrew Tridgell 2001
- Copyright (C) Jim McDonough 2002
+ Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
Copyright (C) Luke Howard 2003
This program is free software; you can redistribute it and/or modify
@@ -323,13 +323,16 @@ BOOL spnego_parse_krb5_wrap(DATA_BLOB blob, DATA_BLOB *ticket, uint8 tok_id[2])
generate a SPNEGO negTokenTarg packet, ready for a EXTENDED_SECURITY
kerberos session setup
*/
-DATA_BLOB spnego_gen_negTokenTarg(const char *principal, int time_offset)
+DATA_BLOB spnego_gen_negTokenTarg(const char *principal, int time_offset, unsigned char session_key_krb5[16])
{
DATA_BLOB tkt, tkt_wrapped, targ;
const char *krb_mechs[] = {OID_KERBEROS5_OLD, OID_NTLMSSP, NULL};
- /* get a kerberos ticket for the service */
- tkt = cli_krb5_get_ticket(principal, time_offset);
+ /* get a kerberos ticket for the service and extract the session key */
+ tkt = cli_krb5_get_ticket(principal, time_offset, session_key_krb5);
+
+ if (tkt.data == NULL)
+ return tkt;
/* wrap that up in a nice GSS-API wrapping */
tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);
diff --git a/source/libsmb/clitrans.c b/source/libsmb/clitrans.c
index 3d3cd427d76..e6771ac6885 100644
--- a/source/libsmb/clitrans.c
+++ b/source/libsmb/clitrans.c
@@ -40,6 +40,7 @@ BOOL cli_send_trans(struct cli_state *cli, int trans,
char *outdata,*outparam;
char *p;
int pipe_name_len=0;
+ uint16 mid;
this_lparam = MIN(lparam,cli->max_xmit - (500+lsetup*2)); /* hack */
this_ldata = MIN(ldata,cli->max_xmit - (500+lsetup*2+this_lparam));
@@ -49,6 +50,7 @@ BOOL cli_send_trans(struct cli_state *cli, int trans,
SCVAL(cli->outbuf,smb_com,trans);
SSVAL(cli->outbuf,smb_tid, cli->cnum);
cli_setup_packet(cli);
+ mid = cli->mid;
if (pipe_name) {
pipe_name_len = clistr_push(cli, smb_buf(cli->outbuf), pipe_name, -1, STR_TERMINATE);
@@ -84,13 +86,19 @@ BOOL cli_send_trans(struct cli_state *cli, int trans,
cli_setup_bcc(cli, outdata+this_ldata);
show_msg(cli->outbuf);
- if (!cli_send_smb(cli))
+
+ cli_signing_trans_start(cli);
+ if (!cli_send_smb(cli)) {
+ cli_signing_trans_stop(cli);
return False;
+ }
if (this_ldata < ldata || this_lparam < lparam) {
/* receive interim response */
- if (!cli_receive_smb(cli) || cli_is_error(cli))
+ if (!cli_receive_smb(cli) || cli_is_error(cli)) {
+ cli_signing_trans_stop(cli);
return(False);
+ }
tot_data = this_ldata;
tot_param = this_lparam;
@@ -122,9 +130,15 @@ BOOL cli_send_trans(struct cli_state *cli, int trans,
memcpy(outdata,data+tot_data,this_ldata);
cli_setup_bcc(cli, outdata+this_ldata);
+ /* Ensure this packet has the same MID as
+ * the primary. Important in signing. JRA. */
+ cli->mid = mid;
+
show_msg(cli->outbuf);
- if (!cli_send_smb(cli))
+ if (!cli_send_smb(cli)) {
+ cli_signing_trans_stop(cli);
return False;
+ }
tot_data += this_ldata;
tot_param += this_lparam;
@@ -151,8 +165,10 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
*data_len = *param_len = 0;
- if (!cli_receive_smb(cli))
+ if (!cli_receive_smb(cli)) {
+ cli_signing_trans_stop(cli);
return False;
+ }
show_msg(cli->inbuf);
@@ -161,6 +177,7 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
DEBUG(0,("Expected %s response, got command 0x%02x\n",
trans==SMBtrans?"SMBtrans":"SMBtrans2",
CVAL(cli->inbuf,smb_com)));
+ cli_signing_trans_stop(cli);
return(False);
}
@@ -171,8 +188,10 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
*/
status = cli_nt_error(cli);
- if (NT_STATUS_IS_ERR(status))
+ if (NT_STATUS_IS_ERR(status)) {
+ cli_signing_trans_stop(cli);
return False;
+ }
/* parse out the lengths */
total_data = SVAL(cli->inbuf,smb_tdrcnt);
@@ -183,6 +202,7 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
tdata = Realloc(*data,total_data);
if (!tdata) {
DEBUG(0,("cli_receive_trans: failed to enlarge data buffer\n"));
+ cli_signing_trans_stop(cli);
return False;
}
else
@@ -193,6 +213,7 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
tparam = Realloc(*param,total_param);
if (!tparam) {
DEBUG(0,("cli_receive_trans: failed to enlarge param buffer\n"));
+ cli_signing_trans_stop(cli);
return False;
}
else
@@ -206,6 +227,7 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
if (this_data + *data_len > total_data ||
this_param + *param_len > total_param) {
DEBUG(1,("Data overflow in cli_receive_trans\n"));
+ cli_signing_trans_stop(cli);
return False;
}
@@ -214,6 +236,7 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
this_param + *param_len < this_param ||
this_param + *param_len < *param_len) {
DEBUG(1,("Data overflow in cli_receive_trans\n"));
+ cli_signing_trans_stop(cli);
return False;
}
@@ -226,6 +249,7 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
data_offset_out + this_data < data_offset_out ||
data_offset_out + this_data < this_data) {
DEBUG(1,("Data overflow in cli_receive_trans\n"));
+ cli_signing_trans_stop(cli);
return False;
}
if (data_offset_in > cli->bufsize ||
@@ -233,6 +257,7 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
data_offset_in + this_data < data_offset_in ||
data_offset_in + this_data < this_data) {
DEBUG(1,("Data overflow in cli_receive_trans\n"));
+ cli_signing_trans_stop(cli);
return False;
}
@@ -247,6 +272,7 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
param_offset_out + this_param < param_offset_out ||
param_offset_out + this_param < this_param) {
DEBUG(1,("Param overflow in cli_receive_trans\n"));
+ cli_signing_trans_stop(cli);
return False;
}
if (param_offset_in > cli->bufsize ||
@@ -254,6 +280,7 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
param_offset_in + this_param < param_offset_in ||
param_offset_in + this_param < this_param) {
DEBUG(1,("Param overflow in cli_receive_trans\n"));
+ cli_signing_trans_stop(cli);
return False;
}
@@ -265,8 +292,10 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
if (total_data <= *data_len && total_param <= *param_len)
break;
- if (!cli_receive_smb(cli))
- return False;
+ if (!cli_receive_smb(cli)) {
+ cli_signing_trans_stop(cli);
+ return False;
+ }
show_msg(cli->inbuf);
@@ -275,9 +304,11 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
DEBUG(0,("Expected %s response, got command 0x%02x\n",
trans==SMBtrans?"SMBtrans":"SMBtrans2",
CVAL(cli->inbuf,smb_com)));
+ cli_signing_trans_stop(cli);
return(False);
}
if (NT_STATUS_IS_ERR(cli_nt_error(cli))) {
+ cli_signing_trans_stop(cli);
return(False);
}
@@ -292,6 +323,7 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
}
+ cli_signing_trans_stop(cli);
return(True);
}
@@ -309,6 +341,7 @@ BOOL cli_send_nt_trans(struct cli_state *cli,
unsigned int i;
unsigned int this_ldata,this_lparam;
unsigned int tot_data=0,tot_param=0;
+ uint16 mid;
char *outdata,*outparam;
this_lparam = MIN(lparam,cli->max_xmit - (500+lsetup*2)); /* hack */
@@ -319,6 +352,7 @@ BOOL cli_send_nt_trans(struct cli_state *cli,
SCVAL(cli->outbuf,smb_com,SMBnttrans);
SSVAL(cli->outbuf,smb_tid, cli->cnum);
cli_setup_packet(cli);
+ mid = cli->mid;
outparam = smb_buf(cli->outbuf)+3;
outdata = outparam+this_lparam;
@@ -347,13 +381,18 @@ BOOL cli_send_nt_trans(struct cli_state *cli,
cli_setup_bcc(cli, outdata+this_ldata);
show_msg(cli->outbuf);
- if (!cli_send_smb(cli))
+ cli_signing_trans_start(cli);
+ if (!cli_send_smb(cli)) {
+ cli_signing_trans_stop(cli);
return False;
+ }
if (this_ldata < ldata || this_lparam < lparam) {
/* receive interim response */
- if (!cli_receive_smb(cli) || cli_is_error(cli))
+ if (!cli_receive_smb(cli) || cli_is_error(cli)) {
+ cli_signing_trans_stop(cli);
return(False);
+ }
tot_data = this_ldata;
tot_param = this_lparam;
@@ -384,9 +423,16 @@ BOOL cli_send_nt_trans(struct cli_state *cli,
memcpy(outdata,data+tot_data,this_ldata);
cli_setup_bcc(cli, outdata+this_ldata);
+ /* Ensure this packet has the same MID as
+ * the primary. Important in signing. JRA. */
+ cli->mid = mid;
+
show_msg(cli->outbuf);
- if (!cli_send_smb(cli))
+
+ if (!cli_send_smb(cli)) {
+ cli_signing_trans_stop(cli);
return False;
+ }
tot_data += this_ldata;
tot_param += this_lparam;
@@ -396,8 +442,6 @@ BOOL cli_send_nt_trans(struct cli_state *cli,
return(True);
}
-
-
/****************************************************************************
receive a SMB nttrans response allocating the necessary memory
****************************************************************************/
@@ -416,8 +460,10 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
*data_len = *param_len = 0;
- if (!cli_receive_smb(cli))
+ if (!cli_receive_smb(cli)) {
+ cli_signing_trans_stop(cli);
return False;
+ }
show_msg(cli->inbuf);
@@ -425,6 +471,7 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
if (CVAL(cli->inbuf,smb_com) != SMBnttrans) {
DEBUG(0,("Expected SMBnttrans response, got command 0x%02x\n",
CVAL(cli->inbuf,smb_com)));
+ cli_signing_trans_stop(cli);
return(False);
}
@@ -435,8 +482,10 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
*/
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)) {
+ cli_signing_trans_stop(cli);
return(False);
+ }
}
/* parse out the lengths */
@@ -448,6 +497,7 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
tdata = Realloc(*data,total_data);
if (!tdata) {
DEBUG(0,("cli_receive_nt_trans: failed to enlarge data buffer to %d\n",total_data));
+ cli_signing_trans_stop(cli);
return False;
} else {
*data = tdata;
@@ -458,6 +508,7 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
tparam = Realloc(*param,total_param);
if (!tparam) {
DEBUG(0,("cli_receive_nt_trans: failed to enlarge param buffer to %d\n", total_param));
+ cli_signing_trans_stop(cli);
return False;
} else {
*param = tparam;
@@ -471,6 +522,7 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
if (this_data + *data_len > total_data ||
this_param + *param_len > total_param) {
DEBUG(1,("Data overflow in cli_receive_nt_trans\n"));
+ cli_signing_trans_stop(cli);
return False;
}
@@ -479,6 +531,7 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
this_param + *param_len < this_param ||
this_param + *param_len < *param_len) {
DEBUG(1,("Data overflow in cli_receive_nt_trans\n"));
+ cli_signing_trans_stop(cli);
return False;
}
@@ -491,6 +544,7 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
data_offset_out + this_data < data_offset_out ||
data_offset_out + this_data < this_data) {
DEBUG(1,("Data overflow in cli_receive_nt_trans\n"));
+ cli_signing_trans_stop(cli);
return False;
}
if (data_offset_in > cli->bufsize ||
@@ -498,6 +552,7 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
data_offset_in + this_data < data_offset_in ||
data_offset_in + this_data < this_data) {
DEBUG(1,("Data overflow in cli_receive_nt_trans\n"));
+ cli_signing_trans_stop(cli);
return False;
}
@@ -513,6 +568,7 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
param_offset_out + this_param < param_offset_out ||
param_offset_out + this_param < this_param) {
DEBUG(1,("Param overflow in cli_receive_nt_trans\n"));
+ cli_signing_trans_stop(cli);
return False;
}
if (param_offset_in > cli->bufsize ||
@@ -520,6 +576,7 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
param_offset_in + this_param < param_offset_in ||
param_offset_in + this_param < this_param) {
DEBUG(1,("Param overflow in cli_receive_nt_trans\n"));
+ cli_signing_trans_stop(cli);
return False;
}
@@ -532,8 +589,10 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
if (total_data <= *data_len && total_param <= *param_len)
break;
- if (!cli_receive_smb(cli))
+ if (!cli_receive_smb(cli)) {
+ cli_signing_trans_stop(cli);
return False;
+ }
show_msg(cli->inbuf);
@@ -541,13 +600,15 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
if (CVAL(cli->inbuf,smb_com) != SMBnttrans) {
DEBUG(0,("Expected SMBnttrans response, got command 0x%02x\n",
CVAL(cli->inbuf,smb_com)));
+ cli_signing_trans_stop(cli);
return(False);
}
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)) {
+ cli_signing_trans_stop(cli);
return(False);
+ }
}
/* parse out the total lengths again - they can shrink! */
if (SVAL(cli->inbuf,smb_ntr_TotalDataCount) < total_data)
@@ -559,5 +620,6 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
break;
}
+ cli_signing_trans_stop(cli);
return(True);
}
diff --git a/source/libsmb/errormap.c b/source/libsmb/errormap.c
index 8ee5ee3d31e..3d99e3d5e52 100644
--- a/source/libsmb/errormap.c
+++ b/source/libsmb/errormap.c
@@ -1498,6 +1498,7 @@ const struct unix_error_map unix_dos_nt_errmap[] = {
{ ENFILE, ERRDOS, ERRnofids, NT_STATUS_TOO_MANY_OPENED_FILES },
{ EMFILE, ERRDOS, ERRnofids, NT_STATUS_TOO_MANY_OPENED_FILES },
{ ENOSPC, ERRHRD, ERRdiskfull, NT_STATUS_DISK_FULL },
+ { ENOMEM, ERRDOS, ERRnomem, NT_STATUS_NO_MEMORY },
#ifdef EDQUOT
{ EDQUOT, ERRHRD, ERRdiskfull, NT_STATUS_DISK_FULL },
#endif
diff --git a/source/libsmb/namequery_dc.c b/source/libsmb/namequery_dc.c
index c9d45a7acc1..a596f00ddb9 100644
--- a/source/libsmb/namequery_dc.c
+++ b/source/libsmb/namequery_dc.c
@@ -161,18 +161,28 @@ BOOL get_dc_name(const char *domain, fstring srv_name, struct in_addr *ip_out)
{
struct in_addr dc_ip;
BOOL ret;
+ BOOL our_domain = False;
zero_ip(&dc_ip);
ret = False;
- if (lp_security() == SEC_ADS)
+
+ if ( strequal(lp_workgroup(), domain) || strequal(lp_realm(), domain) )
+ our_domain = True;
+
+ /* always try to obey what the admin specified in smb.conf.
+ If it is not our domain, assume that domain names with periods
+ in them are realm names */
+
+ if ( (our_domain && lp_security()==SEC_ADS) || strchr_m(domain, '.') ) {
ret = ads_dc_name(domain, &dc_ip, srv_name);
-
+ }
+
if (!ret) {
/* fall back on rpc methods if the ADS methods fail */
ret = rpc_dc_name(domain, srv_name, &dc_ip);
}
-
+
*ip_out = dc_ip;
return ret;
diff --git a/source/libsmb/nmblib.c b/source/libsmb/nmblib.c
index 157a2bb43cb..6ee05f01045 100644
--- a/source/libsmb/nmblib.c
+++ b/source/libsmb/nmblib.c
@@ -1129,12 +1129,14 @@ char *dns_to_netbios_name(char *dns_name)
/****************************************************************************
-interpret the weird netbios "name". Return the name type
+interpret the weird netbios "name" into a unix fstring. Return the name type
****************************************************************************/
-static int name_interpret(char *in,char *out)
+static int name_interpret(char *in, fstring name)
{
int ret;
int len = (*in++) / 2;
+ fstring out_string;
+ char *out = out_string;
*out=0;
@@ -1150,8 +1152,8 @@ static int name_interpret(char *in,char *out)
in += 2;
out++;
}
- *out = 0;
ret = out[-1];
+ out[-1] = 0;
#ifdef NETBIOS_SCOPE
/* Handle any scope names */
@@ -1165,6 +1167,8 @@ static int name_interpret(char *in,char *out)
in += len;
}
#endif
+ pull_ascii(name, out_string, sizeof(fstring), sizeof(out_string), STR_TERMINATE);
+
return(ret);
}
@@ -1245,9 +1249,9 @@ static char *name_ptr(char *buf,int ofs)
}
/****************************************************************************
-extract a netbios name from a buf
+extract a netbios name from a buf (into a unix string) return name type
****************************************************************************/
-int name_extract(char *buf,int ofs,char *name)
+int name_extract(char *buf,int ofs, fstring name)
{
char *p = name_ptr(buf,ofs);
int d = PTR_DIFF(p,buf+ofs);
diff --git a/source/libsmb/ntlmssp.c b/source/libsmb/ntlmssp.c
index 66dc6e08eb8..e4d4acd29b0 100644
--- a/source/libsmb/ntlmssp.c
+++ b/source/libsmb/ntlmssp.c
@@ -23,6 +23,12 @@
#include "includes.h"
+#if 0
+/* we currently do not know how to get the right session key for this, so
+ we cannot enable it by default... :-( */
+#define USE_NTLM2 1
+#endif
+
/**
* Print out the NTLMSSP flags for debugging
* @param neg_flags The flags from the packet
@@ -140,7 +146,7 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state,
&cliname,
&domname)) {
DEBUG(1, ("ntlmssp_server_negotiate: failed to parse NTLMSSP:\n"));
- dump_data(2, request.data, request.length);
+ dump_data(2, (const char *)request.data, request.length);
return NT_STATUS_INVALID_PARAMETER;
}
@@ -172,6 +178,9 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state,
target_name = ntlmssp_target_name(ntlmssp_state,
neg_flags, &chal_flags);
+ if (target_name == NULL)
+ return NT_STATUS_INVALID_PARAMETER;
+
/* This should be a 'netbios domain -> DNS domain' mapping */
dnsdomname[0] = '\0';
get_mydomname(dnsdomname);
@@ -273,14 +282,14 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
&sess_key,
&neg_flags)) {
DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP:\n"));
- dump_data(2, request.data, request.length);
+ dump_data(2, (const char *)request.data, request.length);
return NT_STATUS_INVALID_PARAMETER;
}
data_blob_free(&sess_key);
- DEBUG(3,("Got user=[%s] domain=[%s] workstation=[%s] len1=%d len2=%d\n",
- ntlmssp_state->user, ntlmssp_state->domain, ntlmssp_state->workstation, ntlmssp_state->lm_resp.length, ntlmssp_state->nt_resp.length));
+ DEBUG(3,("Got user=[%s] domain=[%s] workstation=[%s] len1=%lu len2=%lu\n",
+ ntlmssp_state->user, ntlmssp_state->domain, ntlmssp_state->workstation, (unsigned long)ntlmssp_state->lm_resp.length, (unsigned long)ntlmssp_state->nt_resp.length));
#if 0
file_save("nthash1.dat", &ntlmssp_state->nt_resp.data, &ntlmssp_state->nt_resp.length);
@@ -412,6 +421,10 @@ static NTSTATUS ntlmssp_client_initial(struct ntlmssp_client_state *ntlmssp_stat
if (ntlmssp_state->use_ntlmv2) {
ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2;
}
+
+#ifdef USE_NTLM2
+ ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2;
+#endif
/* generate the ntlmssp negotiate packet */
msrpc_gen(next_request, "CddAA",
@@ -463,7 +476,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st
&server_domain_blob,
&chal_flags)) {
DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#1)\n"));
- dump_data(2, reply.data, reply.length);
+ dump_data(2, (const char *)reply.data, reply.length);
return NT_STATUS_INVALID_PARAMETER;
}
@@ -525,17 +538,22 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st
&unkn1, &unkn2,
&struct_blob)) {
DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#2)\n"));
- dump_data(2, reply.data, reply.length);
+ dump_data(2, (const char *)reply.data, reply.length);
return NT_STATUS_INVALID_PARAMETER;
}
+ ntlmssp_state->server_domain = talloc_strdup(ntlmssp_state->mem_ctx,
+ server_domain);
+
SAFE_FREE(server_domain);
if (challenge_blob.length != 8) {
data_blob_free(&struct_blob);
return NT_STATUS_INVALID_PARAMETER;
}
- if (ntlmssp_state->use_ntlmv2) {
+ if (!ntlmssp_state->password) {
+ /* do nothing - blobs are zero length */
+ } else if (ntlmssp_state->use_ntlmv2) {
if (!struct_blob.length) {
/* be lazy, match win2k - we can't do NTLMv2 without it */
@@ -554,7 +572,34 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st
data_blob_free(&struct_blob);
return NT_STATUS_NO_MEMORY;
}
+#ifdef USE_NTLM2
+ } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
+ struct MD5Context md5_session_nonce_ctx;
+ uchar nt_hash[16];
+ uchar session_nonce[16];
+ E_md4hash(ntlmssp_state->password, nt_hash);
+
+ generate_random_buffer(lm_response.data, 8, False);
+ memset(lm_response.data+8, 0, 16);
+
+ MD5Init(&md5_session_nonce_ctx);
+ MD5Update(&md5_session_nonce_ctx, challenge_blob.data, 8);
+ MD5Update(&md5_session_nonce_ctx, lm_response.data, 8);
+ MD5Final(session_nonce, &md5_session_nonce_ctx);
+
+ nt_response = data_blob(NULL, 24);
+ SMBNTencrypt(ntlmssp_state->password,
+ challenge_blob.data,
+ nt_response.data);
+
+ /* This is *NOT* the correct session key algorithm - just
+ fill in the bytes with something... */
+ session_key = data_blob(NULL, 16);
+ SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data);
+#endif
} else {
+
+
uchar lm_hash[16];
uchar nt_hash[16];
E_deshash(ntlmssp_state->password, lm_hash);
@@ -565,15 +610,15 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st
lm_response = data_blob(NULL, 24);
SMBencrypt(ntlmssp_state->password,challenge_blob.data,
lm_response.data);
- }
+ }
nt_response = data_blob(NULL, 24);
SMBNTencrypt(ntlmssp_state->password,challenge_blob.data,
nt_response.data);
-
+
session_key = data_blob(NULL, 16);
if ((ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY)
- && lp_client_lanman_auth()) {
+ && lp_client_lanman_auth()) {
SMBsesskeygen_lmv1(lm_hash, lm_response.data,
session_key.data);
} else {
@@ -706,9 +751,13 @@ NTSTATUS ntlmssp_set_username(NTLMSSP_CLIENT_STATE *ntlmssp_state, const char *u
NTSTATUS ntlmssp_set_password(NTLMSSP_CLIENT_STATE *ntlmssp_state, const char *password)
{
- ntlmssp_state->password = talloc_strdup(ntlmssp_state->mem_ctx, password);
- if (!ntlmssp_state->password) {
- return NT_STATUS_NO_MEMORY;
+ if (!password) {
+ ntlmssp_state->password = NULL;
+ } else {
+ ntlmssp_state->password = talloc_strdup(ntlmssp_state->mem_ctx, password);
+ if (!ntlmssp_state->password) {
+ return NT_STATUS_NO_MEMORY;
+ }
}
return NT_STATUS_OK;
}
diff --git a/source/libsmb/ntlmssp_parse.c b/source/libsmb/ntlmssp_parse.c
index f53afcdcd01..60cb4ab04ae 100644
--- a/source/libsmb/ntlmssp_parse.c
+++ b/source/libsmb/ntlmssp_parse.c
@@ -2,7 +2,7 @@
Unix SMB/CIFS implementation.
simple kerberos5/SPNEGO routines
Copyright (C) Andrew Tridgell 2001
- Copyright (C) Jim McDonough 2002
+ Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
Copyright (C) Andrew Bartlett 2002-2003
This program is free software; you can redistribute it and/or modify
@@ -153,7 +153,8 @@ BOOL msrpc_gen(DATA_BLOB *blob,
SSVAL(blob->data, head_ofs, n); head_ofs += 2;
SSVAL(blob->data, head_ofs, n); head_ofs += 2;
SIVAL(blob->data, head_ofs, data_ofs); head_ofs += 4;
- memcpy(blob->data+data_ofs, b, n);
+ if (n && b) /* don't follow null pointers... */
+ memcpy(blob->data+data_ofs, b, n);
data_ofs += n;
break;
case 'd':
diff --git a/source/libsmb/ntlmssp_sign.c b/source/libsmb/ntlmssp_sign.c
index ecaef808c9b..ff2f97c2e88 100644
--- a/source/libsmb/ntlmssp_sign.c
+++ b/source/libsmb/ntlmssp_sign.c
@@ -91,8 +91,8 @@ static void calc_ntlmv2_hash(unsigned char hash[16], char digest[16],
MD5Init(&ctx3);
MD5Update(&ctx3, session_key.data, session_key.length);
- MD5Update(&ctx3, constant, strlen(constant));
- MD5Final(digest, &ctx3);
+ MD5Update(&ctx3, (const unsigned char *)constant, strlen(constant));
+ MD5Final((unsigned char *)digest, &ctx3);
calc_hash(hash, digest, 16);
}
@@ -113,8 +113,8 @@ static NTSTATUS ntlmssp_make_packet_signature(NTLMSSP_CLIENT_STATE *ntlmssp_stat
uchar digest[16];
SIVAL(seq_num, 0, ntlmssp_state->ntlmssp_seq_num);
- hmac_md5_init_limK_to_64(ntlmssp_state->cli_sign_const, 16, &ctx);
- hmac_md5_update(seq_num, 4, &ctx);
+ hmac_md5_init_limK_to_64((const unsigned char *)(ntlmssp_state->cli_sign_const), 16, &ctx);
+ hmac_md5_update((const unsigned char *)seq_num, 4, &ctx);
hmac_md5_update(data, length, &ctx);
hmac_md5_final(digest, &ctx);
@@ -132,7 +132,7 @@ static NTSTATUS ntlmssp_make_packet_signature(NTLMSSP_CLIENT_STATE *ntlmssp_stat
}
} else {
uint32 crc;
- crc = crc32_calc_buffer(data, length);
+ crc = crc32_calc_buffer((const char *)data, length);
if (!msrpc_gen(sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, ntlmssp_state->ntlmssp_seq_num)) {
return NT_STATUS_NO_MEMORY;
}
@@ -183,10 +183,10 @@ NTSTATUS ntlmssp_client_check_packet(NTLMSSP_CLIENT_STATE *ntlmssp_state,
if (memcmp(sig->data+sig->length - 8, local_sig.data+local_sig.length - 8, 8) != 0) {
DEBUG(5, ("BAD SIG: wanted signature of\n"));
- dump_data(5, local_sig.data, local_sig.length);
+ dump_data(5, (const char *)local_sig.data, local_sig.length);
DEBUG(5, ("BAD SIG: got signature of\n"));
- dump_data(5, sig->data, sig->length);
+ dump_data(5, (const char *)(sig->data), sig->length);
DEBUG(0, ("NTLMSSP packet check failed due to invalid signature!\n"));
return NT_STATUS_ACCESS_DENIED;
@@ -216,8 +216,8 @@ NTSTATUS ntlmssp_client_seal_packet(NTLMSSP_CLIENT_STATE *ntlmssp_state,
uchar digest[16];
SIVAL(seq_num, 0, ntlmssp_state->ntlmssp_seq_num);
- hmac_md5_init_limK_to_64(ntlmssp_state->cli_sign_const, 16, &ctx);
- hmac_md5_update(seq_num, 4, &ctx);
+ hmac_md5_init_limK_to_64((const unsigned char *)(ntlmssp_state->cli_sign_const), 16, &ctx);
+ hmac_md5_update((const unsigned char *)seq_num, 4, &ctx);
hmac_md5_update(data, length, &ctx);
hmac_md5_final(digest, &ctx);
@@ -236,7 +236,7 @@ NTSTATUS ntlmssp_client_seal_packet(NTLMSSP_CLIENT_STATE *ntlmssp_state,
NTLMSSPcalc_ap(ntlmssp_state->cli_sign_hash, sig->data+4, sig->length-4);
} else {
uint32 crc;
- crc = crc32_calc_buffer(data, length);
+ crc = crc32_calc_buffer((const char *)data, length);
if (!msrpc_gen(sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, ntlmssp_state->ntlmssp_seq_num)) {
return NT_STATUS_NO_MEMORY;
}
@@ -335,7 +335,7 @@ NTSTATUS ntlmssp_client_sign_init(NTLMSSP_CLIENT_STATE *ntlmssp_state)
DEBUG(5, ("NTLMSSP Sign/Seal - using LM KEY\n"));
- calc_hash(ntlmssp_state->ntlmssp_hash, ntlmssp_state->session_key.data, 8);
+ calc_hash(ntlmssp_state->ntlmssp_hash, (const char *)(ntlmssp_state->session_key.data), 8);
dump_data_pw("NTLMSSP hash:\n", ntlmssp_state->ntlmssp_hash,
sizeof(ntlmssp_state->ntlmssp_hash));
} else {
@@ -347,7 +347,7 @@ NTSTATUS ntlmssp_client_sign_init(NTLMSSP_CLIENT_STATE *ntlmssp_state)
DEBUG(5, ("NTLMSSP Sign/Seal - using NT KEY\n"));
- calc_hash(ntlmssp_state->ntlmssp_hash, ntlmssp_state->session_key.data, 16);
+ calc_hash(ntlmssp_state->ntlmssp_hash, (const char *)(ntlmssp_state->session_key.data), 16);
dump_data_pw("NTLMSSP hash:\n", ntlmssp_state->ntlmssp_hash,
sizeof(ntlmssp_state->ntlmssp_hash));
}
diff --git a/source/libsmb/smb_signing.c b/source/libsmb/smb_signing.c
index df17362f083..08ff655a3f8 100644
--- a/source/libsmb/smb_signing.c
+++ b/source/libsmb/smb_signing.c
@@ -1,7 +1,7 @@
/*
Unix SMB/CIFS implementation.
SMB Signing Code
- Copyright (C) Jeremy Allison 2002.
+ Copyright (C) Jeremy Allison 2003.
Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003
This program is free software; you can redistribute it and/or modify
@@ -25,17 +25,26 @@
struct outstanding_packet_lookup {
uint16 mid;
uint32 reply_seq_num;
+ BOOL deferred_packet;
struct outstanding_packet_lookup *prev, *next;
};
+/* Store the data for an ongoing trans/trans2/nttrans operation. */
+struct trans_info_context {
+ uint16 mid;
+ uint32 send_seq_num;
+ uint32 reply_seq_num;
+};
+
struct smb_basic_signing_context {
DATA_BLOB mac_key;
uint32 send_seq_num;
+ struct trans_info_context *trans_info;
struct outstanding_packet_lookup *outstanding_packet_list;
};
static void store_sequence_for_reply(struct outstanding_packet_lookup **list,
- uint16 mid, uint32 reply_seq_num)
+ uint16 mid, uint32 reply_seq_num, BOOL deferred_pkt)
{
struct outstanding_packet_lookup *t;
struct outstanding_packet_lookup *tmp;
@@ -46,22 +55,47 @@ static void store_sequence_for_reply(struct outstanding_packet_lookup **list,
DLIST_ADD_END(*list, t, tmp);
t->mid = mid;
t->reply_seq_num = reply_seq_num;
+ t->deferred_packet = deferred_pkt;
+
+ DEBUG(10,("store_sequence_for_reply: stored %sseq = %u mid = %u\n",
+ deferred_pkt ? "deferred " : "",
+ (unsigned int)reply_seq_num, (unsigned int)mid ));
}
static BOOL get_sequence_for_reply(struct outstanding_packet_lookup **list,
- uint16 mid, uint32 *reply_seq_num)
+ uint16 mid, uint32 *reply_seq_num, BOOL *def)
{
struct outstanding_packet_lookup *t;
for (t = *list; t; t = t->next) {
if (t->mid == mid) {
*reply_seq_num = t->reply_seq_num;
+ if (def)
+ *def = t->deferred_packet;
+ DEBUG(10,("get_sequence_for_reply: found %sseq = %u mid = %u\n",
+ (t->deferred_packet) ? "deferred " : "",
+ (unsigned int)t->reply_seq_num, (unsigned int)t->mid ));
DLIST_REMOVE(*list, t);
+ SAFE_FREE(t);
+ return True;
+ }
+ }
+ return False;
+}
+
+/***********************************************************
+ A reply is pending if there is a non-deferred packet on the queue.
+************************************************************/
+
+static BOOL is_reply_pending(struct outstanding_packet_lookup *list)
+{
+ for (; list; list = list->next) {
+ if (!list->deferred_packet) {
+ DEBUG(10,("is_reply_pending: True.\n"));
return True;
}
}
- DEBUG(0, ("Unexpected incoming packet, it's MID (%u) does not match"
- " a MID in our outstanding list!\n", mid));
+ DEBUG(10,("is_reply_pending: False.\n"));
return False;
}
@@ -81,7 +115,7 @@ static BOOL cli_set_smb_signing_common(struct cli_state *cli)
}
if (cli->sign_info.free_signing_context)
- cli->sign_info.free_signing_context(cli);
+ cli->sign_info.free_signing_context(&cli->sign_info);
/* These calls are INCOMPATIBLE with SMB signing */
cli->readbraw_supported = False;
@@ -94,42 +128,108 @@ static BOOL cli_set_smb_signing_common(struct cli_state *cli)
SMB signing - Common code for 'real' implementations
************************************************************/
-static BOOL cli_set_smb_signing_real_common(struct cli_state *cli)
+static BOOL set_smb_signing_real_common(struct smb_sign_info *si)
{
- if (cli->sign_info.mandatory_signing) {
+ if (si->mandatory_signing) {
DEBUG(5, ("Mandatory SMB signing enabled!\n"));
- cli->sign_info.doing_signing = True;
}
+ si->doing_signing = True;
DEBUG(5, ("SMB signing enabled!\n"));
return True;
}
-static void cli_mark_packet_signed(struct cli_state *cli)
+static void mark_packet_signed(char *outbuf)
{
uint16 flags2;
- flags2 = SVAL(cli->outbuf,smb_flg2);
+ flags2 = SVAL(outbuf,smb_flg2);
flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
- SSVAL(cli->outbuf,smb_flg2, flags2);
+ SSVAL(outbuf,smb_flg2, flags2);
}
-static BOOL cli_signing_good(struct cli_state *cli, BOOL good)
+/***********************************************************
+ SMB signing - NULL implementation - calculate a MAC to send.
+************************************************************/
+
+static void null_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
{
- DEBUG(10, ("got SMB signature of\n"));
- dump_data(10,&cli->inbuf[smb_ss_field] , 8);
+ /* we can't zero out the sig, as we might be trying to send a
+ session request - which is NBT-level, not SMB level and doesn't
+ have the field */
+ return;
+}
- if (good && !cli->sign_info.doing_signing) {
- cli->sign_info.doing_signing = True;
+/***********************************************************
+ SMB signing - NULL implementation - check a MAC sent by server.
+************************************************************/
+
+static BOOL null_check_incoming_message(char *inbuf, struct smb_sign_info *si)
+{
+ return True;
+}
+
+/***********************************************************
+ SMB signing - NULL implementation - free signing context
+************************************************************/
+
+static void null_free_signing_context(struct smb_sign_info *si)
+{
+ return;
+}
+
+/**
+ SMB signing - NULL implementation - setup the MAC key.
+
+ @note Used as an initialisation only - it will not correctly
+ shut down a real signing mechanism
+*/
+
+static BOOL null_set_signing(struct smb_sign_info *si)
+{
+ si->signing_context = NULL;
+
+ si->sign_outgoing_message = null_sign_outgoing_message;
+ si->check_incoming_message = null_check_incoming_message;
+ si->free_signing_context = null_free_signing_context;
+
+ return True;
+}
+
+/**
+ * Free the signing context
+ */
+
+static void free_signing_context(struct smb_sign_info *si)
+{
+ if (si->free_signing_context) {
+ si->free_signing_context(si);
+ si->signing_context = NULL;
+ }
+
+ null_set_signing(si);
+}
+
+
+static BOOL signing_good(char *inbuf, struct smb_sign_info *si, BOOL good, uint32 seq)
+{
+ if (good && !si->doing_signing) {
+ si->doing_signing = True;
}
if (!good) {
- if (cli->sign_info.doing_signing) {
- DEBUG(1, ("SMB signature check failed!\n"));
+ if (si->doing_signing) {
+ struct smb_basic_signing_context *data = si->signing_context;
+
+ /* W2K sends a bad first signature but the sign engine is on.... JRA. */
+ if (data->send_seq_num > 1)
+ DEBUG(1, ("signing_good: SMB signature check failed on seq %u!\n",
+ (unsigned int)seq ));
+
return False;
} else {
- DEBUG(3, ("Server did not sign reply correctly\n"));
- cli_free_signing_context(cli);
+ DEBUG(3, ("signing_good: Peer did not sign reply correctly\n"));
+ free_signing_context(si);
return False;
}
}
@@ -155,13 +255,15 @@ static void simple_packet_signature(struct smb_basic_signing_context *data,
* We do this here, to avoid modifying the packet.
*/
+ DEBUG(10,("simple_packet_signature: sequence number %u\n", seq_number ));
+
SIVAL(sequence_buf, 0, seq_number);
SIVAL(sequence_buf, 4, 0);
/* Calculate the 16 byte MAC - but don't alter the data in the
incoming packet.
- This makes for a bit for fussing about, but it's not too bad.
+ This makes for a bit of fussing about, but it's not too bad.
*/
MD5Init(&md5_ctx);
@@ -185,76 +287,126 @@ static void simple_packet_signature(struct smb_basic_signing_context *data,
/***********************************************************
- SMB signing - Simple implementation - send the MAC.
+ SMB signing - Client implementation - send the MAC.
************************************************************/
-static void cli_simple_sign_outgoing_message(struct cli_state *cli)
+static void client_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
{
unsigned char calc_md5_mac[16];
- struct smb_basic_signing_context *data = cli->sign_info.signing_context;
+ struct smb_basic_signing_context *data = si->signing_context;
+ uint32 send_seq_num;
+
+ if (!si->doing_signing)
+ return;
+
+ /* JRA Paranioa test - we should be able to get rid of this... */
+ if (smb_len(outbuf) < (smb_ss_field + 8 - 4)) {
+ DEBUG(1, ("client_sign_outgoing_message: Logic error. Can't check signature on short packet! smb_len = %u\n",
+ smb_len(outbuf) ));
+ abort();
+ }
/* mark the packet as signed - BEFORE we sign it...*/
- cli_mark_packet_signed(cli);
+ mark_packet_signed(outbuf);
- simple_packet_signature(data, cli->outbuf, data->send_seq_num,
- calc_md5_mac);
+ if (data->trans_info)
+ send_seq_num = data->trans_info->send_seq_num;
+ else
+ send_seq_num = data->send_seq_num;
- DEBUG(10, ("sent SMB signature of\n"));
- dump_data(10, calc_md5_mac, 8);
+ simple_packet_signature(data, (const unsigned char *)outbuf, send_seq_num, calc_md5_mac);
- memcpy(&cli->outbuf[smb_ss_field], calc_md5_mac, 8);
+ DEBUG(10, ("client_sign_outgoing_message: sent SMB signature of\n"));
+ dump_data(10, (const char *)calc_md5_mac, 8);
+
+ memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8);
/* cli->outbuf[smb_ss_field+2]=0;
Uncomment this to test if the remote server actually verifies signatures...*/
+ if (data->trans_info)
+ return;
+
data->send_seq_num++;
store_sequence_for_reply(&data->outstanding_packet_list,
- cli->mid,
- data->send_seq_num);
+ SVAL(outbuf,smb_mid),
+ data->send_seq_num, False);
data->send_seq_num++;
}
/***********************************************************
- SMB signing - Simple implementation - check a MAC sent by server.
+ SMB signing - Client implementation - check a MAC sent by server.
************************************************************/
-static BOOL cli_simple_check_incoming_message(struct cli_state *cli)
+static BOOL client_check_incoming_message(char *inbuf, struct smb_sign_info *si)
{
BOOL good;
uint32 reply_seq_number;
+ uint32 saved_seq;
unsigned char calc_md5_mac[16];
unsigned char *server_sent_mac;
- struct smb_basic_signing_context *data = cli->sign_info.signing_context;
+ struct smb_basic_signing_context *data = si->signing_context;
+
+ if (!si->doing_signing)
+ return True;
- if (!get_sequence_for_reply(&data->outstanding_packet_list,
- SVAL(cli->inbuf, smb_mid),
- &reply_seq_number)) {
+ if (smb_len(inbuf) < (smb_ss_field + 8 - 4)) {
+ DEBUG(1, ("client_check_incoming_message: Can't check signature on short packet! smb_len = %u\n", smb_len(inbuf)));
return False;
}
- simple_packet_signature(data, cli->inbuf, reply_seq_number, calc_md5_mac);
+ if (data->trans_info) {
+ reply_seq_number = data->trans_info->reply_seq_num;
+ } else if (!get_sequence_for_reply(&data->outstanding_packet_list,
+ SVAL(inbuf, smb_mid),
+ &reply_seq_number, NULL)) {
+ DEBUG(1, ("client_check_incoming_message: failed to get sequence number %u for reply.\n",
+ (unsigned int) SVAL(inbuf, smb_mid) ));
+ return False;
+ }
+
+ saved_seq = reply_seq_number;
+ simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
- server_sent_mac = &cli->inbuf[smb_ss_field];
+ server_sent_mac = (unsigned char *)&inbuf[smb_ss_field];
good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
if (!good) {
- DEBUG(5, ("BAD SIG: wanted SMB signature of\n"));
- dump_data(5, calc_md5_mac, 8);
+ DEBUG(5, ("client_check_incoming_message: BAD SIG: wanted SMB signature of\n"));
+ dump_data(5, (const char *)calc_md5_mac, 8);
- DEBUG(5, ("BAD SIG: got SMB signature of\n"));
- dump_data(5, server_sent_mac, 8);
+ DEBUG(5, ("client_check_incoming_message: BAD SIG: got SMB signature of\n"));
+ dump_data(5, (const char *)server_sent_mac, 8);
+#if 1 /* JRATEST */
+ {
+ int i;
+ reply_seq_number -= 5;
+ for (i = 0; i < 10; i++, reply_seq_number++) {
+ simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
+ if (memcmp(server_sent_mac, calc_md5_mac, 8) == 0) {
+ DEBUG(0,("client_check_incoming_message: out of seq. seq num %u matches.\n",
+ reply_seq_number ));
+ break;
+ }
+ }
+ }
+#endif /* JRATEST */
+
+ } else {
+ DEBUG(10, ("client_check_incoming_message:: seq %u: got good SMB signature of\n", (unsigned int)reply_seq_number));
+ dump_data(10, (const char *)server_sent_mac, 8);
}
- return cli_signing_good(cli, good);
+ return signing_good(inbuf, si, good, saved_seq);
}
/***********************************************************
SMB signing - Simple implementation - free signing context
************************************************************/
-static void cli_simple_free_signing_context(struct cli_state *cli)
+static void simple_free_signing_context(struct smb_sign_info *si)
{
- struct smb_basic_signing_context *data = cli->sign_info.signing_context;
+ struct smb_basic_signing_context *data = si->signing_context;
struct outstanding_packet_lookup *list = data->outstanding_packet_list;
while (list) {
@@ -264,7 +416,11 @@ static void cli_simple_free_signing_context(struct cli_state *cli)
}
data_blob_free(&data->mac_key);
- SAFE_FREE(cli->sign_info.signing_context);
+
+ if (data->trans_info)
+ SAFE_FREE(data->trans_info);
+
+ SAFE_FREE(si->signing_context);
return;
}
@@ -284,18 +440,29 @@ BOOL cli_simple_set_signing(struct cli_state *cli, const uchar user_session_key[
return False;
}
- if (!cli_set_smb_signing_real_common(cli)) {
+ if (!set_smb_signing_real_common(&cli->sign_info)) {
return False;
}
data = smb_xmalloc(sizeof(*data));
+ memset(data, '\0', sizeof(*data));
cli->sign_info.signing_context = data;
data->mac_key = data_blob(NULL, response.length + 16);
memcpy(&data->mac_key.data[0], user_session_key, 16);
- memcpy(&data->mac_key.data[16],response.data, response.length);
+
+ DEBUG(10, ("cli_simple_set_signing: user_session_key\n"));
+ dump_data(10, (const char *)user_session_key, 16);
+
+ if (response.length) {
+ memcpy(&data->mac_key.data[16],response.data, response.length);
+ DEBUG(10, ("cli_simple_set_signing: response_data\n"));
+ dump_data(10, (const char *)response.data, response.length);
+ } else {
+ DEBUG(10, ("cli_simple_set_signing: NULL response_data\n"));
+ }
/* Initialise the sequence number */
data->send_seq_num = 0;
@@ -303,73 +470,68 @@ BOOL cli_simple_set_signing(struct cli_state *cli, const uchar user_session_key[
/* Initialise the list of outstanding packets */
data->outstanding_packet_list = NULL;
- cli->sign_info.sign_outgoing_message = cli_simple_sign_outgoing_message;
- cli->sign_info.check_incoming_message = cli_simple_check_incoming_message;
- cli->sign_info.free_signing_context = cli_simple_free_signing_context;
+ cli->sign_info.sign_outgoing_message = client_sign_outgoing_message;
+ cli->sign_info.check_incoming_message = client_check_incoming_message;
+ cli->sign_info.free_signing_context = simple_free_signing_context;
return True;
}
/***********************************************************
- SMB signing - NULL implementation - calculate a MAC to send.
+ Tell client code we are in a multiple trans reply state.
************************************************************/
-static void cli_null_sign_outgoing_message(struct cli_state *cli)
+void cli_signing_trans_start(struct cli_state *cli)
{
- /* we can't zero out the sig, as we might be trying to send a
- session request - which is NBT-level, not SMB level and doesn't
- have the field */
- return;
-}
+ struct smb_basic_signing_context *data = cli->sign_info.signing_context;
-/***********************************************************
- SMB signing - NULL implementation - check a MAC sent by server.
-************************************************************/
+ if (!cli->sign_info.doing_signing || !data)
+ return;
-static BOOL cli_null_check_incoming_message(struct cli_state *cli)
-{
- return True;
+ data->trans_info = smb_xmalloc(sizeof(struct trans_info_context));
+ ZERO_STRUCTP(data->trans_info);
+
+ data->trans_info->send_seq_num = data->send_seq_num;
+ data->trans_info->mid = SVAL(cli->outbuf,smb_mid);
+ data->trans_info->reply_seq_num = data->send_seq_num+1;
+
+ DEBUG(10,("cli_signing_trans_start: storing mid = %u, reply_seq_num = %u, send_seq_num = %u \
+data->send_seq_num = %u\n",
+ (unsigned int)data->trans_info->mid,
+ (unsigned int)data->trans_info->reply_seq_num,
+ (unsigned int)data->trans_info->send_seq_num,
+ (unsigned int)data->send_seq_num ));
}
/***********************************************************
- SMB signing - NULL implementation - free signing context
+ Tell client code we are out of a multiple trans reply state.
************************************************************/
-static void cli_null_free_signing_context(struct cli_state *cli)
+void cli_signing_trans_stop(struct cli_state *cli)
{
- return;
-}
+ struct smb_basic_signing_context *data = cli->sign_info.signing_context;
-/**
- SMB signing - NULL implementation - setup the MAC key.
+ if (!cli->sign_info.doing_signing || !data)
+ return;
- @note Used as an initialisation only - it will not correctly
- shut down a real signing mechanism
-*/
+ SAFE_FREE(data->trans_info);
+ data->trans_info = NULL;
-BOOL cli_null_set_signing(struct cli_state *cli)
-{
- cli->sign_info.signing_context = NULL;
-
- cli->sign_info.sign_outgoing_message = cli_null_sign_outgoing_message;
- cli->sign_info.check_incoming_message = cli_null_check_incoming_message;
- cli->sign_info.free_signing_context = cli_null_free_signing_context;
-
- return True;
+ data->send_seq_num += 2;
}
/***********************************************************
SMB signing - TEMP implementation - calculate a MAC to send.
************************************************************/
-static void cli_temp_sign_outgoing_message(struct cli_state *cli)
+static void temp_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
{
/* mark the packet as signed - BEFORE we sign it...*/
- cli_mark_packet_signed(cli);
+ mark_packet_signed(outbuf);
/* I wonder what BSRSPYL stands for - but this is what MS
actually sends! */
- memcpy(&cli->outbuf[smb_ss_field], "BSRSPYL ", 8);
+ memcpy(&outbuf[smb_ss_field], "BSRSPYL ", 8);
return;
}
@@ -377,7 +539,7 @@ static void cli_temp_sign_outgoing_message(struct cli_state *cli)
SMB signing - TEMP implementation - check a MAC sent by server.
************************************************************/
-static BOOL cli_temp_check_incoming_message(struct cli_state *cli)
+static BOOL temp_check_incoming_message(char *inbuf, struct smb_sign_info *si)
{
return True;
}
@@ -386,7 +548,7 @@ static BOOL cli_temp_check_incoming_message(struct cli_state *cli)
SMB signing - TEMP implementation - free signing context
************************************************************/
-static void cli_temp_free_signing_context(struct cli_state *cli)
+static void temp_free_signing_context(struct smb_sign_info *si)
{
return;
}
@@ -395,6 +557,15 @@ static void cli_temp_free_signing_context(struct cli_state *cli)
SMB signing - NULL implementation - setup the MAC key.
************************************************************/
+BOOL cli_null_set_signing(struct cli_state *cli)
+{
+ return null_set_signing(&cli->sign_info);
+}
+
+/***********************************************************
+ SMB signing - temp implementation - setup the MAC key.
+************************************************************/
+
BOOL cli_temp_set_signing(struct cli_state *cli)
{
if (!cli_set_smb_signing_common(cli)) {
@@ -403,23 +574,16 @@ BOOL cli_temp_set_signing(struct cli_state *cli)
cli->sign_info.signing_context = NULL;
- cli->sign_info.sign_outgoing_message = cli_temp_sign_outgoing_message;
- cli->sign_info.check_incoming_message = cli_temp_check_incoming_message;
- cli->sign_info.free_signing_context = cli_temp_free_signing_context;
+ cli->sign_info.sign_outgoing_message = temp_sign_outgoing_message;
+ cli->sign_info.check_incoming_message = temp_check_incoming_message;
+ cli->sign_info.free_signing_context = temp_free_signing_context;
return True;
}
-/**
- * Free the signing context
- */
-
-void cli_free_signing_context(struct cli_state *cli)
+void cli_free_signing_context(struct cli_state *cli)
{
- if (cli->sign_info.free_signing_context)
- cli->sign_info.free_signing_context(cli);
-
- cli_null_set_signing(cli);
+ free_signing_context(&cli->sign_info);
}
/**
@@ -428,33 +592,403 @@ void cli_free_signing_context(struct cli_state *cli)
void cli_calculate_sign_mac(struct cli_state *cli)
{
- cli->sign_info.sign_outgoing_message(cli);
+ cli->sign_info.sign_outgoing_message(cli->outbuf, &cli->sign_info);
}
/**
* Check a packet with the current mechanism
* @return False if we had an established signing connection
- * which had a back checksum, True otherwise
+ * which had a bad checksum, True otherwise.
*/
BOOL cli_check_sign_mac(struct cli_state *cli)
{
+ if (!cli->sign_info.check_incoming_message(cli->inbuf, &cli->sign_info)) {
+ free_signing_context(&cli->sign_info);
+ return False;
+ }
+ return True;
+}
+
+/***********************************************************
+ SMB signing - Server implementation - send the MAC.
+************************************************************/
+
+static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
+{
+ unsigned char calc_md5_mac[16];
+ struct smb_basic_signing_context *data = si->signing_context;
+ uint32 send_seq_number = data->send_seq_num;
+ BOOL was_deferred_packet = False;
+ uint16 mid;
+
+ if (!si->doing_signing) {
+ return;
+ }
+
+ /* JRA Paranioa test - we should be able to get rid of this... */
+ if (smb_len(outbuf) < (smb_ss_field + 8 - 4)) {
+ DEBUG(1, ("srv_sign_outgoing_message: Logic error. Can't send signature on short packet! smb_len = %u\n",
+ smb_len(outbuf) ));
+ abort();
+ }
+
+ /* mark the packet as signed - BEFORE we sign it...*/
+ mark_packet_signed(outbuf);
+
+ mid = SVAL(outbuf, smb_mid);
+
+ /* See if this is a reply for a deferred packet. */
+ get_sequence_for_reply(&data->outstanding_packet_list, mid, &send_seq_number, &was_deferred_packet);
+
+ if (data->trans_info && (data->trans_info->mid == mid)) {
+ /* This is a reply in a trans stream. Use the sequence
+ * number associated with the stream mid. */
+ send_seq_number = data->trans_info->send_seq_num;
+ }
+
+ simple_packet_signature(data, (const unsigned char *)outbuf, send_seq_number, calc_md5_mac);
+
+ DEBUG(10, ("srv_sign_outgoing_message: seq %u: sent SMB signature of\n", (unsigned int)send_seq_number));
+ dump_data(10, (const char *)calc_md5_mac, 8);
+
+ memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8);
+
+/* cli->outbuf[smb_ss_field+2]=0;
+ Uncomment this to test if the remote server actually verifies signatures...*/
+
+ if (!was_deferred_packet) {
+ if (!data->trans_info) {
+ /* Always increment if not in a trans stream. */
+ data->send_seq_num++;
+ } else if ((data->trans_info->send_seq_num == data->send_seq_num) || (data->trans_info->mid != mid)) {
+ /* Increment if this is the first reply in a trans stream or a
+ * packet that doesn't belong to this stream (different mid). */
+ data->send_seq_num++;
+ }
+ }
+}
+
+/***********************************************************
+ Is an incoming packet an oplock break reply ?
+************************************************************/
+
+static BOOL is_oplock_break(char *inbuf)
+{
+ if (CVAL(inbuf,smb_com) != SMBlockingX)
+ return False;
+
+ if (!(CVAL(inbuf,smb_vwv3) & LOCKING_ANDX_OPLOCK_RELEASE))
+ return False;
+
+ DEBUG(10,("is_oplock_break: Packet is oplock break\n"));
+ return True;
+}
+
+/***********************************************************
+ SMB signing - Server implementation - check a MAC sent by server.
+************************************************************/
+
+static BOOL srv_check_incoming_message(char *inbuf, struct smb_sign_info *si)
+{
BOOL good;
+ struct smb_basic_signing_context *data = si->signing_context;
+ uint32 reply_seq_number = data->send_seq_num;
+ uint32 saved_seq;
+ unsigned char calc_md5_mac[16];
+ unsigned char *server_sent_mac;
+ uint mid;
+
+ if (!si->doing_signing)
+ return True;
+
+ if (smb_len(inbuf) < (smb_ss_field + 8 - 4)) {
+ DEBUG(1, ("srv_check_incoming_message: Can't check signature on short packet! smb_len = %u\n", smb_len(inbuf)));
+ return False;
+ }
+
+ mid = SVAL(inbuf, smb_mid);
- if (smb_len(cli->inbuf) < (smb_ss_field + 8 - 4)) {
- DEBUG(cli->sign_info.doing_signing ? 1 : 10, ("Can't check signature on short packet! smb_len = %u\n", smb_len(cli->inbuf)));
- good = False;
+ /* Is this part of a trans stream ? */
+ if (data->trans_info && (data->trans_info->mid == mid)) {
+ /* If so we don't increment the sequence. */
+ reply_seq_number = data->trans_info->reply_seq_num;
} else {
- good = cli->sign_info.check_incoming_message(cli);
+ /* We always increment the sequence number. */
+ data->send_seq_num++;
+
+ /* If we get an asynchronous oplock break reply and there
+ * isn't a reply pending we need to re-sync the sequence
+ * number.
+ */
+ if (is_oplock_break(inbuf) && !is_reply_pending(data->outstanding_packet_list))
+ data->send_seq_num++;
}
+ saved_seq = reply_seq_number;
+ simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
+
+ server_sent_mac = (unsigned char *)&inbuf[smb_ss_field];
+ good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
+
if (!good) {
- if (cli->sign_info.doing_signing) {
- return False;
- } else {
- cli_free_signing_context(cli);
+
+ DEBUG(5, ("srv_check_incoming_message: BAD SIG: seq %u wanted SMB signature of\n",
+ (unsigned int)saved_seq));
+ dump_data(5, (const char *)calc_md5_mac, 8);
+
+ DEBUG(5, ("srv_check_incoming_message: BAD SIG: seq %u got SMB signature of\n",
+ (unsigned int)saved_seq));
+ dump_data(5, (const char *)server_sent_mac, 8);
+
+#if 1 /* JRATEST */
+ {
+ int i;
+ reply_seq_number -= 5;
+ for (i = 0; i < 10; i++, reply_seq_number++) {
+ simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
+ if (memcmp(server_sent_mac, calc_md5_mac, 8) == 0) {
+ DEBUG(0,("srv_check_incoming_message: out of seq. seq num %u matches.\n",
+ reply_seq_number ));
+ break;
+ }
+ }
}
+#endif /* JRATEST */
+
+ } else {
+ DEBUG(10, ("srv_check_incoming_message: seq %u: (current is %u) got good SMB signature of\n", (unsigned int)reply_seq_number, (unsigned int)data->send_seq_num));
+ dump_data(10, (const char *)server_sent_mac, 8);
}
+ return signing_good(inbuf, si, good, saved_seq);
+}
- return True;
+/***********************************************************
+ SMB signing - server API's.
+************************************************************/
+
+static struct smb_sign_info srv_sign_info = {
+ null_sign_outgoing_message,
+ null_check_incoming_message,
+ null_free_signing_context,
+ NULL,
+ False,
+ False,
+ False,
+ False
+};
+
+/***********************************************************
+ Turn signing off or on for oplock break code.
+************************************************************/
+
+BOOL srv_oplock_set_signing(BOOL onoff)
+{
+ BOOL ret = srv_sign_info.doing_signing;
+ srv_sign_info.doing_signing = onoff;
+ return ret;
+}
+
+/***********************************************************
+ Called to validate an incoming packet from the client.
+************************************************************/
+
+BOOL srv_check_sign_mac(char *inbuf)
+{
+ /* Check if it's a session keepalive. */
+ if(CVAL(inbuf,0) == SMBkeepalive)
+ return True;
+
+ return srv_sign_info.check_incoming_message(inbuf, &srv_sign_info);
+}
+
+/***********************************************************
+ Called to sign an outgoing packet to the client.
+************************************************************/
+
+void srv_calculate_sign_mac(char *outbuf)
+{
+ /* Check if it's a session keepalive. */
+ /* JRA Paranioa test - do we ever generate these in the server ? */
+ if(CVAL(outbuf,0) == SMBkeepalive)
+ return;
+
+ srv_sign_info.sign_outgoing_message(outbuf, &srv_sign_info);
+}
+
+/***********************************************************
+ Called by server to defer an outgoing packet.
+************************************************************/
+
+void srv_defer_sign_response(uint16 mid, BOOL deferred_packet)
+{
+ struct smb_basic_signing_context *data;
+
+ if (!srv_sign_info.doing_signing)
+ return;
+
+ data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
+
+ if (!data)
+ return;
+
+ store_sequence_for_reply(&data->outstanding_packet_list,
+ mid, data->send_seq_num, deferred_packet);
+ data->send_seq_num++;
+}
+
+/***********************************************************
+ Called to remove sequence records when a deferred packet is
+ cancelled by mid. This should never find one....
+************************************************************/
+
+void srv_cancel_sign_response(uint16 mid)
+{
+ struct smb_basic_signing_context *data;
+ uint32 dummy_seq;
+
+ if (!srv_sign_info.doing_signing)
+ return;
+
+ data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
+
+ if (!data)
+ return;
+
+ DEBUG(10,("srv_cancel_sign_response: for mid %u\n", (unsigned int)mid ));
+
+ while (get_sequence_for_reply(&data->outstanding_packet_list, mid, &dummy_seq,NULL))
+ ;
+}
+
+/***********************************************************
+ Called by server negprot when signing has been negotiated.
+************************************************************/
+
+void srv_set_signing_negotiated(void)
+{
+ srv_sign_info.allow_smb_signing = True;
+ srv_sign_info.negotiated_smb_signing = True;
+ if (lp_server_signing() == Required)
+ srv_sign_info.mandatory_signing = True;
+
+ srv_sign_info.sign_outgoing_message = temp_sign_outgoing_message;
+ srv_sign_info.check_incoming_message = temp_check_incoming_message;
+ srv_sign_info.free_signing_context = temp_free_signing_context;
+}
+
+/***********************************************************
+ Returns whether signing is active. We can't use sendfile or raw
+ reads/writes if it is.
+************************************************************/
+
+BOOL srv_is_signing_active(void)
+{
+ return srv_sign_info.doing_signing;
+}
+
+/***********************************************************
+ Tell server code we are in a multiple trans reply state.
+************************************************************/
+
+void srv_signing_trans_start(uint16 mid)
+{
+ struct smb_basic_signing_context *data;
+
+ if (!srv_sign_info.doing_signing)
+ return;
+
+ data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
+ if (!data)
+ return;
+
+ data->trans_info = smb_xmalloc(sizeof(struct trans_info_context));
+ ZERO_STRUCTP(data->trans_info);
+
+ data->trans_info->reply_seq_num = data->send_seq_num-1;
+ data->trans_info->mid = mid;
+ data->trans_info->send_seq_num = data->send_seq_num;
+
+ DEBUG(10,("srv_signing_trans_start: storing mid = %u, reply_seq_num = %u, send_seq_num = %u \
+data->send_seq_num = %u\n",
+ (unsigned int)mid,
+ (unsigned int)data->trans_info->reply_seq_num,
+ (unsigned int)data->trans_info->send_seq_num,
+ (unsigned int)data->send_seq_num ));
+}
+
+/***********************************************************
+ Tell server code we are out of a multiple trans reply state.
+************************************************************/
+
+void srv_signing_trans_stop(void)
+{
+ struct smb_basic_signing_context *data;
+
+ if (!srv_sign_info.doing_signing)
+ return;
+
+ data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
+ if (!data || !data->trans_info)
+ return;
+
+ DEBUG(10,("srv_signing_trans_stop: removing mid = %u, reply_seq_num = %u, send_seq_num = %u \
+data->send_seq_num = %u\n",
+ (unsigned int)data->trans_info->mid,
+ (unsigned int)data->trans_info->reply_seq_num,
+ (unsigned int)data->trans_info->send_seq_num,
+ (unsigned int)data->send_seq_num ));
+
+ SAFE_FREE(data->trans_info);
+ data->trans_info = NULL;
+}
+
+/***********************************************************
+ Turn on signing from this packet onwards.
+************************************************************/
+
+void srv_set_signing(const uchar user_session_key[16], const DATA_BLOB response)
+{
+ struct smb_basic_signing_context *data;
+
+ if (!user_session_key)
+ return;
+
+ if (!srv_sign_info.negotiated_smb_signing && !srv_sign_info.mandatory_signing) {
+ DEBUG(5,("srv_set_signing: signing negotiated = %u, mandatory_signing = %u. Not allowing smb signing.\n",
+ (unsigned int)srv_sign_info.negotiated_smb_signing,
+ (unsigned int)srv_sign_info.mandatory_signing ));
+ return;
+ }
+
+ /* Once we've turned on, ignore any more sessionsetups. */
+ if (srv_sign_info.doing_signing) {
+ return;
+ }
+
+ if (srv_sign_info.free_signing_context)
+ srv_sign_info.free_signing_context(&srv_sign_info);
+
+ srv_sign_info.doing_signing = True;
+
+ data = smb_xmalloc(sizeof(*data));
+ memset(data, '\0', sizeof(*data));
+
+ srv_sign_info.signing_context = data;
+
+ data->mac_key = data_blob(NULL, response.length + 16);
+
+ memcpy(&data->mac_key.data[0], user_session_key, 16);
+ if (response.length)
+ memcpy(&data->mac_key.data[16],response.data, response.length);
+
+ /* Initialise the sequence number */
+ data->send_seq_num = 0;
+
+ /* Initialise the list of outstanding packets */
+ data->outstanding_packet_list = NULL;
+
+ srv_sign_info.sign_outgoing_message = srv_sign_outgoing_message;
+ srv_sign_info.check_incoming_message = srv_check_incoming_message;
+ srv_sign_info.free_signing_context = simple_free_signing_context;
}
diff --git a/source/libsmb/smbencrypt.c b/source/libsmb/smbencrypt.c
index 7a1a2d7d189..ec31bb5dbaa 100644
--- a/source/libsmb/smbencrypt.c
+++ b/source/libsmb/smbencrypt.c
@@ -81,7 +81,7 @@ void E_deshash(const char *passwd, uchar p16[16])
push_ascii(dospwd, passwd, sizeof(dospwd), STR_UPPER|STR_TERMINATE);
/* Only the fisrt 14 chars are considered, password need not be null terminated. */
- E_P16(dospwd, p16);
+ E_P16((const unsigned char *)dospwd, p16);
ZERO_STRUCT(dospwd);
}
@@ -247,7 +247,7 @@ BOOL make_oem_passwd_hash(char data[516], const char *passwd, uchar old_pw_hash[
return True;
}
-/* Does the md5 encryption from the NT hash for NTLMv2. */
+/* Does the md5 encryption from the Key Response for NTLMv2. */
void SMBOWFencrypt_ntv2(const uchar kr[16],
const DATA_BLOB *srv_chal,
const DATA_BLOB *cli_chal,
diff --git a/source/libsmb/spnego.c b/source/libsmb/spnego.c
new file mode 100644
index 00000000000..50caf7b4c0e
--- /dev/null
+++ b/source/libsmb/spnego.c
@@ -0,0 +1,343 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ RFC2478 Compliant SPNEGO implementation
+
+ Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
+
+ 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.
+*/
+
+#include "includes.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_AUTH
+
+static BOOL read_negTokenInit(ASN1_DATA *asn1, negTokenInit_t *token)
+{
+ ZERO_STRUCTP(token);
+
+ asn1_start_tag(asn1, ASN1_CONTEXT(0));
+ asn1_start_tag(asn1, ASN1_SEQUENCE(0));
+
+ while (!asn1->has_error && 0 < asn1_tag_remaining(asn1)) {
+ int i;
+
+ switch (asn1->data[asn1->ofs]) {
+ /* Read mechTypes */
+ case ASN1_CONTEXT(0):
+ asn1_start_tag(asn1, ASN1_CONTEXT(0));
+ asn1_start_tag(asn1, ASN1_SEQUENCE(0));
+
+ token->mechTypes = malloc(sizeof(*token->mechTypes));
+ for (i = 0; !asn1->has_error &&
+ 0 < asn1_tag_remaining(asn1); i++) {
+ token->mechTypes =
+ realloc(token->mechTypes, (i + 2) *
+ sizeof(*token->mechTypes));
+ asn1_read_OID(asn1, token->mechTypes + i);
+ }
+ token->mechTypes[i] = NULL;
+
+ asn1_end_tag(asn1);
+ asn1_end_tag(asn1);
+ break;
+ /* Read reqFlags */
+ case ASN1_CONTEXT(1):
+ asn1_start_tag(asn1, ASN1_CONTEXT(1));
+ asn1_read_Integer(asn1, &token->reqFlags);
+ token->reqFlags |= SPNEGO_REQ_FLAG;
+ asn1_end_tag(asn1);
+ break;
+ /* Read mechToken */
+ case ASN1_CONTEXT(2):
+ asn1_start_tag(asn1, ASN1_CONTEXT(2));
+ asn1_read_OctetString(asn1, &token->mechToken);
+ asn1_end_tag(asn1);
+ break;
+ /* Read mecListMIC */
+ case ASN1_CONTEXT(3):
+ asn1_start_tag(asn1, ASN1_CONTEXT(3));
+ if (asn1->data[asn1->ofs] == ASN1_OCTET_STRING) {
+ asn1_read_OctetString(asn1,
+ &token->mechListMIC);
+ } else {
+ /* RFC 2478 says we have an Octet String here,
+ but W2k sends something different... */
+ char *mechListMIC;
+ asn1_push_tag(asn1, ASN1_SEQUENCE(0));
+ asn1_push_tag(asn1, ASN1_CONTEXT(0));
+ asn1_read_GeneralString(asn1, &mechListMIC);
+ asn1_pop_tag(asn1);
+ asn1_pop_tag(asn1);
+
+ token->mechListMIC =
+ data_blob(mechListMIC, strlen(mechListMIC));
+ SAFE_FREE(mechListMIC);
+ }
+ asn1_end_tag(asn1);
+ break;
+ default:
+ asn1->has_error = True;
+ break;
+ }
+ }
+
+ asn1_end_tag(asn1);
+ asn1_end_tag(asn1);
+
+ return !asn1->has_error;
+}
+
+static BOOL write_negTokenInit(ASN1_DATA *asn1, negTokenInit_t *token)
+{
+ asn1_push_tag(asn1, ASN1_CONTEXT(0));
+ asn1_push_tag(asn1, ASN1_SEQUENCE(0));
+
+ /* Write mechTypes */
+ if (token->mechTypes && *token->mechTypes) {
+ int i;
+
+ asn1_push_tag(asn1, ASN1_CONTEXT(0));
+ asn1_push_tag(asn1, ASN1_SEQUENCE(0));
+ for (i = 0; token->mechTypes[i]; i++) {
+ asn1_write_OID(asn1, token->mechTypes[i]);
+ }
+ asn1_pop_tag(asn1);
+ asn1_pop_tag(asn1);
+ }
+
+ /* write reqFlags */
+ if (token->reqFlags & SPNEGO_REQ_FLAG) {
+ int flags = token->reqFlags & ~SPNEGO_REQ_FLAG;
+
+ asn1_push_tag(asn1, ASN1_CONTEXT(1));
+ asn1_write_Integer(asn1, flags);
+ asn1_pop_tag(asn1);
+ }
+
+ /* write mechToken */
+ if (token->mechToken.data) {
+ asn1_push_tag(asn1, ASN1_CONTEXT(2));
+ asn1_write_OctetString(asn1, token->mechToken.data,
+ token->mechToken.length);
+ asn1_pop_tag(asn1);
+ }
+
+ /* write mechListMIC */
+ if (token->mechListMIC.data) {
+ asn1_push_tag(asn1, ASN1_CONTEXT(3));
+#if 0
+ /* This is what RFC 2478 says ... */
+ asn1_write_OctetString(asn1, token->mechListMIC.data,
+ token->mechListMIC.length);
+#else
+ /* ... but unfortunately this is what Windows
+ sends/expects */
+ asn1_push_tag(asn1, ASN1_SEQUENCE(0));
+ asn1_push_tag(asn1, ASN1_CONTEXT(0));
+ asn1_push_tag(asn1, ASN1_GENERAL_STRING);
+ asn1_write(asn1, token->mechListMIC.data,
+ token->mechListMIC.length);
+ asn1_pop_tag(asn1);
+ asn1_pop_tag(asn1);
+ asn1_pop_tag(asn1);
+#endif
+ asn1_pop_tag(asn1);
+ }
+
+ asn1_pop_tag(asn1);
+ asn1_pop_tag(asn1);
+
+ return !asn1->has_error;
+}
+
+static BOOL read_negTokenTarg(ASN1_DATA *asn1, negTokenTarg_t *token)
+{
+ ZERO_STRUCTP(token);
+
+ asn1_start_tag(asn1, ASN1_CONTEXT(1));
+ asn1_start_tag(asn1, ASN1_SEQUENCE(0));
+
+ while (!asn1->has_error && 0 < asn1_tag_remaining(asn1)) {
+ switch (asn1->data[asn1->ofs]) {
+ case ASN1_CONTEXT(0):
+ asn1_start_tag(asn1, ASN1_CONTEXT(0));
+ asn1_start_tag(asn1, ASN1_ENUMERATED);
+ asn1_read_uint8(asn1, &token->negResult);
+ asn1_end_tag(asn1);
+ asn1_end_tag(asn1);
+ break;
+ case ASN1_CONTEXT(1):
+ asn1_start_tag(asn1, ASN1_CONTEXT(1));
+ asn1_read_OID(asn1, &token->supportedMech);
+ asn1_end_tag(asn1);
+ break;
+ case ASN1_CONTEXT(2):
+ asn1_start_tag(asn1, ASN1_CONTEXT(2));
+ asn1_read_OctetString(asn1, &token->responseToken);
+ asn1_end_tag(asn1);
+ break;
+ case ASN1_CONTEXT(3):
+ asn1_start_tag(asn1, ASN1_CONTEXT(3));
+ asn1_read_OctetString(asn1, &token->mechListMIC);
+ asn1_end_tag(asn1);
+ break;
+ default:
+ asn1->has_error = True;
+ break;
+ }
+ }
+
+ asn1_end_tag(asn1);
+ asn1_end_tag(asn1);
+
+ return !asn1->has_error;
+}
+
+static BOOL write_negTokenTarg(ASN1_DATA *asn1, negTokenTarg_t *token)
+{
+ asn1_push_tag(asn1, ASN1_CONTEXT(1));
+ asn1_push_tag(asn1, ASN1_SEQUENCE(0));
+
+ asn1_push_tag(asn1, ASN1_CONTEXT(0));
+ asn1_write_enumerated(asn1, token->negResult);
+ asn1_pop_tag(asn1);
+
+ if (token->supportedMech) {
+ asn1_push_tag(asn1, ASN1_CONTEXT(1));
+ asn1_write_OID(asn1, token->supportedMech);
+ asn1_pop_tag(asn1);
+ }
+
+ if (token->responseToken.data) {
+ asn1_push_tag(asn1, ASN1_CONTEXT(2));
+ asn1_write_OctetString(asn1, token->responseToken.data,
+ token->responseToken.length);
+ asn1_pop_tag(asn1);
+ }
+
+ if (token->mechListMIC.data) {
+ asn1_push_tag(asn1, ASN1_CONTEXT(3));
+ asn1_write_OctetString(asn1, token->mechListMIC.data,
+ token->mechListMIC.length);
+ asn1_pop_tag(asn1);
+ }
+
+ asn1_pop_tag(asn1);
+ asn1_pop_tag(asn1);
+
+ return !asn1->has_error;
+}
+
+ssize_t read_spnego_data(DATA_BLOB data, SPNEGO_DATA *token)
+{
+ ASN1_DATA asn1;
+ ssize_t ret = -1;
+
+ ZERO_STRUCTP(token);
+ ZERO_STRUCT(asn1);
+ asn1_load(&asn1, data);
+
+ switch (asn1.data[asn1.ofs]) {
+ case ASN1_APPLICATION(0):
+ asn1_start_tag(&asn1, ASN1_APPLICATION(0));
+ asn1_check_OID(&asn1, OID_SPNEGO);
+ if (read_negTokenInit(&asn1, &token->negTokenInit)) {
+ token->type = SPNEGO_NEG_TOKEN_INIT;
+ }
+ asn1_end_tag(&asn1);
+ break;
+ case ASN1_CONTEXT(1):
+ if (read_negTokenTarg(&asn1, &token->negTokenTarg)) {
+ token->type = SPNEGO_NEG_TOKEN_TARG;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (!asn1.has_error) ret = asn1.ofs;
+ asn1_free(&asn1);
+
+ return ret;
+}
+
+ssize_t write_spnego_data(DATA_BLOB *blob, SPNEGO_DATA *spnego)
+{
+ ASN1_DATA asn1;
+ ssize_t ret = -1;
+
+ ZERO_STRUCT(asn1);
+
+ switch (spnego->type) {
+ case SPNEGO_NEG_TOKEN_INIT:
+ asn1_push_tag(&asn1, ASN1_APPLICATION(0));
+ asn1_write_OID(&asn1, OID_SPNEGO);
+ write_negTokenInit(&asn1, &spnego->negTokenInit);
+ asn1_pop_tag(&asn1);
+ break;
+ case SPNEGO_NEG_TOKEN_TARG:
+ write_negTokenTarg(&asn1, &spnego->negTokenTarg);
+ break;
+ default:
+ asn1.has_error = True;
+ break;
+ }
+
+ if (!asn1.has_error) {
+ *blob = data_blob(asn1.data, asn1.length);
+ ret = asn1.ofs;
+ }
+ asn1_free(&asn1);
+
+ return ret;
+}
+
+BOOL free_spnego_data(SPNEGO_DATA *spnego)
+{
+ BOOL ret = True;
+
+ if (!spnego) goto out;
+
+ switch(spnego->type) {
+ case SPNEGO_NEG_TOKEN_INIT:
+ if (spnego->negTokenInit.mechTypes) {
+ int i;
+ for (i = 0; spnego->negTokenInit.mechTypes[i]; i++) {
+ free(spnego->negTokenInit.mechTypes[i]);
+ }
+ free(spnego->negTokenInit.mechTypes);
+ }
+ data_blob_free(&spnego->negTokenInit.mechToken);
+ data_blob_free(&spnego->negTokenInit.mechListMIC);
+ break;
+ case SPNEGO_NEG_TOKEN_TARG:
+ if (spnego->negTokenTarg.supportedMech) {
+ free(spnego->negTokenTarg.supportedMech);
+ }
+ data_blob_free(&spnego->negTokenTarg.responseToken);
+ data_blob_free(&spnego->negTokenTarg.mechListMIC);
+ break;
+ default:
+ ret = False;
+ break;
+ }
+ ZERO_STRUCTP(spnego);
+out:
+ return ret;
+}
+
diff --git a/source/libsmb/trustdom_cache.c b/source/libsmb/trustdom_cache.c
index 83781250880..0128d080062 100644
--- a/source/libsmb/trustdom_cache.c
+++ b/source/libsmb/trustdom_cache.c
@@ -223,7 +223,7 @@ BOOL trustdom_cache_store_timestamp( uint32 t, time_t timeout )
if (!gencache_init())
return False;
- snprintf(value, sizeof(value), "%d", t );
+ fstr_sprintf(value, "%d", t );
if (!gencache_set(TDOMTSKEY, value, timeout)) {
DEBUG(5, ("failed to set timestamp for trustdom_cache\n"));
diff --git a/source/libsmb/trusts_util.c b/source/libsmb/trusts_util.c
index 77e63709aac..610f4b3c031 100644
--- a/source/libsmb/trusts_util.c
+++ b/source/libsmb/trusts_util.c
@@ -154,7 +154,7 @@ BOOL enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain,
/* setup the anonymous connection */
result = cli_full_connection( &cli, global_myname(), dc_name, &dc_ip, 0, "IPC$", "IPC",
- "", "", "", 0, &retry);
+ "", "", "", 0, Undefined, &retry);
if ( !NT_STATUS_IS_OK(result) )
goto done;