summaryrefslogtreecommitdiff
path: root/source3/libsmb
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2003-09-09 04:07:32 +0000
committerGerald Carter <jerry@samba.org>2003-09-09 04:07:32 +0000
commit4093bf7ff8c8861cf7b941945ede53a8ec5bb6c8 (patch)
treedd0a9f32d9933e1f75d919b5083e007d7453f9c4 /source3/libsmb
parent3d7cb49747a9a7f5cdec0ee05c6270ec3604202f (diff)
downloadsamba-4093bf7ff8c8861cf7b941945ede53a8ec5bb6c8.tar.gz
samba-4093bf7ff8c8861cf7b941945ede53a8ec5bb6c8.tar.bz2
samba-4093bf7ff8c8861cf7b941945ede53a8ec5bb6c8.zip
sync 3.0 into HEAD for the last time
(This used to be commit c17a7dc9a190156a069da3e861c18fd3f81224ad)
Diffstat (limited to 'source3/libsmb')
-rw-r--r--source3/libsmb/cliconnect.c114
-rw-r--r--source3/libsmb/clientgen.c7
-rw-r--r--source3/libsmb/clifile.c5
-rw-r--r--source3/libsmb/clikrb5.c20
-rw-r--r--source3/libsmb/climessage.c2
-rw-r--r--source3/libsmb/cliprint.c5
-rw-r--r--source3/libsmb/clirap.c10
-rw-r--r--source3/libsmb/clirap2.c63
-rw-r--r--source3/libsmb/clireadwrite.c2
-rw-r--r--source3/libsmb/clisecdesc.c4
-rw-r--r--source3/libsmb/clispnego.c3
-rw-r--r--source3/libsmb/namequery.c2
-rw-r--r--source3/libsmb/namequery_dc.c16
-rw-r--r--source3/libsmb/nmblib.c34
-rw-r--r--source3/libsmb/ntlmssp.c102
-rw-r--r--source3/libsmb/ntlmssp_parse.c3
-rw-r--r--source3/libsmb/ntlmssp_sign.c24
-rw-r--r--source3/libsmb/smb_signing.c160
-rw-r--r--source3/libsmb/smbencrypt.c4
-rw-r--r--source3/libsmb/spnego.c343
-rw-r--r--source3/libsmb/trusts_util.c9
21 files changed, 712 insertions, 220 deletions
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 94fe04a480..48bcb61f92 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -190,7 +190,7 @@ static BOOL cli_session_setup_plaintext(struct cli_state *cli, const char *user,
char *p;
fstring lanman;
- fstr_sprintf( lanman, "Samba %s", VERSION );
+ fstr_sprintf( lanman, "Samba %s", SAMBA_VERSION_STRING);
set_message(cli->outbuf,13,0,True);
SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
@@ -247,7 +247,8 @@ static void set_cli_session_key (struct cli_state *cli, DATA_BLOB session_key)
}
/****************************************************************************
- do a NT1 NTLM/LM encrypted session setup
+ do a NT1 NTLM/LM encrypted session setup - for when extended security
+ is not negotiated.
@param cli client state to create do session setup on
@param user username
@param pass *either* cleartext password (passlen !=24) or LM response.
@@ -267,7 +268,9 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user,
BOOL ret = False;
char *p;
- if (passlen != 24) {
+ if (passlen == 0) {
+ /* do nothing - guest login */
+ } else if (passlen != 24) {
if (lp_client_ntlmv2_auth()) {
DATA_BLOB server_chal;
DATA_BLOB names_blob;
@@ -351,7 +354,7 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user,
goto end;
}
- show_msg(cli->inbuf);
+ /* show_msg(cli->inbuf); */
if (cli_is_error(cli)) {
ret = False;
@@ -610,6 +613,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);
}
@@ -619,7 +623,7 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
if (!NT_STATUS_IS_OK(ntlmssp_client_end(&ntlmssp_state))) {
return False;
}
-
+
return (NT_STATUS_IS_OK(nt_status));
}
@@ -627,8 +631,8 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
Do a spnego encrypted session setup.
****************************************************************************/
-static BOOL cli_session_setup_spnego(struct cli_state *cli, const char *user,
- const char *pass, const char *workgroup)
+BOOL cli_session_setup_spnego(struct cli_state *cli, const char *user,
+ const char *pass, const char *workgroup)
{
char *principal;
char *OIDs[ASN1_MAX_OIDS];
@@ -677,7 +681,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();
@@ -1024,22 +1028,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. */
+ /*
+ * 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) {
@@ -1223,7 +1232,7 @@ BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
Initialise client credentials for authenticated pipe access.
****************************************************************************/
-static void init_creds(struct ntuser_creds *creds, const char* username,
+void init_creds(struct ntuser_creds *creds, const char* username,
const char* domain, const char* password)
{
ZERO_STRUCTP(creds);
@@ -1239,30 +1248,21 @@ static void init_creds(struct ntuser_creds *creds, const char* username,
}
/**
- establishes a connection right up to doing tconX, password specified.
+ establishes a connection to after the negprot.
@param output_cli A fully initialised cli structure, non-null only on success
@param dest_host The netbios name of the remote host
@param dest_ip (optional) The the destination IP, NULL for name based lookup
@param port (optional) The destination port (0 for default)
- @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
- @param service_type The 'type' of serivice.
- @param user Username, unix string
- @param domain User's domain
- @param password User's password, unencrypted unix string.
@param retry BOOL. Did this connection fail with a retryable error ?
-*/
-NTSTATUS cli_full_connection(struct cli_state **output_cli,
- const char *my_name,
- const char *dest_host,
- struct in_addr *dest_ip, int port,
- const char *service, const char *service_type,
- const char *user, const char *domain,
- const char *password, int flags,
- int signing_state,
- BOOL *retry)
+*/
+NTSTATUS cli_start_connection(struct cli_state **output_cli,
+ const char *my_name,
+ const char *dest_host,
+ struct in_addr *dest_ip, int port,
+ int signing_state, int flags,
+ BOOL *retry)
{
- struct ntuser_creds creds;
NTSTATUS nt_status;
struct nmb_name calling;
struct nmb_name called;
@@ -1295,7 +1295,7 @@ NTSTATUS cli_full_connection(struct cli_state **output_cli,
again:
- DEBUG(3,("Connecting to host=%s share=%s\n", dest_host, service));
+ DEBUG(3,("Connecting to host=%s\n", dest_host));
if (!cli_connect(cli, dest_host, &ip)) {
DEBUG(1,("cli_full_connection: failed to connect to %s (%s)\n",
@@ -1336,6 +1336,46 @@ again:
return nt_status;
}
+ *output_cli = cli;
+ return NT_STATUS_OK;
+}
+
+
+/**
+ establishes a connection right up to doing tconX, password specified.
+ @param output_cli A fully initialised cli structure, non-null only on success
+ @param dest_host The netbios name of the remote host
+ @param dest_ip (optional) The the destination IP, NULL for name based lookup
+ @param port (optional) The destination port (0 for default)
+ @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
+ @param service_type The 'type' of serivice.
+ @param user Username, unix string
+ @param domain User's domain
+ @param password User's password, unencrypted unix string.
+ @param retry BOOL. Did this connection fail with a retryable error ?
+*/
+
+NTSTATUS cli_full_connection(struct cli_state **output_cli,
+ const char *my_name,
+ const char *dest_host,
+ struct in_addr *dest_ip, int port,
+ const char *service, const char *service_type,
+ const char *user, const char *domain,
+ const char *password, int flags,
+ int signing_state,
+ BOOL *retry)
+{
+ struct ntuser_creds creds;
+ NTSTATUS nt_status;
+ struct cli_state *cli = NULL;
+
+ nt_status = cli_start_connection(&cli, my_name, dest_host,
+ dest_ip, port, signing_state, flags, retry);
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
+ }
+
if (!cli_session_setup(cli, user, password, strlen(password)+1,
password, strlen(password)+1,
domain)) {
diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c
index bc5f1462cc..0a134f715d 100644
--- a/source3/libsmb/clientgen.c
+++ b/source3/libsmb/clientgen.c
@@ -299,9 +299,12 @@ struct cli_state *cli_initialise(struct cli_state *cli)
memset(cli->outbuf, 0, cli->bufsize);
memset(cli->inbuf, 0, cli->bufsize);
+
+#if defined(DEVELOPER)
/* just because we over-allocate, doesn't mean it's right to use it */
clobber_region(FUNCTION_MACRO, __LINE__, cli->outbuf+cli->bufsize, SAFETY_MARGIN);
clobber_region(FUNCTION_MACRO, __LINE__, cli->inbuf+cli->bufsize, SAFETY_MARGIN);
+#endif
/* initialise signing */
cli_null_set_signing(cli);
@@ -339,7 +342,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;
}
diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c
index f021076a46..c7f0cdb84b 100644
--- a/source3/libsmb/clifile.c
+++ b/source3/libsmb/clifile.c
@@ -951,8 +951,9 @@ BOOL cli_chkpath(struct cli_state *cli, const char *path)
char *p;
pstrcpy(path2,path);
- trim_string(path2,NULL,"\\");
- if (!*path2) *path2 = '\\';
+ trim_char(path2,'\0','\\');
+ if (!*path2)
+ *path2 = '\\';
memset(cli->outbuf,'\0',smb_size);
set_message(cli->outbuf,0,0,True);
diff --git a/source3/libsmb/clikrb5.c b/source3/libsmb/clikrb5.c
index beac8cb2c1..1fccc04a01 100644
--- a/source3/libsmb/clikrb5.c
+++ b/source3/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,
@@ -369,29 +371,27 @@ failed:
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
- BOOL ret = False;
krb5_error_code err;
+ BOOL ret = False;
memset(session_key, 0, 16);
-#ifdef ENCTYPE_ARCFOUR_HMAC
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) {
- if (KRB5_KEY_TYPE(skey) ==
- ENCTYPE_ARCFOUR_HMAC
- && KRB5_KEY_LENGTH(skey) == 16) {
+ 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;
}
diff --git a/source3/libsmb/climessage.c b/source3/libsmb/climessage.c
index 8ce8416487..035088212c 100644
--- a/source3/libsmb/climessage.c
+++ b/source3/libsmb/climessage.c
@@ -87,7 +87,7 @@ int cli_message_text_build(struct cli_state *cli, char *msg, int len, int grp)
p = smb_buf(cli->outbuf);
*p++ = 1;
- if ((lendos = convert_string_allocate(CH_UNIX, CH_DOS, msg,len, (void **) &msgdos)) < 0 || !msgdos) {
+ if ((lendos = convert_string_allocate(NULL,CH_UNIX, CH_DOS, msg,len, (void **) &msgdos)) < 0 || !msgdos) {
DEBUG(3,("Conversion failed, sending message in UNIX charset\n"));
SSVAL(p, 0, len); p += 2;
memcpy(p, msg, len);
diff --git a/source3/libsmb/cliprint.c b/source3/libsmb/cliprint.c
index f302c045a5..2fb0e59aca 100644
--- a/source3/libsmb/cliprint.c
+++ b/source3/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;
@@ -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));
diff --git a/source3/libsmb/clirap.c b/source3/libsmb/clirap.c
index a307ac6ccf..79ad38fc8c 100644
--- a/source3/libsmb/clirap.c
+++ b/source3/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/source3/libsmb/clirap2.c b/source3/libsmb/clirap2.c
index 669b33860d..12a3d63aff 100644
--- a/source3/libsmb/clirap2.c
+++ b/source3/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/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c
index 0715aa7f1a..8eac7d07d8 100644
--- a/source3/libsmb/clireadwrite.c
+++ b/source3/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/source3/libsmb/clisecdesc.c b/source3/libsmb/clisecdesc.c
index d86a9022a6..548cd6ec18 100644
--- a/source3/libsmb/clisecdesc.c
+++ b/source3/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/source3/libsmb/clispnego.c b/source3/libsmb/clispnego.c
index b0570b09b6..63076a1a1c 100644
--- a/source3/libsmb/clispnego.c
+++ b/source3/libsmb/clispnego.c
@@ -331,6 +331,9 @@ DATA_BLOB spnego_gen_negTokenTarg(const char *principal, int time_offset, unsign
/* 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/source3/libsmb/namequery.c b/source3/libsmb/namequery.c
index 9875f77c72..1de7413711 100644
--- a/source3/libsmb/namequery.c
+++ b/source3/libsmb/namequery.c
@@ -61,7 +61,7 @@ static struct node_status *parse_node_status(char *p, int *num_names)
p++;
for (i=0;i< *num_names;i++) {
StrnCpy(ret[i].name,p,15);
- trim_string(ret[i].name,NULL," ");
+ trim_char(ret[i].name,'\0',' ');
ret[i].type = CVAL(p,15);
ret[i].flags = p[16];
p += 18;
diff --git a/source3/libsmb/namequery_dc.c b/source3/libsmb/namequery_dc.c
index c9d45a7acc..a596f00ddb 100644
--- a/source3/libsmb/namequery_dc.c
+++ b/source3/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/source3/libsmb/nmblib.c b/source3/libsmb/nmblib.c
index 6ee05f0104..ff38245435 100644
--- a/source3/libsmb/nmblib.c
+++ b/source3/libsmb/nmblib.c
@@ -310,21 +310,24 @@ static int put_nmb_name(char *buf,int offset,struct nmb_name *name)
}
/*******************************************************************
- useful for debugging messages
- ******************************************************************/
+ Useful for debugging messages.
+******************************************************************/
+
char *nmb_namestr(struct nmb_name *n)
{
- static int i=0;
- static fstring ret[4];
- char *p = ret[i];
-
- if (!n->scope[0])
- slprintf(p,sizeof(fstring)-1, "%s<%02x>",n->name,n->name_type);
- else
- slprintf(p,sizeof(fstring)-1, "%s<%02x>.%s",n->name,n->name_type,n->scope);
-
- i = (i+1)%4;
- return(p);
+ static int i=0;
+ static fstring ret[4];
+ fstring name;
+ char *p = ret[i];
+
+ pull_ascii_fstring(name, n->name);
+ if (!n->scope[0])
+ slprintf(p,sizeof(fstring)-1, "%s<%02x>",name,n->name_type);
+ else
+ slprintf(p,sizeof(fstring)-1, "%s<%02x>.%s",name,n->name_type,n->scope);
+
+ i = (i+1)%4;
+ return(p);
}
/*******************************************************************
@@ -820,10 +823,9 @@ static int build_dgram(char *buf,struct packet_struct *p)
void make_nmb_name( struct nmb_name *n, const char *name, int type)
{
memset( (char *)n, '\0', sizeof(struct nmb_name) );
- push_ascii(n->name, name, 16, STR_TERMINATE|STR_UPPER);
+ push_ascii(n->name, name, sizeof(n->name), STR_TERMINATE|STR_UPPER);
n->name_type = (unsigned int)type & 0xFF;
- StrnCpy( n->scope, global_scope(), 63 );
- strupper_m( n->scope );
+ push_ascii(n->scope, global_scope(), 64, STR_TERMINATE);
}
/*******************************************************************
diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c
index a50ae9b70f..42bf18d1d2 100644
--- a/source3/libsmb/ntlmssp.c
+++ b/source3/libsmb/ntlmssp.c
@@ -140,7 +140,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 +172,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,7 +276,7 @@ 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;
}
@@ -412,6 +415,8 @@ static NTSTATUS ntlmssp_client_initial(struct ntlmssp_client_state *ntlmssp_stat
if (ntlmssp_state->use_ntlmv2) {
ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2;
}
+
+ ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2;
/* generate the ntlmssp negotiate packet */
msrpc_gen(next_request, "CddAA",
@@ -446,16 +451,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st
DATA_BLOB lm_response = data_blob(NULL, 0);
DATA_BLOB nt_response = data_blob(NULL, 0);
DATA_BLOB session_key = data_blob(NULL, 0);
- uint8 datagram_sess_key[16];
- size_t datagram_sess_key_len;
-
-#if 0 /* until we know what flag to tigger it on */
- generate_random_buffer(datagram_sess_key, sizeof(datagram_sess_key), False);
- datagram_sess_key_len = sizeof(datagram_sess_key);
-#else
- ZERO_STRUCT(datagram_sess_key);
- datagram_sess_key_len = 0;
-#endif
+ DATA_BLOB encrypted_session_key = data_blob(NULL, 0);
if (!msrpc_parse(&reply, "CdBd",
"NTLMSSP",
@@ -463,7 +459,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;
}
@@ -489,7 +485,9 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st
} else {
chal_parse_string = "CdAdbdd";
}
+
auth_gen_string = "CdBBAAABd";
+
ntlmssp_state->unicode = False;
ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_UNICODE;
ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_OEM;
@@ -513,6 +511,10 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st
ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_128;
}
+ if (!(chal_flags & NTLMSSP_NEGOTIATE_KEY_EXCH)) {
+ ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_KEY_EXCH;
+ }
+
DEBUG(3, ("NTLMSSP: Set final flags:\n"));
debug_ntlmssp_flags(ntlmssp_state->neg_flags);
@@ -525,17 +527,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 +561,38 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st
data_blob_free(&struct_blob);
return NT_STATUS_NO_MEMORY;
}
+ } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
+ struct MD5Context md5_session_nonce_ctx;
+ uchar nt_hash[16];
+ uchar session_nonce[16];
+ uchar session_nonce_hash[16];
+ uchar nt_session_key[16];
+ E_md4hash(ntlmssp_state->password, nt_hash);
+
+ lm_response = data_blob(NULL, 24);
+ generate_random_buffer(lm_response.data, 8, False);
+ memset(lm_response.data+8, 0, 16);
+
+ memcpy(session_nonce, challenge_blob.data, 8);
+ memcpy(&session_nonce[8], lm_response.data, 8);
+
+ 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_hash, &md5_session_nonce_ctx);
+
+ nt_response = data_blob(NULL, 24);
+ SMBNTencrypt(ntlmssp_state->password,
+ session_nonce_hash,
+ nt_response.data);
+
+ session_key = data_blob(NULL, 16);
+
+ SMBsesskeygen_ntv1(nt_hash, NULL, nt_session_key);
+ hmac_md5(nt_session_key, session_nonce, sizeof(session_nonce), session_key.data);
} else {
+
+
uchar lm_hash[16];
uchar nt_hash[16];
E_deshash(ntlmssp_state->password, lm_hash);
@@ -565,15 +603,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 {
@@ -582,6 +620,18 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st
}
data_blob_free(&struct_blob);
+ /* Key exchange encryptes a new client-generated session key with
+ the password-derived key */
+ if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
+ uint8 client_session_key[16];
+
+ generate_random_buffer(client_session_key, sizeof(client_session_key), False);
+ encrypted_session_key = data_blob(client_session_key, sizeof(client_session_key));
+ SamOEMhash(encrypted_session_key.data, session_key.data, encrypted_session_key.length);
+ data_blob_free(&session_key);
+ session_key = data_blob(client_session_key, sizeof(client_session_key));
+ }
+
/* this generates the actual auth packet */
if (!msrpc_gen(next_request, auth_gen_string,
"NTLMSSP",
@@ -591,7 +641,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st
ntlmssp_state->domain,
ntlmssp_state->user,
ntlmssp_state->get_global_myname(),
- datagram_sess_key, datagram_sess_key_len,
+ encrypted_session_key.data, encrypted_session_key.length,
ntlmssp_state->neg_flags)) {
data_blob_free(&lm_response);
@@ -600,6 +650,8 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st
return NT_STATUS_NO_MEMORY;
}
+ data_blob_free(&encrypted_session_key);
+
data_blob_free(&ntlmssp_state->chal);
data_blob_free(&ntlmssp_state->lm_resp);
data_blob_free(&ntlmssp_state->nt_resp);
@@ -638,6 +690,8 @@ NTSTATUS ntlmssp_client_start(NTLMSSP_CLIENT_STATE **ntlmssp_state)
(*ntlmssp_state)->neg_flags =
NTLMSSP_NEGOTIATE_128 |
NTLMSSP_NEGOTIATE_NTLM |
+ NTLMSSP_NEGOTIATE_NTLM2 |
+ NTLMSSP_NEGOTIATE_KEY_EXCH |
NTLMSSP_REQUEST_TARGET;
(*ntlmssp_state)->ref_count = 1;
@@ -706,9 +760,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/source3/libsmb/ntlmssp_parse.c b/source3/libsmb/ntlmssp_parse.c
index 3c6da349e4..60cb4ab04a 100644
--- a/source3/libsmb/ntlmssp_parse.c
+++ b/source3/libsmb/ntlmssp_parse.c
@@ -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/source3/libsmb/ntlmssp_sign.c b/source3/libsmb/ntlmssp_sign.c
index ecaef808c9..ff2f97c2e8 100644
--- a/source3/libsmb/ntlmssp_sign.c
+++ b/source3/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/source3/libsmb/smb_signing.c b/source3/libsmb/smb_signing.c
index 4167452953..08ff655a3f 100644
--- a/source3/libsmb/smb_signing.c
+++ b/source3/libsmb/smb_signing.c
@@ -25,6 +25,7 @@
struct outstanding_packet_lookup {
uint16 mid;
uint32 reply_seq_num;
+ BOOL deferred_packet;
struct outstanding_packet_lookup *prev, *next;
};
@@ -43,7 +44,7 @@ struct smb_basic_signing_context {
};
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;
@@ -54,19 +55,25 @@ 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;
- DEBUG(10,("store_sequence_for_reply: stored seq = %u mid = %u\n",
+ 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;
- DEBUG(10,("get_sequence_for_reply: found seq = %u mid = %u\n",
+ 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);
@@ -77,6 +84,22 @@ static BOOL get_sequence_for_reply(struct outstanding_packet_lookup **list,
}
/***********************************************************
+ 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(10,("is_reply_pending: False.\n"));
+ return False;
+}
+
+/***********************************************************
SMB signing - Common code before we set a new signing implementation
************************************************************/
@@ -188,7 +211,7 @@ static void free_signing_context(struct smb_sign_info *si)
}
-static BOOL signing_good(char *inbuf, struct smb_sign_info *si, BOOL good)
+static BOOL signing_good(char *inbuf, struct smb_sign_info *si, BOOL good, uint32 seq)
{
if (good && !si->doing_signing) {
si->doing_signing = True;
@@ -200,7 +223,8 @@ static BOOL signing_good(char *inbuf, struct smb_sign_info *si, BOOL good)
/* 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!\n"));
+ DEBUG(1, ("signing_good: SMB signature check failed on seq %u!\n",
+ (unsigned int)seq ));
return False;
} else {
@@ -290,10 +314,10 @@ static void client_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
else
send_seq_num = data->send_seq_num;
- simple_packet_signature(data, outbuf, send_seq_num, calc_md5_mac);
+ simple_packet_signature(data, (const unsigned char *)outbuf, send_seq_num, calc_md5_mac);
DEBUG(10, ("client_sign_outgoing_message: sent SMB signature of\n"));
- dump_data(10, calc_md5_mac, 8);
+ dump_data(10, (const char *)calc_md5_mac, 8);
memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8);
@@ -306,7 +330,7 @@ static void client_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
data->send_seq_num++;
store_sequence_for_reply(&data->outstanding_packet_list,
SVAL(outbuf,smb_mid),
- data->send_seq_num);
+ data->send_seq_num, False);
data->send_seq_num++;
}
@@ -318,6 +342,7 @@ 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;
@@ -335,29 +360,30 @@ static BOOL client_check_incoming_message(char *inbuf, struct smb_sign_info *si)
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)) {
+ &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;
}
- simple_packet_signature(data, inbuf, reply_seq_number, calc_md5_mac);
+ saved_seq = reply_seq_number;
+ simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
- server_sent_mac = &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, ("client_check_incoming_message: BAD SIG: wanted SMB signature of\n"));
- dump_data(5, calc_md5_mac, 8);
+ dump_data(5, (const char *)calc_md5_mac, 8);
DEBUG(5, ("client_check_incoming_message: BAD SIG: got SMB signature of\n"));
- dump_data(5, server_sent_mac, 8);
+ 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, inbuf, reply_seq_number, calc_md5_mac);
+ 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 ));
@@ -369,9 +395,9 @@ static BOOL client_check_incoming_message(char *inbuf, struct smb_sign_info *si)
} else {
DEBUG(10, ("client_check_incoming_message:: seq %u: got good SMB signature of\n", (unsigned int)reply_seq_number));
- dump_data(10, server_sent_mac, 8);
+ dump_data(10, (const char *)server_sent_mac, 8);
}
- return signing_good(inbuf, si, good);
+ return signing_good(inbuf, si, good, saved_seq);
}
/***********************************************************
@@ -428,12 +454,12 @@ BOOL cli_simple_set_signing(struct cli_state *cli, const uchar user_session_key[
memcpy(&data->mac_key.data[0], user_session_key, 16);
DEBUG(10, ("cli_simple_set_signing: user_session_key\n"));
- dump_data(10, user_session_key, 16);
+ 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, response.data, response.length);
+ dump_data(10, (const char *)response.data, response.length);
} else {
DEBUG(10, ("cli_simple_set_signing: NULL response_data\n"));
}
@@ -584,17 +610,6 @@ BOOL cli_check_sign_mac(struct cli_state *cli)
return True;
}
-static BOOL packet_is_oplock_break(char *buf)
-{
- if (CVAL(buf,smb_com) != SMBlockingX)
- return False;
-
- if (CVAL(buf,smb_vwv3) != LOCKING_ANDX_OPLOCK_RELEASE)
- return False;
-
- return True;
-}
-
/***********************************************************
SMB signing - Server implementation - send the MAC.
************************************************************/
@@ -608,25 +623,6 @@ static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
uint16 mid;
if (!si->doing_signing) {
- if (si->allow_smb_signing && si->negotiated_smb_signing) {
- mid = SVAL(outbuf, smb_mid);
-
- was_deferred_packet = get_sequence_for_reply(&data->outstanding_packet_list,
- mid, &send_seq_number);
- if (!was_deferred_packet) {
- /*
- * Is this an outgoing oplock break ? If so, store the
- * mid in the outstanding list.
- */
-
- if (packet_is_oplock_break(outbuf)) {
- store_sequence_for_reply(&data->outstanding_packet_list,
- mid, data->send_seq_num);
- }
-
- data->send_seq_num++;
- }
- }
return;
}
@@ -643,7 +639,7 @@ static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
mid = SVAL(outbuf, smb_mid);
/* See if this is a reply for a deferred packet. */
- was_deferred_packet = get_sequence_for_reply(&data->outstanding_packet_list, mid, &send_seq_number);
+ 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
@@ -651,10 +647,10 @@ static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
send_seq_number = data->trans_info->send_seq_num;
}
- simple_packet_signature(data, outbuf, send_seq_number, calc_md5_mac);
+ 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, calc_md5_mac, 8);
+ dump_data(10, (const char *)calc_md5_mac, 8);
memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8);
@@ -662,7 +658,7 @@ static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
Uncomment this to test if the remote server actually verifies signatures...*/
if (!was_deferred_packet) {
- if (!data->trans_info) {
+ 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)) {
@@ -670,7 +666,23 @@ static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
* 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;
}
/***********************************************************
@@ -682,6 +694,7 @@ 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;
@@ -703,30 +716,37 @@ static BOOL srv_check_incoming_message(char *inbuf, struct smb_sign_info *si)
} else {
/* We always increment the sequence number. */
data->send_seq_num++;
- /* Oplock break requests store an outgoing mid in the packet list. */
- if (packet_is_oplock_break(inbuf))
- get_sequence_for_reply(&data->outstanding_packet_list, mid, &reply_seq_number);
+
+ /* 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++;
}
- simple_packet_signature(data, inbuf, reply_seq_number, calc_md5_mac);
+ saved_seq = reply_seq_number;
+ simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
- server_sent_mac = &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, ("srv_check_incoming_message: BAD SIG: wanted SMB signature of\n"));
- dump_data(5, calc_md5_mac, 8);
+ 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: got SMB signature of\n"));
- dump_data(5, server_sent_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, inbuf, reply_seq_number, calc_md5_mac);
+ 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 ));
@@ -737,10 +757,10 @@ static BOOL srv_check_incoming_message(char *inbuf, struct smb_sign_info *si)
#endif /* JRATEST */
} else {
- DEBUG(10, ("srv_check_incoming_message: seq %u: got good SMB signature of\n", (unsigned int)reply_seq_number));
- dump_data(10, server_sent_mac, 8);
+ 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);
+ return signing_good(inbuf, si, good, saved_seq);
}
/***********************************************************
@@ -800,7 +820,7 @@ void srv_calculate_sign_mac(char *outbuf)
Called by server to defer an outgoing packet.
************************************************************/
-void srv_defer_sign_response(uint16 mid)
+void srv_defer_sign_response(uint16 mid, BOOL deferred_packet)
{
struct smb_basic_signing_context *data;
@@ -813,7 +833,7 @@ void srv_defer_sign_response(uint16 mid)
return;
store_sequence_for_reply(&data->outstanding_packet_list,
- mid, data->send_seq_num);
+ mid, data->send_seq_num, deferred_packet);
data->send_seq_num++;
}
@@ -837,7 +857,7 @@ void srv_cancel_sign_response(uint16 mid)
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))
+ while (get_sequence_for_reply(&data->outstanding_packet_list, mid, &dummy_seq,NULL))
;
}
diff --git a/source3/libsmb/smbencrypt.c b/source3/libsmb/smbencrypt.c
index 7a1a2d7d18..ec31bb5dba 100644
--- a/source3/libsmb/smbencrypt.c
+++ b/source3/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/source3/libsmb/spnego.c b/source3/libsmb/spnego.c
new file mode 100644
index 0000000000..50caf7b4c0
--- /dev/null
+++ b/source3/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/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c
index 610f4b3c03..4e02b29f92 100644
--- a/source3/libsmb/trusts_util.c
+++ b/source3/libsmb/trusts_util.c
@@ -35,16 +35,15 @@ static NTSTATUS just_change_the_password(struct cli_state *cli, TALLOC_CTX *mem_
uint32 sec_channel_type)
{
NTSTATUS result;
- uint32 neg_flags = 0x000001ff;
- result = cli_nt_setup_creds(cli, sec_channel_type, orig_trust_passwd_hash, &neg_flags, 2);
-
- if (!NT_STATUS_IS_OK(result)) {
+ /* ensure that schannel uses the right domain */
+ fstrcpy(cli->domain, lp_workgroup());
+ if (! NT_STATUS_IS_OK(result = cli_nt_establish_netlogon(cli, sec_channel_type, orig_trust_passwd_hash))) {
DEBUG(3,("just_change_the_password: unable to setup creds (%s)!\n",
nt_errstr(result)));
return result;
}
-
+
result = cli_net_srv_pwset(cli, mem_ctx, global_myname(), new_trust_passwd_hash);
if (!NT_STATUS_IS_OK(result)) {