diff options
Diffstat (limited to 'source3/libsmb')
-rw-r--r-- | source3/libsmb/cliconnect.c | 114 | ||||
-rw-r--r-- | source3/libsmb/clientgen.c | 7 | ||||
-rw-r--r-- | source3/libsmb/clifile.c | 5 | ||||
-rw-r--r-- | source3/libsmb/clikrb5.c | 20 | ||||
-rw-r--r-- | source3/libsmb/climessage.c | 2 | ||||
-rw-r--r-- | source3/libsmb/cliprint.c | 5 | ||||
-rw-r--r-- | source3/libsmb/clirap.c | 10 | ||||
-rw-r--r-- | source3/libsmb/clirap2.c | 63 | ||||
-rw-r--r-- | source3/libsmb/clireadwrite.c | 2 | ||||
-rw-r--r-- | source3/libsmb/clisecdesc.c | 4 | ||||
-rw-r--r-- | source3/libsmb/clispnego.c | 3 | ||||
-rw-r--r-- | source3/libsmb/namequery.c | 2 | ||||
-rw-r--r-- | source3/libsmb/namequery_dc.c | 16 | ||||
-rw-r--r-- | source3/libsmb/nmblib.c | 34 | ||||
-rw-r--r-- | source3/libsmb/ntlmssp.c | 102 | ||||
-rw-r--r-- | source3/libsmb/ntlmssp_parse.c | 3 | ||||
-rw-r--r-- | source3/libsmb/ntlmssp_sign.c | 24 | ||||
-rw-r--r-- | source3/libsmb/smb_signing.c | 160 | ||||
-rw-r--r-- | source3/libsmb/smbencrypt.c | 4 | ||||
-rw-r--r-- | source3/libsmb/spnego.c | 343 | ||||
-rw-r--r-- | source3/libsmb/trusts_util.c | 9 |
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)) { |