diff options
author | Andrew Tridgell <tridge@samba.org> | 1999-12-13 13:27:58 +0000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 1999-12-13 13:27:58 +0000 |
commit | 3db52feb1f3b2c07ce0b06ad4a7099fa6efe3fc7 (patch) | |
tree | 866dd15416c3d8554bb207709f433a87ad0c012d /source3/libsmb | |
parent | f6276724bafdb6145c0c7b565172d80cb04516ea (diff) | |
download | samba-3db52feb1f3b2c07ce0b06ad4a7099fa6efe3fc7.tar.gz samba-3db52feb1f3b2c07ce0b06ad4a7099fa6efe3fc7.tar.bz2 samba-3db52feb1f3b2c07ce0b06ad4a7099fa6efe3fc7.zip |
first pass at updating head branch to be to be the same as the SAMBA_2_0 branch
(This used to be commit 453a822a76780063dff23526c35408866d0c0154)
Diffstat (limited to 'source3/libsmb')
-rw-r--r-- | source3/libsmb/clientgen.c | 1892 | ||||
-rw-r--r-- | source3/libsmb/namequery.c | 827 | ||||
-rw-r--r-- | source3/libsmb/nmblib.c | 288 | ||||
-rw-r--r-- | source3/libsmb/nterr.c | 20 | ||||
-rw-r--r-- | source3/libsmb/passchange.c | 4 | ||||
-rw-r--r-- | source3/libsmb/pwd_cache.c | 217 | ||||
-rw-r--r-- | source3/libsmb/smbdes.c | 23 | ||||
-rw-r--r-- | source3/libsmb/smbencrypt.c | 481 | ||||
-rw-r--r-- | source3/libsmb/smberr.c | 85 |
9 files changed, 1411 insertions, 2426 deletions
diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index 62c7429b59..4f620bc5f4 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -2,8 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. SMB client generic functions - Copyright (C) Andrew Tridgell 1994-1999 - Copyright (C) Luke Kenneth Casson Leighton 1996-1999 + Copyright (C) Andrew Tridgell 1994-1998 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 @@ -25,84 +24,52 @@ #include "includes.h" #include "trans2.h" + extern int DEBUGLEVEL; +extern pstring user_socket_options; +extern pstring scope; -/* - * set the port that will be used for connections by the client - */ +static void cli_process_oplock(struct cli_state *cli); +/* + * Change the port number used to call on + */ int cli_set_port(struct cli_state *cli, int port) { - - if (port != 0) + if (port > 0) cli->port = port; - return cli->port; /* return it incase caller wants it */ - + return cli->port; } /**************************************************************************** -copy a string (unicode or otherwise) into an SMB buffer. skips a string -plus points to next +recv an smb ****************************************************************************/ -static char *cli_put_string(struct cli_state *cli, char *p, const char *str, - BOOL skip_end) +static BOOL cli_receive_smb(struct cli_state *cli) { - uint16 flgs2 = SVAL(cli->outbuf, smb_flg2); - if (IS_BITS_SET_ALL(flgs2, FLAGS2_UNICODE_STRINGS)) - { - p = align2(p, cli->outbuf); - p = ascii_to_unibuf(p, str, 1024); - if (skip_end) - { - CVAL(p, 0) = 0; p++; - CVAL(p, 0) = 0; p++; - } - return p; - } - else - { - pstrcpy(p, str); - p = skip_string(p, 1); - if (skip_end) - { - CVAL(p, 0) = 0; p++; + BOOL ret; + again: + ret = client_receive_smb(cli->fd,cli->inbuf,cli->timeout); + + if (ret) { + /* it might be an oplock break request */ + if (CVAL(cli->inbuf,smb_com) == SMBlockingX && + SVAL(cli->inbuf,smb_vwv6) == 0 && + SVAL(cli->inbuf,smb_vwv7) == 0) { + if (cli->use_oplocks) cli_process_oplock(cli); + /* try to prevent loops */ + CVAL(cli->inbuf,smb_com) = 0xFF; + goto again; } - return p; } -} -/**************************************************************************** -copy a string (unicode or otherwise) into an SMB buffer. skips a string -plus points to next -****************************************************************************/ -static const char *cli_get_string(struct cli_state *cli, char *p, - char *str, size_t str_len) -{ - uint16 flgs2 = SVAL(cli->inbuf,smb_flg2); - if (IS_BITS_SET_ALL(flgs2, FLAGS2_UNICODE_STRINGS)) - { - return unibuf_to_ascii(str, p, str_len); - } - else - { - safe_strcpy(str, p, str_len-1); - return skip_string(p, 1); - } -} - -/**************************************************************************** -recv an smb -****************************************************************************/ -static BOOL cli_receive_smb(struct cli_state *cli) -{ - return client_receive_smb(cli->fd,cli->inbuf,cli->timeout); + return ret; } /**************************************************************************** send an smb to a fd and re-establish if necessary ****************************************************************************/ -static BOOL cli_send_smb(struct cli_state *cli, BOOL show) +static BOOL cli_send_smb(struct cli_state *cli) { size_t len; size_t nwritten=0; @@ -111,26 +78,9 @@ static BOOL cli_send_smb(struct cli_state *cli, BOOL show) len = smb_len(cli->outbuf) + 4; - if (show) - { - uint8 msg_type = CVAL(cli->outbuf, 0); - if (msg_type == 0) - { - show_msg(cli->outbuf); - } - else - { - dump_data(10, cli->outbuf, len); - } - } - while (nwritten < len) { ret = write_socket(cli->fd,cli->outbuf+nwritten,len - nwritten); - if (ret <= 0 && errno == EPIPE && !reestablished) - { - DEBUG(5,("cli_send_smb: write error (%s) - reconnecting\n", - strerror(errno))); - + if (ret <= 0 && errno == EPIPE && !reestablished) { if (cli_reestablish_connection(cli)) { reestablished = True; nwritten=0; @@ -139,8 +89,9 @@ static BOOL cli_send_smb(struct cli_state *cli, BOOL show) } if (ret <= 0) { DEBUG(0,("Error writing %d bytes to client. %d. Exiting\n", - len,ret)); - return False; + (int)len,(int)ret)); + close_sockets(); + exit(1); } nwritten += ret; } @@ -148,26 +99,62 @@ static BOOL cli_send_smb(struct cli_state *cli, BOOL show) return True; } -/****************************************************** - Return an error message - either an SMB error or a RAP - error. -*******************************************************/ - -char *cli_errstr(struct cli_state *cli) -{ - static fstring error_message; - cli_safe_errstr(cli, error_message, sizeof(error_message)); - return error_message; +/**************************************************************************** +setup basics in a outgoing packet +****************************************************************************/ +static void cli_setup_packet(struct cli_state *cli) +{ + cli->rap_error = 0; + cli->nt_error = 0; + SSVAL(cli->outbuf,smb_pid,cli->pid); + SSVAL(cli->outbuf,smb_uid,cli->vuid); + SSVAL(cli->outbuf,smb_mid,cli->mid); + if (cli->protocol > PROTOCOL_CORE) { + SCVAL(cli->outbuf,smb_flg,0x8); + SSVAL(cli->outbuf,smb_flg2,0x1); + } } + + /**************************************************************************** - return a description of an SMB error +process an oplock break request from the server ****************************************************************************/ -void cli_safe_smb_errstr(struct cli_state *cli, char *msg, size_t len) +static void cli_process_oplock(struct cli_state *cli) { - smb_safe_errstr(cli->inbuf, msg, len); + char *oldbuf = cli->outbuf; + pstring buf; + int fnum; + + fnum = SVAL(cli->inbuf,smb_vwv2); + + /* damn, we really need to keep a record of open files so we + can detect a oplock break and a close crossing on the + wire. for now this swallows the errors */ + if (fnum == 0) return; + + cli->outbuf = buf; + + memset(buf,'\0',smb_size); + set_message(buf,8,0,True); + + CVAL(buf,smb_com) = SMBlockingX; + SSVAL(buf,smb_tid, cli->cnum); + cli_setup_packet(cli); + SSVAL(buf,smb_vwv0,0xFF); + SSVAL(buf,smb_vwv1,0); + SSVAL(buf,smb_vwv2,fnum); + SSVAL(buf,smb_vwv3,2); /* oplock break ack */ + SIVAL(buf,smb_vwv4,0); /* timoeut */ + SSVAL(buf,smb_vwv6,0); /* unlockcount */ + SSVAL(buf,smb_vwv7,0); /* lockcount */ + + cli_send_smb(cli); + + cli->outbuf = oldbuf; } + /***************************************************** RAP error codes - a small start but will be extended. *******************************************************/ @@ -186,36 +173,36 @@ struct {2244, "This password cannot be used now (password history conflict)." }, {2245, "The password is shorter than required." }, {2246, "The password of this user is too recent to change."}, + + /* these really shouldn't be here ... */ + {0x80, "Not listening on called name"}, + {0x81, "Not listening for calling name"}, + {0x82, "Called name not present"}, + {0x83, "Called name present, but insufficient resources"}, + {0, NULL} }; /**************************************************************************** - return a description of a RAP error + return a description of an SMB error ****************************************************************************/ -BOOL get_safe_rap_errstr(int rap_error, char *err_msg, size_t msglen) +static char *cli_smb_errstr(struct cli_state *cli) { - int i; - - slprintf(err_msg, msglen - 1, "RAP code %d", rap_error); - - for (i = 0; rap_errmap[i].message != NULL; i++) - { - if (rap_errmap[i].err == rap_error) - { - safe_strcpy( err_msg, rap_errmap[i].message, msglen); - return True; - } - } - return False; + return smb_errstr(cli->inbuf); } -/**************************************************************************** - return a description of an SMB error -****************************************************************************/ -void cli_safe_errstr(struct cli_state *cli, char *err_msg, size_t msglen) +/****************************************************** + Return an error message - either an SMB error or a RAP + error. +*******************************************************/ + +char *cli_errstr(struct cli_state *cli) { + static fstring error_message; uint8 errclass; uint32 errnum; + uint32 nt_rpc_error; + int i; /* * Errors are of three kinds - smb errors, @@ -224,54 +211,50 @@ void cli_safe_errstr(struct cli_state *cli, char *err_msg, size_t msglen) * errors, whose error code is in cli.rap_error. */ - cli_error(cli, &errclass, &errnum); + cli_error(cli, &errclass, &errnum, &nt_rpc_error); if (errclass != 0) { - cli_safe_smb_errstr(cli, err_msg, msglen); + return cli_smb_errstr(cli); } - else if (cli->nt_error) - { - /* - * Was it an NT error ? - */ - (void)get_safe_nt_error_msg(cli->nt_error, err_msg, msglen); - } - else + /* + * Was it an NT error ? + */ + + if (nt_rpc_error) { - /* - * Must have been a rap error. - */ - (void)get_safe_rap_errstr(cli->rap_error, err_msg, msglen); + char *nt_msg = get_nt_error_msg(nt_rpc_error); + + if (nt_msg == NULL) + { + slprintf(error_message, sizeof(fstring) - 1, "NT code %d", nt_rpc_error); + } + else + { + fstrcpy(error_message, nt_msg); + } + + return error_message; } -} -/**************************************************************************** -setup basics in a outgoing packet -****************************************************************************/ -static void cli_setup_packet(struct cli_state *cli) -{ - uint16 flgs2 = 0; - flgs2 |= FLAGS2_LONG_PATH_COMPONENTS; - flgs2 |= FLAGS2_32_BIT_ERROR_CODES; - flgs2 |= FLAGS2_EXT_SEC; -#if 0 - flgs2 |= FLAGS2_UNICODE_STRINGS; -#endif - cli->rap_error = 0; - cli->nt_error = 0; - SSVAL(cli->outbuf,smb_pid,cli->pid); - SSVAL(cli->outbuf,smb_uid,cli->vuid); - SSVAL(cli->outbuf,smb_mid,cli->mid); + /* + * Must have been a rap error. + */ + + slprintf(error_message, sizeof(error_message) - 1, "code %d", cli->rap_error); - if (cli->protocol > PROTOCOL_CORE) + for (i = 0; rap_errmap[i].message != NULL; i++) { - SCVAL(cli->outbuf,smb_flg,0x8); - SSVAL(cli->outbuf,smb_flg2,flgs2); - } -} + if (rap_errmap[i].err == cli->rap_error) + { + fstrcpy( error_message, rap_errmap[i].message); + break; + } + } + return error_message; +} /***************************************************************************** Convert a character pointer in a cli_call_api() response to a form we can use. @@ -299,7 +282,7 @@ static char *fix_char_ptr(unsigned int datap, unsigned int converter, /**************************************************************************** send a SMB trans or trans2 request ****************************************************************************/ -BOOL cli_send_trans(struct cli_state *cli, int trans, +static BOOL cli_send_trans(struct cli_state *cli, int trans, char *name, int pipe_name_len, int fid, int flags, uint16 *setup, int lsetup, int msetup, @@ -315,7 +298,7 @@ BOOL cli_send_trans(struct cli_state *cli, int trans, this_lparam = MIN(lparam,cli->max_xmit - (500+lsetup*2)); /* hack */ this_ldata = MIN(ldata,cli->max_xmit - (500+lsetup*2+this_lparam)); - bzero(cli->outbuf,smb_size); + memset(cli->outbuf,'\0',smb_size); set_message(cli->outbuf,14+lsetup,0,True); CVAL(cli->outbuf,smb_com) = trans; SSVAL(cli->outbuf,smb_tid, cli->cnum); @@ -353,7 +336,8 @@ BOOL cli_send_trans(struct cli_state *cli, int trans, set_message(cli->outbuf,14+lsetup, /* wcnt, bcc */ PTR_DIFF(outdata+this_ldata,smb_buf(cli->outbuf)),False); - cli_send_smb(cli, True); + show_msg(cli->outbuf); + cli_send_smb(cli); if (this_ldata < ldata || this_lparam < lparam) { /* receive interim response */ @@ -387,13 +371,14 @@ BOOL cli_send_trans(struct cli_state *cli, int trans, if (trans==SMBtrans2) SSVALS(cli->outbuf,smb_sfid,fid); /* fid */ if (this_lparam) /* param[] */ - memcpy(outparam,param,this_lparam); + memcpy(outparam,param+tot_param,this_lparam); if (this_ldata) /* data[] */ - memcpy(outdata,data,this_ldata); + memcpy(outdata,data+tot_data,this_ldata); set_message(cli->outbuf,trans==SMBtrans?8:9, /* wcnt, bcc */ PTR_DIFF(outdata+this_ldata,smb_buf(cli->outbuf)),False); - cli_send_smb(cli, True); + show_msg(cli->outbuf); + cli_send_smb(cli); tot_data += this_ldata; tot_param += this_lparam; @@ -414,12 +399,16 @@ static BOOL cli_receive_trans(struct cli_state *cli,int trans, int total_data=0; int total_param=0; int this_data,this_param; - + uint8 eclass; + uint32 ecode; + *data_len = *param_len = 0; if (!cli_receive_smb(cli)) return False; + show_msg(cli->inbuf); + /* sanity check */ if (CVAL(cli->inbuf,smb_com) != trans) { DEBUG(0,("Expected %s response, got command 0x%02x\n", @@ -428,9 +417,16 @@ static BOOL cli_receive_trans(struct cli_state *cli,int trans, return(False); } - if (cli_error(cli, NULL, NULL)) + /* + * An NT RPC pipe call can return ERRDOS, ERRmoredata + * to a trans call. This is not an error and should not + * be treated as such. + */ + + if (cli_error(cli, &eclass, &ecode, NULL)) { - return(False); + if(cli->nt_pipe_fnum == 0 || !(eclass == ERRDOS && ecode == ERRmoredata)) + return(False); } /* parse out the lengths */ @@ -472,6 +468,8 @@ static BOOL cli_receive_trans(struct cli_state *cli,int trans, if (!cli_receive_smb(cli)) return False; + show_msg(cli->inbuf); + /* sanity check */ if (CVAL(cli->inbuf,smb_com) != trans) { DEBUG(0,("Expected %s response, got command 0x%02x\n", @@ -479,10 +477,10 @@ static BOOL cli_receive_trans(struct cli_state *cli,int trans, CVAL(cli->inbuf,smb_com))); return(False); } - - if (cli_error(cli, NULL, NULL)) + if (cli_error(cli, &eclass, &ecode, NULL)) { - return(False); + if(cli->nt_pipe_fnum == 0 || !(eclass == ERRDOS && ecode == ERRmoredata)) + return(False); } } @@ -642,6 +640,8 @@ BOOL cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, c int type = SVAL(p,14); int comment_offset = IVAL(p,16) & 0xFFFF; char *cmnt = comment_offset?(rdata+comment_offset-converter):""; + dos_to_unix(sname,True); + dos_to_unix(cmnt,True); fn(sname, type, cmnt); } } else { @@ -719,6 +719,8 @@ BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype, stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY; + dos_to_unix(sname, True); + dos_to_unix(cmnt, True); fn(sname, stype, cmnt); } } @@ -754,41 +756,76 @@ prots[] = /**************************************************************************** -send a session setup + Send a session setup. The username is in UNIX character format and must be + converted to DOS codepage format before sending. If the password is in + plaintext, the same should be done. ****************************************************************************/ -BOOL cli_session_setup_x(struct cli_state *cli, - char *user, - char *pass, int passlen, - char *ntpass, int ntpasslen, - char *user_domain) + +BOOL cli_session_setup(struct cli_state *cli, + char *user, + char *pass, int passlen, + char *ntpass, int ntpasslen, + char *workgroup) { - uint8 eclass; - uint32 ecode; char *p; - BOOL esec = cli->capabilities & CAP_EXTENDED_SECURITY; + fstring pword, ntpword; - if (cli->reuse) - { - DEBUG(3,("cli_session_setup_x: reuse enabled, skipping SMBsesssetupX\n")); + if (cli->protocol < PROTOCOL_LANMAN1) return True; - } - DEBUG(100,("cli_session_setup. extended security: %s\n", - BOOLSTR(esec))); - -#ifdef DEBUG_PASSWORD - DEBUG(100,("cli_session_setup. pass, ntpass\n")); - dump_data(100, pass, passlen); - dump_data(100, ntpass, ntpasslen); -#endif + if (passlen > sizeof(pword)-1 || ntpasslen > sizeof(ntpword)-1) { + return False; + } - if (cli->protocol < PROTOCOL_LANMAN1) - { - return True; + if (((passlen == 0) || (passlen == 1)) && (pass[0] == '\0')) { + /* Null session connect. */ + pword[0] = '\0'; + ntpword[0] = '\0'; + } else { + if ((cli->sec_mode & 2) && passlen != 24) { + /* + * Encrypted mode needed, and non encrypted password supplied. + */ + passlen = 24; + ntpasslen = 24; + fstrcpy(pword, pass); + unix_to_dos(pword,True); + fstrcpy(ntpword, ntpass);; + unix_to_dos(ntpword,True); + SMBencrypt((uchar *)pword,(uchar *)cli->cryptkey,(uchar *)pword); + SMBNTencrypt((uchar *)ntpword,(uchar *)cli->cryptkey,(uchar *)ntpword); + } else if ((cli->sec_mode & 2) && passlen == 24) { + /* + * Encrypted mode needed, and encrypted password supplied. + */ + memcpy(pword, pass, passlen); + if(ntpasslen == 24) { + memcpy(ntpword, ntpass, ntpasslen); + } else { + fstrcpy(ntpword, ""); + ntpasslen = 0; + } + } else { + /* + * Plaintext mode needed, assume plaintext supplied. + */ + fstrcpy(pword, pass); + unix_to_dos(pword,True); + fstrcpy(ntpword, ""); + ntpasslen = 0; + } } + /* if in share level security then don't send a password now */ + if (!(cli->sec_mode & 1)) { + fstrcpy(pword, ""); + passlen=1; + fstrcpy(ntpword, ""); + ntpasslen=1; + } + /* send a session setup command */ - bzero(cli->outbuf,smb_size); + memset(cli->outbuf,'\0',smb_size); if (cli->protocol < PROTOCOL_NT1) { @@ -803,36 +840,13 @@ BOOL cli_session_setup_x(struct cli_state *cli, SIVAL(cli->outbuf,smb_vwv5,cli->sesskey); SSVAL(cli->outbuf,smb_vwv7,passlen); p = smb_buf(cli->outbuf); - memcpy(p,pass,passlen); + memcpy(p,pword,passlen); p += passlen; pstrcpy(p,user); + unix_to_dos(p,True); strupper(p); } - else if (esec) - { - set_message(cli->outbuf,12,0,True); - CVAL(cli->outbuf,smb_com) = SMBsesssetupX; - cli_setup_packet(cli); - - CVAL(cli->outbuf,smb_vwv0) = 0xFF; - SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE); - SSVAL(cli->outbuf,smb_vwv3,2); - SSVAL(cli->outbuf,smb_vwv4,cli->pid); - SIVAL(cli->outbuf,smb_vwv5,cli->sesskey); - SSVAL(cli->outbuf,smb_vwv7,passlen); - SIVAL(cli->outbuf,smb_vwv10, CAP_EXTENDED_SECURITY|CAP_STATUS32|CAP_UNICODE); - p = smb_buf(cli->outbuf); - memcpy(p,pass,passlen); - p += passlen; - - p = cli_put_string(cli, p, "Unix", False); - p = cli_put_string(cli, p, "Samba", False); - p = cli_put_string(cli, p, "", False); - p++; - - set_message(cli->outbuf,12,PTR_DIFF(p,smb_buf(cli->outbuf)),False); - } - else + else { set_message(cli->outbuf,13,0,True); CVAL(cli->outbuf,smb_com) = SMBsesssetupX; @@ -845,204 +859,58 @@ BOOL cli_session_setup_x(struct cli_state *cli, SIVAL(cli->outbuf,smb_vwv5,cli->sesskey); SSVAL(cli->outbuf,smb_vwv7,passlen); SSVAL(cli->outbuf,smb_vwv8,ntpasslen); - SIVAL(cli->outbuf,smb_vwv11, 0); + SSVAL(cli->outbuf,smb_vwv11,0); p = smb_buf(cli->outbuf); - memcpy(p,pass,passlen); + memcpy(p,pword,passlen); p += SVAL(cli->outbuf,smb_vwv7); - memcpy(p,ntpass,ntpasslen); + memcpy(p,ntpword,ntpasslen); p += SVAL(cli->outbuf,smb_vwv8); - strupper(user); - p = cli_put_string(cli, p, user, False); - strupper(user_domain); - p = cli_put_string(cli, p, user_domain, False); - p = cli_put_string(cli, p, "Unix", True); - p = cli_put_string(cli, p, "Samba", False); - + pstrcpy(p,user); + unix_to_dos(p,True); + strupper(p); + p = skip_string(p,1); + pstrcpy(p,workgroup); + strupper(p); + p = skip_string(p,1); + pstrcpy(p,"Unix");p = skip_string(p,1); + pstrcpy(p,"Samba");p = skip_string(p,1); set_message(cli->outbuf,13,PTR_DIFF(p,smb_buf(cli->outbuf)),False); } - cli_send_smb(cli, True); - if (!cli_receive_smb(cli)) - { - DEBUG(10,("cli_session_setup_x: receive smb failed\n")); + cli_send_smb(cli); + if (!cli_receive_smb(cli)) return False; - } - - if (cli_error(cli, &eclass, &ecode)) - { - uint16 flgs2 = SVAL(cli->inbuf,smb_flg2); - if (IS_BITS_CLR_ALL(flgs2, FLAGS2_32_BIT_ERROR_CODES)) - { - if (ecode != ERRmoredata || !esec) - { - return False; - } - } - else if (ecode != 0xC0000016) /* STATUS_MORE_PROCESSING_REQD */ - { - return False; - } - } - /* use the returned vuid from now on */ - cli->vuid = SVAL(cli->inbuf,smb_uid); + show_msg(cli->inbuf); - if (cli->protocol >= PROTOCOL_NT1) - { - if (esec) - { - } - else - { - /* - * Save off some of the connected server - * info. - */ - char *server_domain; - char *server_os; - char *server_type; - - server_os = smb_buf(cli->inbuf); - server_type = skip_string(server_os,1); - server_domain = skip_string(server_type,1); - - fstrcpy(cli->server_os, server_os); - fstrcpy(cli->server_type, server_type); - fstrcpy(cli->server_domain, server_domain); - } + if (CVAL(cli->inbuf,smb_rcls) != 0) { + return False; } - return True; -} - -static BOOL cli_calc_session_pwds(struct cli_state *cli, - char *myhostname, - char *pword, char *ntpword, - char *pass, int *passlen, - char *ntpass, int *ntpasslen, - char *sess_key, - BOOL ntlmv2) -{ - BOOL ntpass_ok = ntpass != NULL && ntpasslen != NULL; - - if (pass == NULL || passlen == NULL) - { - DEBUG(0,("cli_calc_session_pwds: pass and passlen are NULL\n")); - return False; - } - if ((ntpass != NULL || ntpasslen != NULL) && - (ntpass == NULL || ntpasslen == NULL)) - { - DEBUG(0,("cli_calc_session_pwds: ntpasswd pointers invalid\n")); - return False; - } - -#ifdef DEBUG_PASSWORD - DEBUG(100,("cli_calc_session_pwds. pass, ntpass\n")); - dump_data(100, pass, *passlen); - if (ntpass_ok) - { - dump_data(100, ntpass, *ntpasslen); - } -#endif - if (!IS_BITS_SET_ALL(cli->sec_mode, 1)) - { - /* if in share level security then don't send a password now */ - pword[0] = '\0'; - *passlen=1; - if (ntpass_ok) - { - ntpword[0] = '\0'; - *ntpasslen=1; - } - return True; - } - else if ((*passlen == 0 || *passlen == 1) && (pass[0] == '\0')) - { - /* Null session connect. */ - pword [0] = '\0'; - if (ntpass_ok) - { - ntpword[0] = '\0'; - *ntpasslen=0; - } - - return True; - } - - if (!ntpass_ok) - { - return False; - } - - if (*passlen == 24 && *ntpasslen >= 24) - { - if (IS_BITS_SET_ALL(cli->sec_mode, 2)) - { - /* encrypted password, implicit from 24-byte lengths */ - memcpy(pword , pass , *passlen); - memcpy(ntpword, ntpass, *ntpasslen); - } - else - { - DEBUG(0,("cli_calc_session_pwds: encrypted passwords not supported by server\n")); - return False; - } - } - else if (*ntpasslen == 0 || !IS_BITS_SET_ALL(cli->sec_mode, 2)) - { - /* plain-text password: server doesn't support encrypted. */ - fstrcpy(pword, pass); - fstrcpy(ntpword, ""); - *ntpasslen = 0; - } - else if (ntpasslen != NULL) - { - if (cli->use_ntlmv2 != False) - { - DEBUG(10,("cli_establish_connection: NTLMv2\n")); - pwd_make_lm_nt_owf2(&(cli->usr.pwd), cli->cryptkey, - cli->usr.user_name, myhostname, - cli->usr.domain); - } - else - { - DEBUG(10,("cli_establish_connection: NTLMv1\n")); - pwd_make_lm_nt_owf(&(cli->usr.pwd), cli->cryptkey); - } - - pwd_get_lm_nt_owf(&(cli->usr.pwd), pass, ntpass, - ntpasslen, sess_key); - - *passlen = 24; - } - return True; -} - -/**************************************************************************** -send a session setup -****************************************************************************/ -BOOL cli_session_setup(struct cli_state *cli, - char *myhostname, char *user, - char *pass, int passlen, - char *ntpass, int ntpasslen, - char *user_domain) -{ - fstring pword, ntpword; - - if (passlen > sizeof(pword)-1 || ntpasslen > sizeof(ntpword)-1) - { - return False; - } + /* use the returned vuid from now on */ + cli->vuid = SVAL(cli->inbuf,smb_uid); + + if (cli->protocol >= PROTOCOL_NT1) { + /* + * Save off some of the connected server + * info. + */ + char *server_domain,*server_os,*server_type; + server_os = smb_buf(cli->inbuf); + server_type = skip_string(server_os,1); + server_domain = skip_string(server_type,1); + fstrcpy(cli->server_os, server_os); + dos_to_unix(cli->server_os, True); + fstrcpy(cli->server_type, server_type); + dos_to_unix(cli->server_type, True); + fstrcpy(cli->server_domain, server_domain); + dos_to_unix(cli->server_domain, True); + } - fstrcpy(cli->usr.user_name, user); + fstrcpy(cli->user_name, user); + dos_to_unix(cli->user_name, True); - return cli_calc_session_pwds(cli, myhostname, pword, ntpword, - pass, &passlen, - ntpass, &ntpasslen, cli->sess_key, - cli->use_ntlmv2) && - cli_session_setup_x(cli, user, pass, passlen, ntpass, ntpasslen, - user_domain); + return True; } /**************************************************************************** @@ -1051,20 +919,14 @@ BOOL cli_session_setup(struct cli_state *cli, BOOL cli_ulogoff(struct cli_state *cli) { - if (cli->reuse) - { - DEBUG(3,("cli_ulogoff: reuse enabled, skipping SMBulogoff\n")); - return True; - } - - bzero(cli->outbuf,smb_size); + memset(cli->outbuf,'\0',smb_size); set_message(cli->outbuf,2,0,True); CVAL(cli->outbuf,smb_com) = SMBulogoffX; cli_setup_packet(cli); SSVAL(cli->outbuf,smb_vwv0,0xFF); SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */ - cli_send_smb(cli, True); + cli_send_smb(cli); if (!cli_receive_smb(cli)) return False; @@ -1077,10 +939,10 @@ send a tconX BOOL cli_send_tconX(struct cli_state *cli, char *share, char *dev, char *pass, int passlen) { - fstring fullshare, pword; + fstring fullshare, pword, dos_pword; char *p; - bzero(cli->outbuf,smb_size); - bzero(cli->inbuf,smb_size); + memset(cli->outbuf,'\0',smb_size); + memset(cli->inbuf,'\0',smb_size); fstrcpy(cli->share, share); @@ -1091,17 +953,32 @@ BOOL cli_send_tconX(struct cli_state *cli, } if ((cli->sec_mode & 2) && *pass && passlen != 24) { + /* + * Non-encrypted passwords - convert to DOS codepage before encryption. + */ passlen = 24; - SMBencrypt((uchar *)pass,(uchar *)cli->cryptkey,(uchar *)pword); + fstrcpy(dos_pword,pass); + unix_to_dos(dos_pword,True); + SMBencrypt((uchar *)dos_pword,(uchar *)cli->cryptkey,(uchar *)pword); } else { - memcpy(pword, pass, passlen); + if(!(cli->sec_mode & 2)) { + /* + * Non-encrypted passwords - convert to DOS codepage before using. + */ + fstrcpy(pword,pass); + unix_to_dos(pword,True); + } else { + memcpy(pword, pass, passlen); + } } slprintf(fullshare, sizeof(fullshare)-1, "\\\\%s\\%s", cli->desthost, share); + unix_to_dos(fullshare, True); strupper(fullshare); - set_message(cli->outbuf,4, 0, True); + set_message(cli->outbuf,4, + 2 + strlen(fullshare) + passlen + strlen(dev),True); CVAL(cli->outbuf,smb_com) = SMBtconX; cli_setup_packet(cli); @@ -1111,15 +988,14 @@ BOOL cli_send_tconX(struct cli_state *cli, p = smb_buf(cli->outbuf); memcpy(p,pword,passlen); p += passlen; - p = cli_put_string(cli, p, fullshare, False); - fstrcpy(p, dev); - p = skip_string(p, 1); - - set_message(cli->outbuf,4,PTR_DIFF(p, smb_buf(cli->outbuf)),False); + fstrcpy(p,fullshare); + p = skip_string(p,1); + pstrcpy(p,dev); + unix_to_dos(p,True); SCVAL(cli->inbuf,smb_rcls, 1); - cli_send_smb(cli, True); + cli_send_smb(cli); if (!cli_receive_smb(cli)) return False; @@ -1129,10 +1005,8 @@ BOOL cli_send_tconX(struct cli_state *cli, fstrcpy(cli->dev, "A:"); - if (cli->protocol >= PROTOCOL_NT1) - { - cli_get_string(cli, smb_buf(cli->inbuf), - cli->dev, sizeof(cli->dev)); + if (cli->protocol >= PROTOCOL_NT1) { + fstrcpy(cli->dev, smb_buf(cli->inbuf)); } if (strcasecmp(share,"IPC$")==0) { @@ -1140,8 +1014,8 @@ BOOL cli_send_tconX(struct cli_state *cli, } /* only grab the device if we have a recent protocol level */ - if (cli->protocol >= PROTOCOL_NT1 && smb_buflen(cli->inbuf) == 3) - { + if (cli->protocol >= PROTOCOL_NT1 && + smb_buflen(cli->inbuf) == 3) { /* almost certainly win95 - enable bug fixes */ cli->win95 = True; } @@ -1156,13 +1030,13 @@ send a tree disconnect ****************************************************************************/ BOOL cli_tdis(struct cli_state *cli) { - bzero(cli->outbuf,smb_size); + memset(cli->outbuf,'\0',smb_size); set_message(cli->outbuf,0,0,True); CVAL(cli->outbuf,smb_com) = SMBtdis; SSVAL(cli->outbuf,smb_tid,cli->cnum); cli_setup_packet(cli); - cli_send_smb(cli, True); + cli_send_smb(cli); if (!cli_receive_smb(cli)) return False; @@ -1176,8 +1050,8 @@ BOOL cli_rename(struct cli_state *cli, char *fname_src, char *fname_dst) { char *p; - bzero(cli->outbuf,smb_size); - bzero(cli->inbuf,smb_size); + memset(cli->outbuf,'\0',smb_size); + memset(cli->inbuf,'\0',smb_size); set_message(cli->outbuf,1, 4 + strlen(fname_src) + strlen(fname_dst), True); @@ -1190,11 +1064,13 @@ BOOL cli_rename(struct cli_state *cli, char *fname_src, char *fname_dst) p = smb_buf(cli->outbuf); *p++ = 4; pstrcpy(p,fname_src); + unix_to_dos(p,True); p = skip_string(p,1); *p++ = 4; pstrcpy(p,fname_dst); + unix_to_dos(p,True); - cli_send_smb(cli, True); + cli_send_smb(cli); if (!cli_receive_smb(cli)) { return False; } @@ -1213,8 +1089,8 @@ BOOL cli_unlink(struct cli_state *cli, char *fname) { char *p; - bzero(cli->outbuf,smb_size); - bzero(cli->inbuf,smb_size); + memset(cli->outbuf,'\0',smb_size); + memset(cli->inbuf,'\0',smb_size); set_message(cli->outbuf,1, 2 + strlen(fname),True); @@ -1227,8 +1103,9 @@ BOOL cli_unlink(struct cli_state *cli, char *fname) p = smb_buf(cli->outbuf); *p++ = 4; pstrcpy(p,fname); + unix_to_dos(p,True); - cli_send_smb(cli, True); + cli_send_smb(cli); if (!cli_receive_smb(cli)) { return False; } @@ -1247,8 +1124,8 @@ BOOL cli_mkdir(struct cli_state *cli, char *dname) { char *p; - bzero(cli->outbuf,smb_size); - bzero(cli->inbuf,smb_size); + memset(cli->outbuf,'\0',smb_size); + memset(cli->inbuf,'\0',smb_size); set_message(cli->outbuf,0, 2 + strlen(dname),True); @@ -1259,8 +1136,9 @@ BOOL cli_mkdir(struct cli_state *cli, char *dname) p = smb_buf(cli->outbuf); *p++ = 4; pstrcpy(p,dname); + unix_to_dos(p,True); - cli_send_smb(cli, True); + cli_send_smb(cli); if (!cli_receive_smb(cli)) { return False; } @@ -1279,8 +1157,8 @@ BOOL cli_rmdir(struct cli_state *cli, char *dname) { char *p; - bzero(cli->outbuf,smb_size); - bzero(cli->inbuf,smb_size); + memset(cli->outbuf,'\0',smb_size); + memset(cli->inbuf,'\0',smb_size); set_message(cli->outbuf,0, 2 + strlen(dname),True); @@ -1291,8 +1169,9 @@ BOOL cli_rmdir(struct cli_state *cli, char *dname) p = smb_buf(cli->outbuf); *p++ = 4; pstrcpy(p,dname); + unix_to_dos(p,True); - cli_send_smb(cli, True); + cli_send_smb(cli); if (!cli_receive_smb(cli)) { return False; } @@ -1309,12 +1188,12 @@ BOOL cli_rmdir(struct cli_state *cli, char *dname) /**************************************************************************** open a file ****************************************************************************/ -int cli_nt_create(struct cli_state *cli, const char *fname) +int cli_nt_create(struct cli_state *cli, char *fname) { char *p; - bzero(cli->outbuf,smb_size); - bzero(cli->inbuf,smb_size); + memset(cli->outbuf,'\0',smb_size); + memset(cli->inbuf,'\0',smb_size); set_message(cli->outbuf,24,1 + strlen(fname),True); @@ -1335,9 +1214,10 @@ int cli_nt_create(struct cli_state *cli, const char *fname) p = smb_buf(cli->outbuf); pstrcpy(p,fname); + unix_to_dos(p,True); p = skip_string(p,1); - cli_send_smb(cli, True); + cli_send_smb(cli); if (!cli_receive_smb(cli)) { return -1; } @@ -1353,8 +1233,7 @@ int cli_nt_create(struct cli_state *cli, const char *fname) /**************************************************************************** open a file ****************************************************************************/ -int cli_open(struct cli_state *cli, const char *fname, - int flags, int share_mode) +int cli_open(struct cli_state *cli, char *fname, int flags, int share_mode) { char *p; unsigned openfn=0; @@ -1389,8 +1268,8 @@ int cli_open(struct cli_state *cli, const char *fname, } #endif /* O_SYNC */ - bzero(cli->outbuf,smb_size); - bzero(cli->inbuf,smb_size); + memset(cli->outbuf,'\0',smb_size); + memset(cli->inbuf,'\0',smb_size); set_message(cli->outbuf,15,1 + strlen(fname),True); @@ -1404,13 +1283,21 @@ int cli_open(struct cli_state *cli, const char *fname, SSVAL(cli->outbuf,smb_vwv4,aSYSTEM | aHIDDEN); SSVAL(cli->outbuf,smb_vwv5,0); SSVAL(cli->outbuf,smb_vwv8,openfn); + + if (cli->use_oplocks) { + /* if using oplocks then ask for a batch oplock via + core and extended methods */ + CVAL(cli->outbuf,smb_flg) |= + FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK; + SSVAL(cli->outbuf,smb_vwv2,SVAL(cli->outbuf,smb_vwv2) | 6); + } p = smb_buf(cli->outbuf); - p = cli_put_string(cli, p, fname, False); - - set_message(cli->outbuf,15,PTR_DIFF(p, smb_buf(cli->outbuf)),False); + pstrcpy(p,fname); + unix_to_dos(p,True); + p = skip_string(p,1); - cli_send_smb(cli, True); + cli_send_smb(cli); if (!cli_receive_smb(cli)) { return -1; } @@ -1430,8 +1317,8 @@ int cli_open(struct cli_state *cli, const char *fname, ****************************************************************************/ BOOL cli_close(struct cli_state *cli, int fnum) { - bzero(cli->outbuf,smb_size); - bzero(cli->inbuf,smb_size); + memset(cli->outbuf,'\0',smb_size); + memset(cli->inbuf,'\0',smb_size); set_message(cli->outbuf,3,0,True); @@ -1442,7 +1329,7 @@ BOOL cli_close(struct cli_state *cli, int fnum) SSVAL(cli->outbuf,smb_vwv0,fnum); SIVALS(cli->outbuf,smb_vwv1,-1); - cli_send_smb(cli, True); + cli_send_smb(cli); if (!cli_receive_smb(cli)) { return False; } @@ -1463,8 +1350,8 @@ BOOL cli_lock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int ti char *p; int saved_timeout = cli->timeout; - bzero(cli->outbuf,smb_size); - bzero(cli->inbuf,smb_size); + memset(cli->outbuf,'\0',smb_size); + memset(cli->inbuf,'\0', smb_size); set_message(cli->outbuf,8,10,True); @@ -1483,7 +1370,7 @@ BOOL cli_lock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int ti SSVAL(p, 0, cli->pid); SIVAL(p, 2, offset); SIVAL(p, 6, len); - cli_send_smb(cli, True); + cli_send_smb(cli); cli->timeout = (timeout == -1) ? 0x7FFFFFFF : timeout; @@ -1508,8 +1395,8 @@ BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int { char *p; - bzero(cli->outbuf,smb_size); - bzero(cli->inbuf,smb_size); + memset(cli->outbuf,'\0',smb_size); + memset(cli->inbuf,'\0',smb_size); set_message(cli->outbuf,8,10,True); @@ -1529,7 +1416,7 @@ BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int SIVAL(p, 2, offset); SIVAL(p, 6, len); - cli_send_smb(cli, True); + cli_send_smb(cli); if (!cli_receive_smb(cli)) { return False; } @@ -1549,8 +1436,8 @@ issue a single SMBread and don't wait for a reply static void cli_issue_read(struct cli_state *cli, int fnum, off_t offset, size_t size, int i) { - bzero(cli->outbuf,smb_size); - bzero(cli->inbuf,smb_size); + memset(cli->outbuf,'\0',smb_size); + memset(cli->inbuf,'\0',smb_size); set_message(cli->outbuf,10,0,True); @@ -1565,7 +1452,7 @@ static void cli_issue_read(struct cli_state *cli, int fnum, off_t offset, SSVAL(cli->outbuf,smb_vwv6,size); SSVAL(cli->outbuf,smb_mid,cli->mid + i); - cli_send_smb(cli, True); + cli_send_smb(cli); } /**************************************************************************** @@ -1577,15 +1464,24 @@ size_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t int total = -1; int issued=0; int received=0; - int mpx = MIN(MAX(cli->max_mux-1, 1), MAX_MAX_MUX_LIMIT); +/* + * There is a problem in this code when mpx is more than one. + * for some reason files can get corrupted when being read. + * Until we understand this fully I am serializing reads (one + * read/one reply) for now. JRA. + */ +#if 0 + int mpx = MAX(cli->max_mux-1, 1); +#else + int mpx = 1; +#endif int block = (cli->max_xmit - (smb_size+32)) & ~1023; int mid; int blocks = (size + (block-1)) / block; if (size == 0) return 0; - while (received < blocks) - { + while (received < blocks) { int size2; while (issued - received < mpx && issued < blocks) { @@ -1602,8 +1498,7 @@ size_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t mid = SVAL(cli->inbuf, smb_mid) - cli->mid; size2 = SVAL(cli->inbuf, smb_vwv5); - if (cli_error(cli, NULL, NULL)) - { + if (CVAL(cli->inbuf,smb_rcls) != 0) { blocks = MIN(blocks, mid-1); continue; } @@ -1647,8 +1542,8 @@ static void cli_issue_write(struct cli_state *cli, int fnum, off_t offset, uint1 { char *p; - bzero(cli->outbuf,smb_size); - bzero(cli->inbuf,smb_size); + memset(cli->outbuf,'\0',smb_size); + memset(cli->inbuf,'\0',smb_size); set_message(cli->outbuf,12,size,True); @@ -1673,7 +1568,8 @@ static void cli_issue_write(struct cli_state *cli, int fnum, off_t offset, uint1 SSVAL(cli->outbuf,smb_mid,cli->mid + i); - cli_send_smb(cli, True); + show_msg(cli->outbuf); + cli_send_smb(cli); } /**************************************************************************** @@ -1687,58 +1583,98 @@ ssize_t cli_write(struct cli_state *cli, int fnum, uint16 write_mode, char *buf, off_t offset, size_t size) { - int total = -1; - int issued=0; - int received=0; + int bwritten = 0; + int issued = 0; + int received = 0; int mpx = MAX(cli->max_mux-1, 1); int block = (cli->max_xmit - (smb_size+32)) & ~1023; - int mid; int blocks = (size + (block-1)) / block; - if (size == 0) return 0; - while (received < blocks) { - int size2; - while (issued - received < mpx && issued < blocks) { - int size1 = MIN(block, size-issued*block); - cli_issue_write(cli, fnum, offset+issued*block, + while ((issued - received < mpx) && (issued < blocks)) + { + int bsent = issued * block; + int size1 = MIN(block, size - bsent); + + cli_issue_write(cli, fnum, offset + bsent, write_mode, - buf + issued*block, + buf + bsent, size1, issued); issued++; } - if (!cli_receive_smb(cli)) { - return total; + if (!cli_receive_smb(cli)) + { + return bwritten; } received++; - mid = SVAL(cli->inbuf, smb_mid) - cli->mid; - size2 = SVAL(cli->inbuf, smb_vwv2); - - if (CVAL(cli->inbuf,smb_rcls) != 0) { - blocks = MIN(blocks, mid-1); - continue; - } - if (size2 <= 0) { - blocks = MIN(blocks, mid-1); - /* this distinguishes EOF from an error */ - total = MAX(total, 0); - continue; + if (CVAL(cli->inbuf,smb_rcls) != 0) + { + break; } - total += size2; - - total = MAX(total, mid*block + size2); + bwritten += SVAL(cli->inbuf, smb_vwv2); } - while (received < issued) { - cli_receive_smb(cli); + while (received < issued && cli_receive_smb(cli)) + { received++; } + return bwritten; +} + + +/**************************************************************************** + write to a file using a SMBwrite and not bypassing 0 byte writes +****************************************************************************/ +ssize_t cli_smbwrite(struct cli_state *cli, + int fnum, char *buf, off_t offset, size_t size1) +{ + char *p; + ssize_t total = 0; + + do { + size_t size = MIN(size1, cli->max_xmit - 48); + + memset(cli->outbuf,'\0',smb_size); + memset(cli->inbuf,'\0',smb_size); + + set_message(cli->outbuf,5, 3 + size,True); + + CVAL(cli->outbuf,smb_com) = SMBwrite; + SSVAL(cli->outbuf,smb_tid,cli->cnum); + cli_setup_packet(cli); + + SSVAL(cli->outbuf,smb_vwv0,fnum); + SSVAL(cli->outbuf,smb_vwv1,size); + SIVAL(cli->outbuf,smb_vwv2,offset); + SSVAL(cli->outbuf,smb_vwv4,0); + + p = smb_buf(cli->outbuf); + *p++ = 1; + SSVAL(p, 0, size); + memcpy(p+2, buf, size); + + cli_send_smb(cli); + if (!cli_receive_smb(cli)) { + return -1; + } + + if (CVAL(cli->inbuf,smb_rcls) != 0) { + return -1; + } + + size = SVAL(cli->inbuf,smb_vwv0); + if (size == 0) break; + + size1 -= size; + total += size; + } while (size1); + return total; } @@ -1750,10 +1686,10 @@ BOOL cli_getattrE(struct cli_state *cli, int fd, uint16 *attr, size_t *size, time_t *c_time, time_t *a_time, time_t *m_time) { - bzero(cli->outbuf,smb_size); - bzero(cli->inbuf,smb_size); + memset(cli->outbuf,'\0',smb_size); + memset(cli->inbuf,'\0',smb_size); - set_message(cli->outbuf,2,0,True); + set_message(cli->outbuf,1,0,True); CVAL(cli->outbuf,smb_com) = SMBgetattrE; SSVAL(cli->outbuf,smb_tid,cli->cnum); @@ -1761,7 +1697,7 @@ BOOL cli_getattrE(struct cli_state *cli, int fd, SSVAL(cli->outbuf,smb_vwv0,fd); - cli_send_smb(cli, True); + cli_send_smb(cli); if (!cli_receive_smb(cli)) { return False; } @@ -1802,8 +1738,8 @@ BOOL cli_getatr(struct cli_state *cli, char *fname, { char *p; - bzero(cli->outbuf,smb_size); - bzero(cli->inbuf,smb_size); + memset(cli->outbuf,'\0',smb_size); + memset(cli->inbuf,'\0',smb_size); set_message(cli->outbuf,0,strlen(fname)+2,True); @@ -1814,8 +1750,9 @@ BOOL cli_getatr(struct cli_state *cli, char *fname, p = smb_buf(cli->outbuf); *p = 4; pstrcpy(p+1, fname); + unix_to_dos(p+1,True); - cli_send_smb(cli, True); + cli_send_smb(cli); if (!cli_receive_smb(cli)) { return False; } @@ -1848,8 +1785,8 @@ BOOL cli_setatr(struct cli_state *cli, char *fname, uint16 attr, time_t t) { char *p; - bzero(cli->outbuf,smb_size); - bzero(cli->inbuf,smb_size); + memset(cli->outbuf,'\0',smb_size); + memset(cli->inbuf,'\0',smb_size); set_message(cli->outbuf,8,strlen(fname)+4,True); @@ -1863,10 +1800,11 @@ BOOL cli_setatr(struct cli_state *cli, char *fname, uint16 attr, time_t t) p = smb_buf(cli->outbuf); *p = 4; pstrcpy(p+1, fname); + unix_to_dos(p+1,True); p = skip_string(p,1); *p = 4; - cli_send_smb(cli, True); + cli_send_smb(cli); if (!cli_receive_smb(cli)) { return False; } @@ -1899,6 +1837,7 @@ BOOL cli_qpathinfo(struct cli_state *cli, const char *fname, memset(param, 0, param_len); SSVAL(param, 0, SMB_INFO_STANDARD); pstrcpy(¶m[6], fname); + unix_to_dos(¶m[6],True); do { ret = (cli_send_trans(cli, SMBtrans2, @@ -1916,7 +1855,7 @@ BOOL cli_qpathinfo(struct cli_state *cli, const char *fname, it gives ERRSRV/ERRerror temprarily */ uint8 eclass; uint32 ecode; - cli_error(cli, &eclass, &ecode); + cli_error(cli, &eclass, &ecode, NULL); if (eclass != ERRSRV || ecode != ERRerror) break; msleep(100); } @@ -1972,6 +1911,7 @@ BOOL cli_qpathinfo2(struct cli_state *cli, const char *fname, memset(param, 0, param_len); SSVAL(param, 0, SMB_QUERY_FILE_ALL_INFO); pstrcpy(¶m[6], fname); + unix_to_dos(¶m[6],True); if (!cli_send_trans(cli, SMBtrans2, NULL, 0, /* name, length */ @@ -2009,7 +1949,7 @@ BOOL cli_qpathinfo2(struct cli_state *cli, const char *fname, *mode = SVAL(rdata, 32); } if (size) { - *size = IVAL(rdata, 40); + *size = IVAL(rdata, 48); } if (ino) { *ino = IVAL(rdata, 64); @@ -2081,7 +2021,7 @@ BOOL cli_qfileinfo(struct cli_state *cli, int fnum, *mode = SVAL(rdata, 32); } if (size) { - *size = IVAL(rdata, 40); + *size = IVAL(rdata, 48); } if (ino) { *ino = IVAL(rdata, 64); @@ -2117,6 +2057,7 @@ static int interpret_long_filename(int level,char *p,file_info *finfo) finfo->size = IVAL(p,16); finfo->mode = CVAL(p,24); pstrcpy(finfo->name,p+27); + dos_to_unix(finfo->name,True); } return(28 + CVAL(p,26)); @@ -2129,6 +2070,7 @@ static int interpret_long_filename(int level,char *p,file_info *finfo) finfo->size = IVAL(p,16); finfo->mode = CVAL(p,24); pstrcpy(finfo->name,p+31); + dos_to_unix(finfo->name,True); } return(32 + CVAL(p,30)); @@ -2142,6 +2084,7 @@ static int interpret_long_filename(int level,char *p,file_info *finfo) finfo->size = IVAL(p,20); finfo->mode = CVAL(p,28); pstrcpy(finfo->name,p+33); + dos_to_unix(finfo->name,True); } return(SVAL(p,4)+4); @@ -2154,6 +2097,7 @@ static int interpret_long_filename(int level,char *p,file_info *finfo) finfo->size = IVAL(p,20); finfo->mode = CVAL(p,28); pstrcpy(finfo->name,p+37); + dos_to_unix(finfo->name,True); } return(SVAL(p,4)+4); @@ -2189,7 +2133,8 @@ static int interpret_long_filename(int level,char *p,file_info *finfo) p += 4; /* EA size */ p += 2; /* short name len? */ p += 24; /* short name? */ - StrnCpy(finfo->name,p,namelen); + StrnCpy(finfo->name,p,MIN(sizeof(finfo->name)-1,namelen)); + dos_to_unix(finfo->name,True); return(ret); } return(SVAL(p,0)); @@ -2217,7 +2162,6 @@ int cli_list(struct cli_state *cli,const char *Mask,uint16 attribute, int dirlist_len = 0; int total_received = -1; BOOL First = True; - int ff_resume_key = 0; int ff_searchcount=0; int ff_eos=0; int ff_lastname=0; @@ -2230,6 +2174,7 @@ int cli_list(struct cli_state *cli,const char *Mask,uint16 attribute, pstring param; pstrcpy(mask,Mask); + unix_to_dos(mask,True); while (ff_eos == 0) { loop_count++; @@ -2253,12 +2198,12 @@ int cli_list(struct cli_state *cli,const char *Mask,uint16 attribute, SSVAL(param,0,ff_dir_handle); SSVAL(param,2,max_matches); /* max count */ SSVAL(param,4,info_level); - SIVAL(param,6,ff_resume_key); /* ff_resume_key */ + SIVAL(param,6,0); /* ff_resume_key */ SSVAL(param,10,8+4+2); /* resume required + close on end + continue */ pstrcpy(param+12,mask); - DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n", - ff_dir_handle,ff_resume_key,ff_lastname,mask)); + DEBUG(5,("hand=0x%X ff_lastname=%d mask=%s\n", + ff_dir_handle,ff_lastname,mask)); } if (!cli_send_trans(cli, SMBtrans2, @@ -2279,7 +2224,7 @@ int cli_list(struct cli_state *cli,const char *Mask,uint16 attribute, it gives ERRSRV/ERRerror temprarily */ uint8 eclass; uint32 ecode; - cli_error(cli, &eclass, &ecode); + cli_error(cli, &eclass, &ecode, NULL); if (eclass != ERRSRV || ecode != ERRerror) break; msleep(100); continue; @@ -2311,19 +2256,19 @@ int cli_list(struct cli_state *cli,const char *Mask,uint16 attribute, switch(info_level) { case 260: - ff_resume_key =0; StrnCpy(mask,p+ff_lastname, - data_len-ff_lastname); + MIN(sizeof(mask)-1,data_len-ff_lastname)); break; case 1: pstrcpy(mask,p + ff_lastname + 1); - ff_resume_key = 0; break; } } else { pstrcpy(mask,""); } - + + dos_to_unix(mask, True); + /* and add them to the dirlist pool */ dirlist = Realloc(dirlist,dirlist_len + data_len); @@ -2347,8 +2292,10 @@ int cli_list(struct cli_state *cli,const char *Mask,uint16 attribute, if (rdata) free(rdata); rdata = NULL; if (rparam) free(rparam); rparam = NULL; - DEBUG(3,("received %d entries (eos=%d resume=%d)\n", - ff_searchcount,ff_eos,ff_resume_key)); + DEBUG(3,("received %d entries (eos=%d)\n", + ff_searchcount,ff_eos)); + + if (ff_searchcount > 0) loop_count = 0; First = False; } @@ -2383,6 +2330,7 @@ BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char char *rparam = NULL; char *rdata = NULL; int rprcnt, rdrcnt; + pstring dos_new_password; if (strlen(user) >= sizeof(fstring)-1) { DEBUG(0,("cli_oem_change_password: user name %s is too long.\n", user)); @@ -2408,19 +2356,22 @@ BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char */ memset(upper_case_old_pw, '\0', sizeof(upper_case_old_pw)); fstrcpy(upper_case_old_pw, old_password); + unix_to_dos(upper_case_old_pw,True); strupper(upper_case_old_pw); E_P16((uchar *)upper_case_old_pw, old_pw_hash); - if (!make_oem_passwd_hash( data, new_password, old_pw_hash, False)) - { - return False; - } + pstrcpy(dos_new_password, new_password); + unix_to_dos(dos_new_password, True); + + if (!make_oem_passwd_hash( data, dos_new_password, old_pw_hash, False)) + return False; /* * Now place the old password hash in the data. */ memset(upper_case_new_pw, '\0', sizeof(upper_case_new_pw)); fstrcpy(upper_case_new_pw, new_password); + unix_to_dos(upper_case_new_pw,True); strupper(upper_case_new_pw); E_P16((uchar *)upper_case_new_pw, new_pw_hash); @@ -2429,14 +2380,13 @@ BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char data_len = 532; - if (!cli_send_trans(cli,SMBtrans, + if (cli_send_trans(cli,SMBtrans, PIPE_LANMAN,strlen(PIPE_LANMAN), /* name, length */ 0,0, /* fid, flags */ NULL,0,0, /* setup, length, max */ param,param_len,2, /* param, length, max */ data,data_len,0 /* data, length, max */ - )) - { + ) == False) { DEBUG(0,("cli_oem_change_password: Failed to send password change for user %s\n", user )); return False; @@ -2466,7 +2416,7 @@ BOOL cli_negprot(struct cli_state *cli) int numprots; int plength; - bzero(cli->outbuf,smb_size); + memset(cli->outbuf,'\0',smb_size); /* setup the protocol strings */ for (plength=0,numprots=0; @@ -2482,6 +2432,7 @@ BOOL cli_negprot(struct cli_state *cli) numprots++) { *p++ = 2; pstrcpy(p,prots[numprots].name); + unix_to_dos(p,True); p += strlen(p) + 1; } @@ -2490,11 +2441,11 @@ BOOL cli_negprot(struct cli_state *cli) CVAL(smb_buf(cli->outbuf),0) = 2; - cli_send_smb(cli, True); + cli_send_smb(cli); if (!cli_receive_smb(cli)) - { return False; - } + + show_msg(cli->inbuf); if (CVAL(cli->inbuf,smb_rcls) != 0 || ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots)) { @@ -2504,56 +2455,28 @@ BOOL cli_negprot(struct cli_state *cli) cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot; - if (cli->protocol >= PROTOCOL_NT1) - { - char *buf = smb_buf(cli->inbuf); - int bcc = SVAL(cli->inbuf,smb_vwv+2*(CVAL(cli->inbuf,smb_wct))); + if (cli->protocol >= PROTOCOL_NT1) { /* NT protocol */ cli->sec_mode = CVAL(cli->inbuf,smb_vwv1); cli->max_mux = SVAL(cli->inbuf, smb_vwv1+1); cli->max_xmit = IVAL(cli->inbuf,smb_vwv3+1); cli->sesskey = IVAL(cli->inbuf,smb_vwv7+1); - cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1)*60; + cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1); + cli->serverzone *= 60; /* this time arrives in real GMT */ cli->servertime = interpret_long_date(cli->inbuf+smb_vwv11+1); - + memcpy(cli->cryptkey,smb_buf(cli->inbuf),8); cli->capabilities = IVAL(cli->inbuf,smb_vwv9+1); - if (IS_BITS_SET_ALL(cli->capabilities, CAP_RAW_MODE)) - { + if (cli->capabilities & 1) { cli->readbraw_supported = True; cli->writebraw_supported = True; } - - if (IS_BITS_SET_ALL(cli->capabilities, CAP_EXTENDED_SECURITY)) - { - /* oops, some kerberos-related nonsense. */ - /* expect to have to use NTLMSSP-over-SMB */ - DEBUG(10,("unknown kerberos-related (?) blob\n")); - memset(cli->cryptkey, 0, 8); - cli->server_domain[0] = 0; - } - else - { - memcpy(cli->cryptkey, buf,8); - if (bcc > 8) - { - unibuf_to_ascii(cli->server_domain, buf+8, - sizeof(cli->server_domain)); - } - else - { - cli->server_domain[0] = 0; - } - DEBUG(5,("server's domain: %s bcc: %d\n", - cli->server_domain, bcc)); - } - } - else if (cli->protocol >= PROTOCOL_LANMAN1) - { + } else if (cli->protocol >= PROTOCOL_LANMAN1) { cli->sec_mode = SVAL(cli->inbuf,smb_vwv1); cli->max_xmit = SVAL(cli->inbuf,smb_vwv2); cli->sesskey = IVAL(cli->inbuf,smb_vwv6); - cli->serverzone = SVALS(cli->inbuf,smb_vwv10)*60; + cli->serverzone = SVALS(cli->inbuf,smb_vwv10); + cli->serverzone *= 60; /* this time is converted to GMT by make_unix_date */ cli->servertime = make_unix_date(cli->inbuf+smb_vwv8); cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0); @@ -2584,11 +2507,6 @@ BOOL cli_session_request(struct cli_state *cli, memcpy(&(cli->calling), calling, sizeof(*calling)); memcpy(&(cli->called ), called , sizeof(*called )); - if (cli->port == 445) - { - return True; - } - /* put in the destination name */ p = cli->outbuf+len; name_mangle(cli->called .name, p, cli->called .name_type); @@ -2607,12 +2525,41 @@ BOOL cli_session_request(struct cli_state *cli, retry: #endif /* WITH_SSL */ - cli_send_smb(cli, True); + cli_send_smb(cli); DEBUG(5,("Sent session request\n")); if (!cli_receive_smb(cli)) return False; + if (CVAL(cli->inbuf,0) == 0x84) { + /* C. Hoch 9/14/95 Start */ + /* For information, here is the response structure. + * We do the byte-twiddling to for portability. + struct RetargetResponse{ + unsigned char type; + unsigned char flags; + int16 length; + int32 ip_addr; + int16 port; + }; + */ + int port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9); + /* SESSION RETARGET */ + putip((char *)&cli->dest_ip,cli->inbuf+4); + + close_sockets(); + cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, port, LONG_CONNECT_TIMEOUT); + if (cli->fd == -1) + return False; + + DEBUG(3,("Retargeted\n")); + + set_socket_options(cli->fd,user_socket_options); + + /* Try again */ + return cli_session_request(cli, calling, called); + } /* C. Hoch 9/14/95 End */ + #ifdef WITH_SSL if (CVAL(cli->inbuf,0) == 0x83 && CVAL(cli->inbuf,4) == 0x8e){ /* use ssl */ if (!sslutil_fd_is_ssl(cli->fd)){ @@ -2624,7 +2571,7 @@ retry: if (CVAL(cli->inbuf,0) != 0x82) { /* This is the wrong place to put the error... JRA. */ - cli->rap_error = CVAL(cli->inbuf,0); + cli->rap_error = CVAL(cli->inbuf,4); return False; } return(True); @@ -2637,7 +2584,6 @@ open the client sockets BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip) { extern struct in_addr ipzero; - int port = cli->port; fstrcpy(cli->desthost, host); @@ -2650,25 +2596,14 @@ BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip) cli->dest_ip = *ip; } - - if (port == 0) port = SMB_PORT2; + if (cli->port == 0) cli->port = 139; /* Set to default */ cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, - port, cli->timeout); + cli->port, cli->timeout); if (cli->fd == -1) - { - if (cli->port != 0) - { - return False; - } - port = SMB_PORT; - - cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, - port, cli->timeout); - if (cli->fd == -1) return False; - } + return False; - cli->port = port; + set_socket_options(cli->fd,user_socket_options); return True; } @@ -2677,14 +2612,6 @@ BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip) /**************************************************************************** initialise a client structure ****************************************************************************/ -void cli_init_creds(struct cli_state *cli, const struct ntuser_creds *usr) -{ - copy_nt_creds(&cli->usr, usr); -} - -/**************************************************************************** -initialise a client structure -****************************************************************************/ struct cli_state *cli_initialise(struct cli_state *cli) { if (!cli) { @@ -2707,7 +2634,7 @@ struct cli_state *cli_initialise(struct cli_state *cli) cli->mid = 1; cli->vuid = UID_FIELD_INVALID; cli->protocol = PROTOCOL_NT1; - cli->timeout = 20000; + cli->timeout = 20000; /* Timeout is in milliseconds. */ cli->bufsize = CLI_BUFFER_SIZE+4; cli->max_xmit = cli->bufsize; cli->outbuf = (char *)malloc(cli->bufsize); @@ -2717,39 +2644,19 @@ struct cli_state *cli_initialise(struct cli_state *cli) return False; } - cli->initialised = 1; - cli->capabilities = CAP_DFS | CAP_NT_SMBS | CAP_STATUS32; - cli->use_ntlmv2 = Auto; + memset(cli->outbuf, '\0', cli->bufsize); + memset(cli->inbuf, '\0', cli->bufsize); - cli_init_creds(cli, NULL); + cli->initialised = 1; return cli; } /**************************************************************************** -close the socket descriptor -****************************************************************************/ -void cli_close_socket(struct cli_state *cli) -{ -#ifdef WITH_SSL - if (cli->fd != -1) - { - sslutil_disconnect(cli->fd); - } -#endif /* WITH_SSL */ - if (cli->fd != -1) - { - close(cli->fd); - } - cli->fd = -1; -} - -/**************************************************************************** shutdown a client structure ****************************************************************************/ void cli_shutdown(struct cli_state *cli) { - DEBUG(10,("cli_shutdown\n")); if (cli->outbuf) { free(cli->outbuf); @@ -2758,7 +2665,12 @@ void cli_shutdown(struct cli_state *cli) { free(cli->inbuf); } - cli_close_socket(cli); +#ifdef WITH_SSL + if (cli->fd != -1) + sslutil_disconnect(cli->fd); +#endif /* WITH_SSL */ + if (cli->fd != -1) + close(cli->fd); memset(cli, 0, sizeof(*cli)); } @@ -2771,43 +2683,34 @@ void cli_shutdown(struct cli_state *cli) for 32 bit "warnings", a return code of 0 is expected. ****************************************************************************/ -int cli_error(struct cli_state *cli, uint8 *eclass, uint32 *num) +int cli_error(struct cli_state *cli, uint8 *eclass, uint32 *num, uint32 *nt_rpc_error) { - int flgs2; + int flgs2 = SVAL(cli->inbuf,smb_flg2); char rcls; int code; - if (!cli->initialised) - { - DEBUG(0,("cli_error: client state uninitialised!\n")); - return EINVAL; - } - - flgs2 = SVAL(cli->inbuf,smb_flg2); - if (eclass) *eclass = 0; if (num ) *num = 0; + if (nt_rpc_error) *nt_rpc_error = cli->nt_error; - if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) - { + if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) { /* 32 bit error codes detected */ uint32 nt_err = IVAL(cli->inbuf,smb_rcls); if (num) *num = nt_err; DEBUG(10,("cli_error: 32 bit codes: code=%08x\n", nt_err)); if (!IS_BITS_SET_ALL(nt_err, 0xc0000000)) return 0; - switch (nt_err & 0xFFFFFF) - { - case NT_STATUS_ACCESS_VIOLATION : return EACCES; - case NT_STATUS_NO_SUCH_FILE : return ENOENT; - case NT_STATUS_NO_SUCH_DEVICE : return ENODEV; - case NT_STATUS_INVALID_HANDLE : return EBADF; - case NT_STATUS_NO_MEMORY : return ENOMEM; - case NT_STATUS_ACCESS_DENIED : return EACCES; - case NT_STATUS_OBJECT_NAME_NOT_FOUND: return ENOENT; - case NT_STATUS_SHARING_VIOLATION : return EBUSY; - case NT_STATUS_OBJECT_PATH_INVALID : return ENOTDIR; - case NT_STATUS_OBJECT_NAME_COLLISION: return EEXIST; + switch (nt_err & 0xFFFFFF) { + case NT_STATUS_ACCESS_VIOLATION: return EACCES; + case NT_STATUS_NO_SUCH_FILE: return ENOENT; + case NT_STATUS_NO_SUCH_DEVICE: return ENODEV; + case NT_STATUS_INVALID_HANDLE: return EBADF; + case NT_STATUS_NO_MEMORY: return ENOMEM; + case NT_STATUS_ACCESS_DENIED: return EACCES; + case NT_STATUS_OBJECT_NAME_NOT_FOUND: return ENOENT; + case NT_STATUS_SHARING_VIOLATION: return EBUSY; + case NT_STATUS_OBJECT_PATH_INVALID: return ENOTDIR; + case NT_STATUS_OBJECT_NAME_COLLISION: return EEXIST; } /* for all other cases - a default code */ @@ -2830,7 +2733,6 @@ int cli_error(struct cli_state *cli, uint8 *eclass, uint32 *num) case ERRrename: return EEXIST; case ERRbadshare: return EBUSY; case ERRlock: return EBUSY; - case ERRmoredata: return 0; /* Informational only */ } } if (rcls == ERRSRV) { @@ -2887,36 +2789,29 @@ BOOL cli_reestablish_connection(struct cli_state *cli) if (cli->cnum != 0) { - do_tcon = True; - } - - if (do_tcon) - { fstrcpy(share, cli->share); fstrcpy(dev , cli->dev); + do_tcon = True; } memcpy(&called , &(cli->called ), sizeof(called )); memcpy(&calling, &(cli->calling), sizeof(calling)); - fstrcpy(dest_host, cli->desthost); + fstrcpy(dest_host, cli->full_dest_host_name); DEBUG(5,("cli_reestablish_connection: %s connecting to %s (ip %s) - %s [%s]\n", nmb_namestr(&calling), nmb_namestr(&called), inet_ntoa(cli->dest_ip), - cli->usr.user_name, cli->usr.domain)); + cli->user_name, cli->domain)); cli->fd = -1; if (cli_establish_connection(cli, dest_host, &cli->dest_ip, &calling, &called, - share, dev, False, do_tcon)) - { - if (cli->fd != oldfd) - { - if (dup2(cli->fd, oldfd) == oldfd) - { - cli_close_socket(cli); + share, dev, False, do_tcon)) { + if (cli->fd != oldfd) { + if (dup2(cli->fd, oldfd) == oldfd) { + close(cli->fd); } } return True; @@ -2924,101 +2819,18 @@ BOOL cli_reestablish_connection(struct cli_state *cli) return False; } -static BOOL cli_init_redirect(struct cli_state *cli, - const char* srv_name, struct in_addr *destip, - const struct ntuser_creds *usr) -{ - int sock; - fstring ip_name; - struct cli_state cli_redir; - fstring path; - - uint32 len; - char *data; - char *in = cli->inbuf; - char *out = cli->outbuf; - prs_struct ps; - uint16 command; - - slprintf(path, sizeof(path)-1, "/tmp/.smb.%d/agent", getuid()); - - if (strequal(srv_name, "*SMBSERVER")) - { - fstrcpy(ip_name, "\\\\"); - inet_aton(&ip_name[2], destip); - srv_name = ip_name; - } - - sock = open_pipe_sock(path); - - if (sock < 0) - { - return False; - } - - command = usr != NULL ? AGENT_CMD_CON : AGENT_CMD_CON_ANON; - - if (!create_ntuser_creds(&ps, srv_name, 0x0, command, usr, cli->reuse)) - { - DEBUG(0,("could not parse credentials\n")); - close(sock); - return False; - } - - len = ps.offset; - data = mem_data(&ps.data, 0); - -#ifdef DEBUG_PASSWORD - DEBUG(100,("data len: %d\n", len)); - dump_data(100, data, len); -#endif - - SIVAL(data, 0, len); - - if (write(sock, data, len) <= 0) - { - DEBUG(0,("write failed\n")); - close(sock); - return False; - } - - len = read(sock, &cli_redir, sizeof(cli_redir)); - - if (len != sizeof(cli_redir)) - { - DEBUG(0,("read failed\n")); - close(sock); - return False; - } - - memcpy(cli, &cli_redir, sizeof(cli_redir)); - cli->inbuf = in; - cli->outbuf = out; - cli->fd = sock; - cli->reuse = False; - - return sock; -} - /**************************************************************************** establishes a connection right up to doing tconX, reading in a password. ****************************************************************************/ BOOL cli_establish_connection(struct cli_state *cli, - const char *dest_host, struct in_addr *dest_ip, + char *dest_host, struct in_addr *dest_ip, struct nmb_name *calling, struct nmb_name *called, char *service, char *service_type, BOOL do_shutdown, BOOL do_tcon) { - fstring callingstr; - fstring calledstr; - - nmb_safe_namestr(calling, callingstr, sizeof(callingstr)); - nmb_safe_namestr(called , calledstr , sizeof(calledstr )); - - DEBUG(5,("cli_establish_connection: %s connecting to %s (%s) - %s [%s] with NTLM%s\n", - callingstr, calledstr, inet_ntoa(*dest_ip), - cli->usr.user_name, cli->usr.domain, - cli->use_ntlmv2 ? "v2" : "v1")); + DEBUG(5,("cli_establish_connection: %s connecting to %s (%s) - %s [%s]\n", + nmb_namestr(calling), nmb_namestr(called), inet_ntoa(*dest_ip), + cli->user_name, cli->domain)); /* establish connection */ @@ -3027,24 +2839,12 @@ BOOL cli_establish_connection(struct cli_state *cli, return False; } - if (cli->fd == -1 && cli->redirect) - { - if (cli_init_redirect(cli, dest_host, dest_ip, &cli->usr)) - { - DEBUG(10,("cli_establish_connection: redirected OK\n")); - return True; - } - else - { - DEBUG(10,("redirect FAILED, make direct connection\n")); - } - } if (cli->fd == -1) { if (!cli_connect(cli, dest_host, dest_ip)) { DEBUG(1,("cli_establish_connection: failed to connect to %s (%s)\n", - callingstr, inet_ntoa(*dest_ip))); + nmb_namestr(calling), inet_ntoa(*dest_ip))); return False; } } @@ -3053,9 +2853,7 @@ BOOL cli_establish_connection(struct cli_state *cli, { DEBUG(1,("failed session request\n")); if (do_shutdown) - { - cli_shutdown(cli); - } + cli_shutdown(cli); return False; } @@ -3063,242 +2861,33 @@ BOOL cli_establish_connection(struct cli_state *cli, { DEBUG(1,("failed negprot\n")); if (do_shutdown) - { - cli_shutdown(cli); - } + cli_shutdown(cli); return False; } - if (cli->usr.domain[0] == 0) - { - safe_strcpy(cli->usr.domain, cli->server_domain, - sizeof(cli->usr.domain)); - } - - if (IS_BITS_SET_ALL(cli->capabilities, CAP_EXTENDED_SECURITY)) + if (cli->pwd.cleartext || cli->pwd.null_pwd) { - /* common to both session setups */ - uint32 ntlmssp_flgs; - char pwd_buf[128]; - int buf_len; - char *p; - char *e = pwd_buf + sizeof(pwd_buf); - - /* 1st session setup */ - char pwd_data[34] = - { - 0x60, 0x40, 0x06, 0x06, 0x2b, 0x06, 0x01, 0x05, - 0x05, 0x02, 0xa0, 0x36, 0x30, 0x34, 0xa0, 0x0e, - 0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, - 0x01, 0x82, 0x37, 0x02, 0x02, 0x0a, 0xa2, 0x22, - 0x04, 0x20 - }; - /* 2nd session setup */ -#if 0 - char pwd_data_2[8] = - { - 0xa1, 0x51, 0x30, 0x4f, 0xa2, 0x4d, 0x04, 0x4b - }; -#endif - char pwd_data_2[8] = - { - 0xa1, 0x51, 0x30, 0x4f, 0xa2, 0x4d, 0x04, 0x4b - }; - prs_struct auth_resp; - int resp_len; - char *p_gssapi; - char *p_oem; - char *p_gssapi_end; - uint16 gssapi_len; - - memset(pwd_buf, 0, sizeof(pwd_buf)); - memcpy(pwd_buf, pwd_data, sizeof(pwd_data)); - p = pwd_buf + sizeof(pwd_data); - - safe_strcpy(p, "NTLMSSP", PTR_DIFF(e, p) - 1); - p = skip_string(p, 1); - CVAL(p, 0) = 0x1; - p += 4; - ntlmssp_flgs = - NTLMSSP_NEGOTIATE_UNICODE | - NTLMSSP_NEGOTIATE_OEM | - NTLMSSP_NEGOTIATE_SIGN | - NTLMSSP_NEGOTIATE_SEAL | - NTLMSSP_NEGOTIATE_LM_KEY | - NTLMSSP_NEGOTIATE_NTLM | - NTLMSSP_NEGOTIATE_ALWAYS_SIGN | - NTLMSSP_NEGOTIATE_00001000 | - NTLMSSP_NEGOTIATE_00002000; - SIVAL(p, 0, ntlmssp_flgs); - p += 4; - p += 16; /* skip some NULL space */ - CVAL(p, 0) = 0; p++; /* alignment */ - - buf_len = PTR_DIFF(p, pwd_buf); - - /* first session negotiation stage */ - if (!cli_session_setup_x(cli, cli->usr.user_name, - pwd_buf, buf_len, - NULL, 0, - cli->usr.domain)) - { - DEBUG(1,("failed session setup\n")); - if (do_shutdown) - { - cli_shutdown(cli); - } - return False; - } - - DEBUG(1,("1st session setup ok\n")); + fstring passwd; + int pass_len; - if (*cli->server_domain || *cli->server_os || *cli->server_type) - { - DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n", - cli->server_domain, - cli->server_os, - cli->server_type)); - } - - p = smb_buf(cli->inbuf) + 0x2f; - ntlmssp_flgs = IVAL(p, 0); /* 0x80808a05; */ - p += 4; - memcpy(cli->cryptkey, p, 8); -#ifdef DEBUG_PASSWORD - DEBUG(100,("cli_session_setup_x: ntlmssp %8x\n", - ntlmssp_flgs)); - - DEBUG(100,("cli_session_setup_x: crypt key\n")); - dump_data(100, cli->cryptkey, 8); -#endif - prs_init(&auth_resp, 1024, 4, SAFETY_MARGIN, False); - - if (cli->use_ntlmv2 != False) - { - DEBUG(10,("cli_establish_connection: NTLMv2\n")); - pwd_make_lm_nt_owf2(&(cli->usr.pwd), cli->cryptkey, - cli->usr.user_name, calling->name, cli->usr.domain); - } - else - { - DEBUG(10,("cli_establish_connection: NTLMv1\n")); - pwd_make_lm_nt_owf(&(cli->usr.pwd), cli->cryptkey); - } - - create_ntlmssp_resp(&cli->usr.pwd, cli->usr.domain, - cli->usr.user_name, cli->calling.name, - ntlmssp_flgs, - &auth_resp); - prs_link(NULL, &auth_resp, NULL); - - memset(pwd_buf, 0, sizeof(pwd_buf)); - p = pwd_buf; - - CVAL(p, 0) = 0xa1; p++; - CVAL(p, 0) = 0x82; p++; - p_gssapi = p; p+= 2; - CVAL(p, 0) = 0x30; p++; - CVAL(p, 0) = 0x82; p++; - p += 2; - - CVAL(p, 0) = 0xa2; p++; - CVAL(p, 0) = 0x82; p++; - p_oem = p; p+= 2; - CVAL(p, 0) = 0x04; p++; - CVAL(p, 0) = 0x82; p++; - p += 2; - - p_gssapi_end = p; - - safe_strcpy(p, "NTLMSSP", PTR_DIFF(e, p) - 1); - p = skip_string(p, 1); - CVAL(p, 0) = 0x3; - p += 4; - - resp_len = mem_buf_len(auth_resp.data); - mem_buf_copy(p, auth_resp.data, 0, resp_len); - prs_mem_free(&auth_resp); - - p += resp_len; - - buf_len = PTR_DIFF(p, pwd_buf); - gssapi_len = PTR_DIFF(p, p_gssapi_end) + 12; - - *p_gssapi++ = (gssapi_len >> 8) & 0xff; - *p_gssapi++ = gssapi_len & 0xff; - - p_gssapi += 2; - gssapi_len -= 4; - - *p_gssapi++ = (gssapi_len >> 8) & 0xff; - *p_gssapi++ = gssapi_len & 0xff; - - gssapi_len -= 4; - - *p_oem++ = (gssapi_len >> 8) & 0xff; - *p_oem++ = gssapi_len & 0xff; - - p_oem += 2; - gssapi_len -= 4; - - *p_oem++ = (gssapi_len >> 8) & 0xff; - *p_oem++ = gssapi_len & 0xff; - - /* second session negotiation stage */ - if (!cli_session_setup_x(cli, cli->usr.user_name, - pwd_buf, buf_len, - NULL, 0, - cli->usr.domain)) - { - DEBUG(1,("failed session setup\n")); - if (do_shutdown) - { - cli_shutdown(cli); - } - return False; - } - - DEBUG(1,("2nd session setup ok\n")); - - if (do_tcon) - { - if (!cli_send_tconX(cli, service, service_type, - NULL, 0)) - - { - DEBUG(1,("failed tcon_X\n")); - if (do_shutdown) - { - cli_shutdown(cli); - } - return False; - } - } - } - else if (cli->usr.pwd.cleartext || cli->usr.pwd.null_pwd) - { - fstring passwd, ntpasswd; - int pass_len = 0, ntpass_len = 0; - - if (cli->usr.pwd.null_pwd) + if (cli->pwd.null_pwd) { /* attempt null session */ - passwd[0] = ntpasswd[0] = 0; - pass_len = ntpass_len = 1; + passwd[0] = 0; + pass_len = 1; } else { /* attempt clear-text session */ - pwd_get_cleartext(&(cli->usr.pwd), passwd); + pwd_get_cleartext(&(cli->pwd), passwd); pass_len = strlen(passwd); } /* attempt clear-text session */ - if (!cli_session_setup(cli, calling->name, - cli->usr.user_name, + if (!cli_session_setup(cli, cli->user_name, passwd, pass_len, - ntpasswd, ntpass_len, - cli->usr.domain)) + NULL, 0, + cli->domain)) { DEBUG(1,("failed session setup\n")); if (do_shutdown) @@ -3324,68 +2913,25 @@ BOOL cli_establish_connection(struct cli_state *cli, else { /* attempt encrypted session */ + unsigned char nt_sess_pwd[24]; unsigned char lm_sess_pwd[24]; - unsigned char nt_sess_pwd[128]; - size_t nt_sess_pwd_len; - - if (cli->use_ntlmv2 != False) - { - DEBUG(10,("cli_establish_connection: NTLMv2\n")); - pwd_make_lm_nt_owf2(&(cli->usr.pwd), cli->cryptkey, - cli->usr.user_name, calling->name, cli->usr.domain); - } - else - { - DEBUG(10,("cli_establish_connection: NTLMv1\n")); - pwd_make_lm_nt_owf(&(cli->usr.pwd), cli->cryptkey); - } - pwd_get_lm_nt_owf(&(cli->usr.pwd), lm_sess_pwd, nt_sess_pwd, - &nt_sess_pwd_len, cli->sess_key); + /* creates (storing a copy of) and then obtains a 24 byte password OWF */ + pwd_make_lm_nt_owf(&(cli->pwd), cli->cryptkey); + pwd_get_lm_nt_owf(&(cli->pwd), lm_sess_pwd, nt_sess_pwd); /* attempt encrypted session */ - if (!cli_session_setup_x(cli, cli->usr.user_name, - (char*)lm_sess_pwd, sizeof(lm_sess_pwd), - (char*)nt_sess_pwd, nt_sess_pwd_len, - cli->usr.domain)) + if (!cli_session_setup(cli, cli->user_name, + (char*)lm_sess_pwd, sizeof(lm_sess_pwd), + (char*)nt_sess_pwd, sizeof(nt_sess_pwd), + cli->domain)) { DEBUG(1,("failed session setup\n")); - - if (cli->use_ntlmv2 == Auto) - { - DEBUG(10,("NTLMv2 failed. Using NTLMv1\n")); - cli->use_ntlmv2 = False; - if (do_tcon) - { - fstrcpy(cli->share, service); - fstrcpy(cli->dev, service_type); - } - fstrcpy(cli->desthost, dest_host); - cli_close_socket(cli); - return cli_establish_connection(cli, - dest_host, dest_ip, - calling, called, - service, service_type, - do_shutdown, do_tcon); - } - if (do_shutdown) - { - cli_shutdown(cli); - } + cli_shutdown(cli); return False; } - DEBUG(1,("session setup ok\n")); - - if (*cli->server_domain || *cli->server_os || *cli->server_type) - { - DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n", - cli->server_domain, - cli->server_os, - cli->server_type)); - } - if (do_tcon) { if (!cli_send_tconX(cli, service, service_type, @@ -3393,184 +2939,18 @@ BOOL cli_establish_connection(struct cli_state *cli, { DEBUG(1,("failed tcon_X\n")); if (do_shutdown) - { - cli_shutdown(cli); - } + cli_shutdown(cli); return False; } } } if (do_shutdown) - { - cli_shutdown(cli); - } - - return True; -} - -BOOL cli_connect_auth(struct cli_state *cli, - const char* desthost, - struct in_addr *dest_ip, - const struct ntuser_creds *usr) -{ - extern pstring global_myname; - extern pstring scope; - struct nmb_name calling, called; - - ZERO_STRUCTP(cli); - if (!cli_initialise(cli)) - { - DEBUG(0,("unable to initialise client connection.\n")); - return False; - } - - make_nmb_name(&calling, global_myname, 0x0 , scope); - make_nmb_name(&called , desthost , 0x20, scope); - - cli_init_creds(cli, usr); - - if (!cli_establish_connection(cli, desthost, dest_ip, - &calling, &called, - "IPC$", "IPC", - False, True)) - { - cli_shutdown(cli); - return False; - } + cli_shutdown(cli); return True; } -/**************************************************************************** - connect to one of multiple servers: don't care which -****************************************************************************/ -BOOL cli_connect_servers_auth(struct cli_state *cli, - char *p, - const struct ntuser_creds *usr) -{ - fstring remote_host; - BOOL connected_ok = False; - - /* - * Treat each name in the 'password server =' line as a potential - * PDC/BDC. Contact each in turn and try and authenticate. - */ - - while(p && next_token(&p,remote_host,LIST_SEP,sizeof(remote_host))) - { - fstring desthost; - struct in_addr dest_ip; - strupper(remote_host); - - if (!resolve_srv_name( remote_host, desthost, &dest_ip)) - { - DEBUG(1,("Can't resolve address for %s\n", remote_host)); - continue; - } - - if (!cli_connect_auth(cli, desthost, &dest_ip, usr) && - !cli_connect_auth(cli, "*SMBSERVER", &dest_ip, usr)) - { - continue; - } - - if (cli->protocol < PROTOCOL_LANMAN2 || - !IS_BITS_SET_ALL(cli->sec_mode, 1)) - { - DEBUG(1,("machine %s not in user level security mode\n", - remote_host)); - cli_shutdown(cli); - continue; - } - - /* - * We have an anonymous connection to IPC$. - */ - - connected_ok = True; - break; - } - - if (!connected_ok) - { - DEBUG(0,("Domain password server not available.\n")); - } - - return connected_ok; -} - -/**************************************************************************** - connect to one of multiple servers: don't care which -****************************************************************************/ -BOOL cli_connect_serverlist(struct cli_state *cli, char *p) -{ - fstring remote_host; - fstring desthost; - struct in_addr dest_ip; - BOOL connected_ok = False; - - /* - * Treat each name in the 'password server =' line as a potential - * PDC/BDC. Contact each in turn and try and authenticate. - */ - - while(p && next_token(&p,remote_host,LIST_SEP,sizeof(remote_host))) - { - ZERO_STRUCTP(cli); - - if (!cli_initialise(cli)) - { - DEBUG(0,("cli_connect_serverlist: unable to initialise client connection.\n")); - return False; - } - - standard_sub_basic(remote_host); - strupper(remote_host); - - if (!resolve_srv_name( remote_host, desthost, &dest_ip)) - { - DEBUG(1,("cli_connect_serverlist: Can't resolve address for %s\n", remote_host)); - continue; - } - - if ((lp_security() != SEC_USER) && (ismyip(dest_ip))) - { - DEBUG(1,("cli_connect_serverlist: Password server loop - not using password server %s\n", remote_host)); - continue; - } - - if (!cli_connect_auth(cli, remote_host , &dest_ip, NULL) && - !cli_connect_auth(cli, "*SMBSERVER", &dest_ip, NULL)) - { - continue; - } - - - if (cli->protocol < PROTOCOL_LANMAN2 || - !IS_BITS_SET_ALL(cli->sec_mode, 1)) - { - DEBUG(1,("cli_connect_serverlist: machine %s isn't in user level security mode\n", - remote_host)); - cli_shutdown(cli); - continue; - } - - /* - * We have an anonymous connection to IPC$. - */ - - connected_ok = True; - break; - } - - if (!connected_ok) - { - DEBUG(0,("cli_connect_serverlist: Domain password server not available.\n")); - } - - return connected_ok; -} /**************************************************************************** cancel a print job @@ -3583,7 +2963,7 @@ int cli_printjob_del(struct cli_state *cli, int job) int rdrcnt,rprcnt, ret = -1; pstring param; - bzero(param,sizeof(param)); + memset(param,'\0',sizeof(param)); p = param; SSVAL(p,0,81); /* DosPrintJobDel() */ @@ -3624,7 +3004,7 @@ int cli_print_queue(struct cli_state *cli, int result_code=0; int i = -1; - bzero(param,sizeof(param)); + memset(param,'\0',sizeof(param)); p = param; SSVAL(p,0,76); /* API function number 76 (DosPrintJobEnum) */ @@ -3686,29 +3066,29 @@ check for existance of a dir ****************************************************************************/ BOOL cli_chkpath(struct cli_state *cli, char *path) { - fstring path2; + pstring path2; char *p; - fstrcpy(path2,path); + safe_strcpy(path2,path,sizeof(pstring)); trim_string(path2,NULL,"\\"); if (!*path2) *path2 = '\\'; - bzero(cli->outbuf,smb_size); + memset(cli->outbuf,'\0',smb_size); set_message(cli->outbuf,0,4 + strlen(path2),True); SCVAL(cli->outbuf,smb_com,SMBchkpth); SSVAL(cli->outbuf,smb_tid,cli->cnum); cli_setup_packet(cli); - p = smb_buf(cli->outbuf); *p++ = 4; - fstrcpy(p,path2); + safe_strcpy(p,path2,strlen(path2)); + unix_to_dos(p,True); - cli_send_smb(cli, True); + cli_send_smb(cli); if (!cli_receive_smb(cli)) { return False; } - if (cli_error(cli, NULL, NULL)) return False; + if (cli_error(cli, NULL, NULL, NULL)) return False; return True; } @@ -3723,7 +3103,7 @@ BOOL cli_message_start(struct cli_state *cli, char *host, char *username, char *p; /* send a SMBsendstrt command */ - bzero(cli->outbuf,smb_size); + memset(cli->outbuf,'\0',smb_size); set_message(cli->outbuf,0,0,True); CVAL(cli->outbuf,smb_com) = SMBsendstrt; SSVAL(cli->outbuf,smb_tid,cli->cnum); @@ -3732,20 +3112,22 @@ BOOL cli_message_start(struct cli_state *cli, char *host, char *username, p = smb_buf(cli->outbuf); *p++ = 4; pstrcpy(p,username); + unix_to_dos(p,True); p = skip_string(p,1); *p++ = 4; pstrcpy(p,host); + unix_to_dos(p,True); p = skip_string(p,1); set_message(cli->outbuf,0,PTR_DIFF(p,smb_buf(cli->outbuf)),False); - cli_send_smb(cli, True); + cli_send_smb(cli); if (!cli_receive_smb(cli)) { return False; } - if (cli_error(cli, NULL, NULL)) return False; + if (cli_error(cli, NULL, NULL, NULL)) return False; *grp = SVAL(cli->inbuf,smb_vwv0); @@ -3760,7 +3142,7 @@ BOOL cli_message_text(struct cli_state *cli, char *msg, int len, int grp) { char *p; - bzero(cli->outbuf,smb_size); + memset(cli->outbuf,'\0',smb_size); set_message(cli->outbuf,1,len+3,True); CVAL(cli->outbuf,smb_com) = SMBsendtxt; SSVAL(cli->outbuf,smb_tid,cli->cnum); @@ -3772,13 +3154,13 @@ BOOL cli_message_text(struct cli_state *cli, char *msg, int len, int grp) *p = 1; SSVAL(p,1,len); memcpy(p+3,msg,len); - cli_send_smb(cli, True); + cli_send_smb(cli); if (!cli_receive_smb(cli)) { return False; } - if (cli_error(cli, NULL, NULL)) return False; + if (cli_error(cli, NULL, NULL, NULL)) return False; return True; } @@ -3788,7 +3170,7 @@ end a message ****************************************************************************/ BOOL cli_message_end(struct cli_state *cli, int grp) { - bzero(cli->outbuf,smb_size); + memset(cli->outbuf,'\0',smb_size); set_message(cli->outbuf,1,0,True); CVAL(cli->outbuf,smb_com) = SMBsendend; SSVAL(cli->outbuf,smb_tid,cli->cnum); @@ -3797,13 +3179,13 @@ BOOL cli_message_end(struct cli_state *cli, int grp) cli_setup_packet(cli); - cli_send_smb(cli, True); + cli_send_smb(cli); if (!cli_receive_smb(cli)) { return False; } - if (cli_error(cli, NULL, NULL)) return False; + if (cli_error(cli, NULL, NULL, NULL)) return False; return True; } @@ -3814,13 +3196,13 @@ query disk space ****************************************************************************/ BOOL cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail) { - bzero(cli->outbuf,smb_size); + memset(cli->outbuf,'\0',smb_size); set_message(cli->outbuf,0,0,True); CVAL(cli->outbuf,smb_com) = SMBdskattr; SSVAL(cli->outbuf,smb_tid,cli->cnum); cli_setup_packet(cli); - cli_send_smb(cli, True); + cli_send_smb(cli); if (!cli_receive_smb(cli)) { return False; } @@ -3832,21 +3214,49 @@ BOOL cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail) return True; } -BOOL get_any_dc_name(const char *domain, char *srv_name) +/**************************************************************************** + Attempt a NetBIOS session request, falling back to *SMBSERVER if needed. +****************************************************************************/ + +BOOL attempt_netbios_session_request(struct cli_state *cli, char *srchost, char *desthost, + struct in_addr *pdest_ip) { - struct cli_state cli; + struct nmb_name calling, called; - if (!cli_connect_servers_auth(&cli, - get_trusted_serverlist(domain), NULL)) - { - return False; - } + make_nmb_name(&calling, srchost, 0x0, scope); + + /* + * If the called name is an IP address + * then use *SMBSERVER immediately. + */ - fstrcpy(srv_name, "\\\\"); - fstrcat(srv_name, cli.desthost); - strupper(srv_name); + if(is_ipaddress(desthost)) + make_nmb_name(&called, "*SMBSERVER", 0x20, scope); + else + make_nmb_name(&called, desthost, 0x20, scope); - cli_shutdown(&cli); + if (!cli_session_request(cli, &calling, &called)) { + struct nmb_name smbservername; - return True; + /* + * If the name wasn't *SMBSERVER then + * try with *SMBSERVER if the first name fails. + */ + + cli_shutdown(cli); + + make_nmb_name(&smbservername , "*SMBSERVER", 0x20, scope); + + if (!nmb_name_equal(&called, &smbservername) || + !cli_initialise(cli) || + !cli_connect(cli, desthost, pdest_ip) || + !cli_session_request(cli, &calling, &smbservername)) { + DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER.\n", + desthost)); + cli_shutdown(cli); + return False; + } + } + + return True; } diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c index 299145ceff..abb9b7d42f 100644 --- a/source3/libsmb/namequery.c +++ b/source3/libsmb/namequery.c @@ -23,17 +23,15 @@ #include "includes.h" extern pstring scope; -extern pstring global_myname; extern int DEBUGLEVEL; /* nmbd.c sets this to True. */ BOOL global_in_nmbd = False; - static int name_trn_id = 0; - /**************************************************************************** -interpret a node status response + Interpret a node status response. ****************************************************************************/ + static void _interpret_node_status(char *p, char *master,char *rname) { int numnames = CVAL(p,0); @@ -43,55 +41,54 @@ static void _interpret_node_status(char *p, char *master,char *rname) if (master) *master = 0; p += 1; - while (numnames--) - { - char qname[17]; - int type; - fstring flags; - int i; - *flags = 0; - StrnCpy(qname,p,15); - type = CVAL(p,15); - p += 16; - - fstrcat(flags, (p[0] & 0x80) ? "<GROUP> " : " "); - if ((p[0] & 0x60) == 0x00) fstrcat(flags,"B "); - if ((p[0] & 0x60) == 0x20) fstrcat(flags,"P "); - if ((p[0] & 0x60) == 0x40) fstrcat(flags,"M "); - if ((p[0] & 0x60) == 0x60) fstrcat(flags,"H "); - if (p[0] & 0x10) fstrcat(flags,"<DEREGISTERING> "); - if (p[0] & 0x08) fstrcat(flags,"<CONFLICT> "); - if (p[0] & 0x04) fstrcat(flags,"<ACTIVE> "); - if (p[0] & 0x02) fstrcat(flags,"<PERMANENT> "); - - if (master && !*master && type == 0x1d) { - StrnCpy(master,qname,15); - trim_string(master,NULL," "); - } + while (numnames--) { + char qname[17]; + int type; + fstring flags; + int i; + *flags = 0; + StrnCpy(qname,p,15); + type = CVAL(p,15); + p += 16; + + fstrcat(flags, (p[0] & 0x80) ? "<GROUP> " : " "); + if ((p[0] & 0x60) == 0x00) fstrcat(flags,"B "); + if ((p[0] & 0x60) == 0x20) fstrcat(flags,"P "); + if ((p[0] & 0x60) == 0x40) fstrcat(flags,"M "); + if ((p[0] & 0x60) == 0x60) fstrcat(flags,"H "); + if (p[0] & 0x10) fstrcat(flags,"<DEREGISTERING> "); + if (p[0] & 0x08) fstrcat(flags,"<CONFLICT> "); + if (p[0] & 0x04) fstrcat(flags,"<ACTIVE> "); + if (p[0] & 0x02) fstrcat(flags,"<PERMANENT> "); + + if (master && !*master && type == 0x1d) { + StrnCpy(master,qname,15); + trim_string(master,NULL," "); + } - if (rname && !*rname && type == 0x20 && !(p[0]&0x80)) { - StrnCpy(rname,qname,15); - trim_string(rname,NULL," "); - } + if (rname && !*rname && type == 0x20 && !(p[0]&0x80)) { + StrnCpy(rname,qname,15); + trim_string(rname,NULL," "); + } - for (i = strlen( qname) ; --i >= 0 ; ) { - if (!isprint((int)qname[i])) qname[i] = '.'; - } - DEBUG(1,("\t%-15s <%02x> - %s\n",qname,type,flags)); - p+=2; + for (i = strlen( qname) ; --i >= 0 ; ) { + if (!isprint((int)qname[i])) qname[i] = '.'; } + DEBUG(1,("\t%-15s <%02x> - %s\n",qname,type,flags)); + p+=2; + } + DEBUG(1,("num_good_sends=%d num_good_receives=%d\n", IVAL(p,20),IVAL(p,24))); } - /**************************************************************************** - do a netbios name status query on a host + Internal function handling a netbios name status query on a host. +**************************************************************************/ - the "master" parameter is a hack used for finding workgroups. - **************************************************************************/ -BOOL name_status(int fd,char *name,int name_type,BOOL recurse, - struct in_addr to_ip,char *master,char *rname, +static BOOL internal_name_status(int fd,char *name,int name_type,BOOL recurse, + struct in_addr to_ip,char *master,char *rname, BOOL verbose, + void (*fn_interpret_node_status)(char *, char *,char *), void (*fn)(struct packet_struct *)) { BOOL found=False; @@ -101,21 +98,9 @@ BOOL name_status(int fd,char *name,int name_type,BOOL recurse, struct packet_struct p; struct packet_struct *p2; struct nmb_packet *nmb = &p.packet.nmb; - int packet_type = NMB_PACKET; - BOOL first_time = True; + static int name_trn_id = 0; - if (fd == -1) - { - retries = 1; - packet_type = NMB_SOCK_PACKET; - fd = get_nmb_sock(); - - if (fd < 0) - { - return False; - } - } - bzero((char *)&p,sizeof(p)); + memset((char *)&p,'\0',sizeof(p)); if (!name_trn_id) name_trn_id = ((unsigned)time(NULL)%(unsigned)0x7FFF) + ((unsigned)getpid()%(unsigned)100); @@ -144,39 +129,40 @@ BOOL name_status(int fd,char *name,int name_type,BOOL recurse, p.port = NMB_PORT; p.fd = fd; p.timestamp = time(NULL); - p.packet_type = packet_type; + p.packet_type = NMB_PACKET; GetTimeOfDay(&tval); - while (1) - { - struct timeval tval2; - GetTimeOfDay(&tval2); - if (first_time || TvalDiff(&tval,&tval2) > retry_time) - { - first_time = False; - if (!found && !send_packet(&p)) - { - if (packet_type == NMB_SOCK_PACKET) close(fd); - return False; - } - GetTimeOfDay(&tval); - } + if (!send_packet(&p)) + return(False); + + retries--; + + while (1) { + struct timeval tval2; + GetTimeOfDay(&tval2); + if (TvalDiff(&tval,&tval2) > retry_time) { + if (!retries) + break; + if (!found && !send_packet(&p)) + return False; + GetTimeOfDay(&tval); + retries--; + } - if ((p2=receive_packet(fd,packet_type,90))) - { - struct nmb_packet *nmb2 = &p2->packet.nmb; + if ((p2=receive_packet(fd,NMB_PACKET,90))) { + struct nmb_packet *nmb2 = &p2->packet.nmb; debug_nmb_packet(p2); - if (nmb->header.name_trn_id != nmb2->header.name_trn_id || - !nmb2->header.response) { - /* its not for us - maybe deal with it later */ - if (fn) - fn(p2); - else - free_packet(p2); - continue; - } + if (nmb->header.name_trn_id != nmb2->header.name_trn_id || + !nmb2->header.response) { + /* its not for us - maybe deal with it later */ + if (fn) + fn(p2); + else + free_packet(p2); + continue; + } if (nmb2->header.opcode != 0 || nmb2->header.nm_flags.bcast || @@ -189,55 +175,53 @@ BOOL name_status(int fd,char *name,int name_type,BOOL recurse, continue; } - retries--; - - _interpret_node_status(&nmb2->answers->rdata[0], master,rname); + if(fn_interpret_node_status) + (*fn_interpret_node_status)(&nmb2->answers->rdata[0],master,rname); free_packet(p2); - if (packet_type == NMB_SOCK_PACKET) close(fd); return(True); } - } - + } - DEBUG(0,("No status response (this is not unusual)\n")); + if(verbose) + DEBUG(0,("No status response (this is not unusual)\n")); -if (packet_type == NMB_SOCK_PACKET) close(fd); return(False); } +/**************************************************************************** + Do a netbios name status query on a host. + The "master" parameter is a hack used for finding workgroups. +**************************************************************************/ + +BOOL name_status(int fd,char *name,int name_type,BOOL recurse, + struct in_addr to_ip,char *master,char *rname, + void (*fn)(struct packet_struct *)) +{ + return internal_name_status(fd,name,name_type,recurse, + to_ip,master,rname,True, + _interpret_node_status, fn); +} /**************************************************************************** - do a netbios name query to find someones IP - returns an array of IP addresses or NULL if none - *count will be set to the number of addresses returned - ****************************************************************************/ + Do a netbios name query to find someones IP. + Returns an array of IP addresses or NULL if none. + *count will be set to the number of addresses returned. +****************************************************************************/ + struct in_addr *name_query(int fd,const char *name,int name_type, BOOL bcast,BOOL recurse, struct in_addr to_ip, int *count, void (*fn)(struct packet_struct *)) { BOOL found=False; int i, retries = 3; - int retry_time = bcast?2000:2000; + int retry_time = bcast?250:2000; struct timeval tval; struct packet_struct p; struct packet_struct *p2; struct nmb_packet *nmb = &p.packet.nmb; + static int name_trn_id = 0; struct in_addr *ip_list = NULL; - BOOL packet_type = NMB_PACKET; - BOOL first_send = True; - - if (fd == -1) - { - retries = 1; - packet_type = NMB_SOCK_PACKET; - fd = get_nmb_sock(); - - if (fd < 0) - { - return NULL; - } - } - bzero((char *)&p,sizeof(p)); + memset((char *)&p,'\0',sizeof(p)); (*count) = 0; if (!name_trn_id) name_trn_id = ((unsigned)time(NULL)%(unsigned)0x7FFF) + @@ -267,27 +251,30 @@ struct in_addr *name_query(int fd,const char *name,int name_type, BOOL bcast,BOO p.port = NMB_PORT; p.fd = fd; p.timestamp = time(NULL); - p.packet_type = packet_type; + p.packet_type = NMB_PACKET; + + GetTimeOfDay(&tval); - GetTimeOfDay(&tval); + if (!send_packet(&p)) + return NULL; - while (retries >= 0) + retries--; + + while (1) { struct timeval tval2; - GetTimeOfDay(&tval2); - if (first_send || TvalDiff(&tval,&tval2) > retry_time) + if (TvalDiff(&tval,&tval2) > retry_time) { - first_send = False; + if (!retries) + break; if (!found && !send_packet(&p)) - { - if (packet_type == NMB_SOCK_PACKET) close(fd); return NULL; - } GetTimeOfDay(&tval); + retries--; } - if ((p2=receive_packet(fd,packet_type,90))) + if ((p2=receive_packet(fd,NMB_PACKET,90))) { struct nmb_packet *nmb2 = &p2->packet.nmb; debug_nmb_packet(p2); @@ -295,8 +282,6 @@ struct in_addr *name_query(int fd,const char *name,int name_type, BOOL bcast,BOO if (nmb->header.name_trn_id != nmb2->header.name_trn_id || !nmb2->header.response) { - DEBUG(10,("packet not for us (received %d, expected %d\n", - nmb2->header.name_trn_id, nmb->header.name_trn_id)); /* * Its not for us - maybe deal with it later * (put it on the queue?). @@ -305,12 +290,9 @@ struct in_addr *name_query(int fd,const char *name,int name_type, BOOL bcast,BOO fn(p2); else free_packet(p2); - continue; } - retries--; - if (nmb2->header.opcode != 0 || nmb2->header.nm_flags.bcast || nmb2->header.rcode || @@ -345,15 +327,16 @@ struct in_addr *name_query(int fd,const char *name,int name_type, BOOL bcast,BOO if (fn) break; - if(found) - { - DEBUG(10,("returning OK\n")); + /* + * If we're doing a unicast lookup we only + * expect one reply. Don't wait the full 2 + * seconds if we got one. JRA. + */ + if(!bcast && found) break; - } } } - if (packet_type == NMB_SOCK_PACKET) close(fd); return ip_list; } @@ -375,6 +358,7 @@ FILE *startlmhosts(char *fname) /******************************************************** Parse the next line in the lmhosts file. *********************************************************/ + BOOL getlmhostsent( FILE *fp, pstring name, int *name_type, struct in_addr *ipaddr) { pstring line; @@ -439,7 +423,7 @@ BOOL getlmhostsent( FILE *fp, pstring name, int *name_type, struct in_addr *ipad char *endptr; ptr++; - *name_type = (int)strtol(ptr, &endptr,0); + *name_type = (int)strtol(ptr, &endptr, 16); if(!*ptr || (endptr == ptr)) { @@ -465,108 +449,107 @@ void endlmhosts(FILE *fp) fclose(fp); } - - /******************************************************** -resolve via "bcast" method + Resolve via "bcast" method. *********************************************************/ -static BOOL resolve_bcast(const char *name, struct in_addr *return_ip, int name_type) + +static BOOL resolve_bcast(const char *name, int name_type, + struct in_addr **return_ip_list, int *return_count) { int sock, i; + int num_interfaces = iface_count(); + + *return_ip_list = NULL; + *return_count = 0; /* * "bcast" means do a broadcast lookup on all the local interfaces. */ - DEBUG(3,("resolve_name: Attempting broadcast lookup for name %s<0x20>\n", name)); + DEBUG(3,("resolve_bcast: Attempting broadcast lookup for name %s<0x%x>\n", name, name_type)); sock = open_socket_in( SOCK_DGRAM, 0, 3, - interpret_addr(lp_socket_address()) ); - - if (sock != -1) { - struct in_addr *iplist = NULL; - int count; - int num_interfaces = iface_count(); - set_socket_options(sock,"SO_BROADCAST"); - /* - * Lookup the name on all the interfaces, return on - * the first successful match. - */ - for( i = 0; i < num_interfaces; i++) { - struct in_addr sendto_ip; - /* Done this way to fix compiler error on IRIX 5.x */ - sendto_ip = *iface_bcast(*iface_n_ip(i)); - iplist = name_query(sock, name, name_type, True, - True, sendto_ip, &count, NULL); - if(iplist != NULL) { - *return_ip = iplist[0]; - free((char *)iplist); - close(sock); - return True; - } + interpret_addr(lp_socket_address()), True ); + + if (sock == -1) return False; + + set_socket_options(sock,"SO_BROADCAST"); + /* + * Lookup the name on all the interfaces, return on + * the first successful match. + */ + for( i = num_interfaces-1; i >= 0; i--) { + struct in_addr sendto_ip; + /* Done this way to fix compiler error on IRIX 5.x */ + sendto_ip = *iface_bcast(*iface_n_ip(i)); + *return_ip_list = name_query(sock, name, name_type, True, + True, sendto_ip, return_count, NULL); + if(*return_ip_list != NULL) { + close(sock); + return True; } - close(sock); } + close(sock); return False; } - - /******************************************************** -resolve via "wins" method + Resolve via "wins" method. *********************************************************/ -static BOOL resolve_wins(const char *name, struct in_addr *return_ip, int name_type) + +static BOOL resolve_wins(const char *name, int name_type, + struct in_addr **return_iplist, int *return_count) { - int sock; - struct in_addr wins_ip; - BOOL wins_ismyip; + int sock; + struct in_addr wins_ip; + BOOL wins_ismyip; - /* - * "wins" means do a unicast lookup to the WINS server. - * Ignore if there is no WINS server specified or if the - * WINS server is one of our interfaces (if we're being - * called from within nmbd - we can't do this call as we - * would then block). - */ + *return_iplist = NULL; + *return_count = 0; + + /* + * "wins" means do a unicast lookup to the WINS server. + * Ignore if there is no WINS server specified or if the + * WINS server is one of our interfaces (if we're being + * called from within nmbd - we can't do this call as we + * would then block). + */ - DEBUG(3,("resolve_name: Attempting wins lookup for name %s<0x20>\n", name)); + DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n", name, name_type)); - if(!*lp_wins_server()) { - DEBUG(3,("resolve_name: WINS server resolution selected and no WINS server present.\n")); - return False; - } + if(!*lp_wins_server()) { + DEBUG(3,("resolve_wins: WINS server resolution selected and no WINS server present.\n")); + return False; + } - wins_ip = *interpret_addr2(lp_wins_server()); - wins_ismyip = ismyip(wins_ip); + wins_ip = *interpret_addr2(lp_wins_server()); + wins_ismyip = ismyip(wins_ip); - if((wins_ismyip && !global_in_nmbd) || !wins_ismyip) { - sock = open_socket_in( SOCK_DGRAM, 0, 3, - interpret_addr(lp_socket_address()) ); + if((wins_ismyip && !global_in_nmbd) || !wins_ismyip) { + sock = open_socket_in( SOCK_DGRAM, 0, 3, + interpret_addr(lp_socket_address()), True ); - if (sock != -1) { - struct in_addr *iplist = NULL; - int count; - iplist = name_query(sock, name, name_type, False, - True, wins_ip, &count, NULL); - if(iplist != NULL) { - *return_ip = iplist[0]; - free((char *)iplist); - close(sock); - return True; - } - close(sock); - } - } + if (sock != -1) { + *return_iplist = name_query(sock, name, name_type, False, + True, wins_ip, return_count, NULL); + if(*return_iplist != NULL) { + close(sock); + return True; + } + close(sock); + } + } - return False; + return False; } - /******************************************************** -resolve via "lmhosts" method + Resolve via "lmhosts" method. *********************************************************/ -static BOOL resolve_lmhosts(const char *name, struct in_addr *return_ip, int name_type) + +static BOOL resolve_lmhosts(const char *name, int name_type, + struct in_addr **return_iplist, int *return_count) { /* * "lmhosts" means parse the local lmhosts file. @@ -575,15 +558,27 @@ static BOOL resolve_lmhosts(const char *name, struct in_addr *return_ip, int nam FILE *fp; pstring lmhost_name; int name_type2; + struct in_addr return_ip; + + *return_iplist = NULL; + *return_count = 0; - DEBUG(3,("resolve_name: Attempting lmhosts lookup for name %s\n", name)); + DEBUG(3,("resolve_lmhosts: Attempting lmhosts lookup for name %s<0x%x>\n", name, name_type)); fp = startlmhosts( LMHOSTSFILE ); if(fp) { - while (getlmhostsent(fp, lmhost_name, &name_type2, return_ip)) { + while (getlmhostsent(fp, lmhost_name, &name_type2, &return_ip)) { if (strequal(name, lmhost_name) && - name_type == name_type2) { + ((name_type2 == -1) || (name_type == name_type2)) + ) { endlmhosts(fp); + *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr)); + if(*return_iplist == NULL) { + DEBUG(3,("resolve_lmhosts: malloc fail !\n")); + return False; + } + **return_iplist = return_ip; + *return_count = 1; return True; } } @@ -594,89 +589,94 @@ static BOOL resolve_lmhosts(const char *name, struct in_addr *return_ip, int nam /******************************************************** -resolve via "hosts" method + Resolve via "hosts" method. *********************************************************/ -static BOOL resolve_hosts(const char *name, struct in_addr *return_ip) + +static BOOL resolve_hosts(const char *name, + struct in_addr **return_iplist, int *return_count) { /* * "host" means do a localhost, or dns lookup. */ struct hostent *hp; - DEBUG(3,("resolve_name: Attempting host lookup for name %s\n", name)); + *return_iplist = NULL; + *return_count = 0; + + DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x20>\n", name)); if (((hp = Get_Hostbyname(name)) != NULL) && (hp->h_addr != NULL)) { - putip((char *)return_ip,(char *)hp->h_addr); + struct in_addr return_ip; + putip((char *)&return_ip,(char *)hp->h_addr); + *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr)); + if(*return_iplist == NULL) { + DEBUG(3,("resolve_hosts: malloc fail !\n")); + return False; + } + **return_iplist = return_ip; + *return_count = 1; return True; } return False; } - /******************************************************** - Resolve a name into an IP address. Use this function if - the string is either an IP address, DNS or host name - or NetBIOS name. This uses the name switch in the + Internal interface to resolve a name into an IP address. + Use this function if the string is either an IP address, DNS + or host name or NetBIOS name. This uses the name switch in the smb.conf to determine the order of name resolution. *********************************************************/ -BOOL is_ip_address(const char *name) -{ - int i; - for (i=0; name[i]; i++) - if (!(isdigit((int)name[i]) || name[i] == '.')) - return False; - - return True; -} -/******************************************************** - Resolve a name into an IP address. Use this function if - the string is either an IP address, DNS or host name - or NetBIOS name. This uses the name switch in the - smb.conf to determine the order of name resolution. -*********************************************************/ -BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type) +static BOOL internal_resolve_name(const char *name, int name_type, + struct in_addr **return_iplist, int *return_count) { pstring name_resolve_list; fstring tok; char *ptr; - - if (strcmp(name,"0.0.0.0") == 0) { - return_ip->s_addr = 0; - return True; - } - if (strcmp(name,"255.255.255.255") == 0) { - return_ip->s_addr = 0xFFFFFFFF; - return True; - } - - /* if it's in the form of an IP address then get the lib to interpret it */ - if (is_ip_address(name)) { - return_ip->s_addr = inet_addr(name); + BOOL allones = (strcmp(name,"255.255.255.255") == 0); + BOOL allzeros = (strcmp(name,"0.0.0.0") == 0); + BOOL is_address = is_ipaddress(name); + *return_iplist = NULL; + *return_count = 0; + + if (allzeros || allones || is_address) { + *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr)); + if(*return_iplist == NULL) { + DEBUG(3,("internal_resolve_name: malloc fail !\n")); + return False; + } + if(is_address) { + /* if it's in the form of an IP address then get the lib to interpret it */ + (*return_iplist)->s_addr = inet_addr(name); + } else { + (*return_iplist)->s_addr = allones ? 0xFFFFFFFF : 0; + *return_count = 1; + } return True; } - + pstrcpy(name_resolve_list, lp_name_resolve_order()); ptr = name_resolve_list; - if (!ptr || !*ptr) ptr = "host"; + if (!ptr || !*ptr) + ptr = "host"; while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) { if((strequal(tok, "host") || strequal(tok, "hosts"))) { - if (name_type == 0x20 && resolve_hosts(name, return_ip)) { + if (name_type == 0x20 && resolve_hosts(name, return_iplist, return_count)) { return True; } } else if(strequal( tok, "lmhosts")) { - if (resolve_lmhosts(name, return_ip, name_type)) { + if (resolve_lmhosts(name, name_type, return_iplist, return_count)) { return True; } } else if(strequal( tok, "wins")) { /* don't resolve 1D via WINS */ if (name_type != 0x1D && - resolve_wins(name, return_ip, name_type)) { + resolve_wins(name, name_type, return_iplist, return_count)) { return True; } } else if(strequal( tok, "bcast")) { - if (resolve_bcast(name, return_ip, name_type)) { + if (resolve_bcast(name, name_type, return_iplist, return_count)) { return True; } } else { @@ -684,50 +684,319 @@ BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type) } } + if((*return_iplist) != NULL) { + free((char *)(*return_iplist)); + *return_iplist = NULL; + } return False; } /******************************************************** - resolve a name of format \\server_name or \\ipaddress - into a name. also, cut the \\ from the front for us. + Internal interface to resolve a name into one IP address. + Use this function if the string is either an IP address, DNS + or host name or NetBIOS name. This uses the name switch in the + smb.conf to determine the order of name resolution. *********************************************************/ -BOOL resolve_srv_name(const char* srv_name, fstring dest_host, - struct in_addr *ip) -{ - BOOL ret; - const char *sv_name = srv_name; - DEBUG(10,("resolve_srv_name: %s\n", srv_name)); +BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type) +{ + struct in_addr *ip_list = NULL; + int count = 0; - if (srv_name == NULL || strequal("\\\\.", srv_name)) - { - fstrcpy(dest_host, global_myname); - ip = interpret_addr2("127.0.0.1"); + if(internal_resolve_name(name, name_type, &ip_list, &count)) { + *return_ip = ip_list[0]; + free((char *)ip_list); return True; } + if(ip_list != NULL) + free((char *)ip_list); + return False; +} - if (strnequal("\\\\", srv_name, 2)) - { - sv_name = &srv_name[2]; - } +/******************************************************** + Find the IP address of the master browser or DMB for a workgroup. +*********************************************************/ - fstrcpy(dest_host, sv_name); - ret = resolve_name(dest_host, ip, 0x20); - - if (is_ip_address(dest_host)) - { - fstrcpy(dest_host, "*SMBSERVER"); +BOOL find_master_ip(char *group, struct in_addr *master_ip) +{ + struct in_addr *ip_list = NULL; + int count = 0; + + if (internal_resolve_name(group, 0x1D, &ip_list, &count)) { + *master_ip = ip_list[0]; + free((char *)ip_list); + return True; } - - return ret; + if(internal_resolve_name(group, 0x1B, &ip_list, &count)) { + *master_ip = ip_list[0]; + free((char *)ip_list); + return True; + } + + if(ip_list != NULL) + free((char *)ip_list); + return False; } /******************************************************** -find the IP address of the master browser or DMB for a workgroup + Internal function to extract the MACHINE<0x20> name. *********************************************************/ -BOOL find_master_ip(char *group, struct in_addr *master_ip) + +static void _lookup_pdc_name(char *p, char *master,char *rname) +{ + int numnames = CVAL(p,0); + + *rname = '\0'; + + p += 1; + while (numnames--) { + int type = CVAL(p,15); + if(type == 0x20) { + StrnCpy(rname,p,15); + trim_string(rname,NULL," "); + return; + } + p += 18; + } +} + +/******************************************************** + Lookup a PDC name given a Domain name and IP address. +*********************************************************/ + +BOOL lookup_pdc_name(const char *srcname, const char *domain, struct in_addr *pdc_ip, char *ret_name) { - if (resolve_name(group, master_ip, 0x1D)) return True; +#if !defined(I_HATE_WINDOWS_REPLY_CODE) + + fstring pdc_name; + BOOL ret; + + /* + * Due to the fact win WinNT *sucks* we must do a node status + * query here... JRA. + */ - return resolve_name(group, master_ip, 0x1B); + int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True ); + + if(sock == -1) + return False; + + *pdc_name = '\0'; + + ret = internal_name_status(sock,"*SMBSERVER",0x20,True, + *pdc_ip,NULL,pdc_name,False, + _lookup_pdc_name,NULL); + + close(sock); + + if(ret && *pdc_name) { + fstrcpy(ret_name, pdc_name); + return True; + } + + return False; + +#else /* defined(I_HATE_WINDOWS_REPLY_CODE) */ + /* + * Sigh. I *love* this code, it took me ages to get right and it's + * completely *USELESS* because NT 4.x refuses to send the mailslot + * reply back to the correct port (it always uses 138). + * I hate NT when it does these things... JRA. + */ + + int retries = 3; + int retry_time = 2000; + struct timeval tval; + struct packet_struct p; + struct dgram_packet *dgram = &p.packet.dgram; + char *ptr,*p2; + char tmp[4]; + int len; + struct sockaddr_in sock_name; + int sock_len = sizeof(sock_name); + const char *mailslot = "\\MAILSLOT\\NET\\NETLOGON"; + static int name_trn_id = 0; + char buffer[1024]; + char *bufp; + int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True ); + + if(sock == -1) + return False; + + /* Find out the transient UDP port we have been allocated. */ + if(getsockname(sock, (struct sockaddr *)&sock_name, &sock_len)<0) { + DEBUG(0,("lookup_pdc_name: Failed to get local UDP port. Error was %s\n", + strerror(errno))); + close(sock); + return False; + } + + /* + * Create the request data. + */ + + memset(buffer,'\0',sizeof(buffer)); + bufp = buffer; + SSVAL(bufp,0,QUERYFORPDC); + bufp += 2; + fstrcpy(bufp,srcname); + bufp += (strlen(bufp) + 1); + fstrcpy(bufp,"\\MAILSLOT\\NET\\GETDC411"); + bufp += (strlen(bufp) + 1); + bufp = align2(bufp, buffer); + dos_PutUniCode(bufp, srcname, sizeof(buffer) - (bufp - buffer) - 1); + bufp = skip_unicode_string(bufp, 1); + SIVAL(bufp,0,1); + SSVAL(bufp,4,0xFFFF); + SSVAL(bufp,6,0xFFFF); + bufp += 8; + len = PTR_DIFF(bufp,buffer); + + if (!name_trn_id) + name_trn_id = ((unsigned)time(NULL)%(unsigned)0x7FFF) + ((unsigned)getpid()%(unsigned)100); + name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF; + + memset((char *)&p,'\0',sizeof(p)); + + /* DIRECT GROUP or UNIQUE datagram. */ + dgram->header.msg_type = 0x10; + dgram->header.flags.node_type = M_NODE; + dgram->header.flags.first = True; + dgram->header.flags.more = False; + dgram->header.dgm_id = name_trn_id; + dgram->header.source_ip = sock_name.sin_addr; + dgram->header.source_port = ntohs(sock_name.sin_port); + dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */ + dgram->header.packet_offset = 0; + + make_nmb_name(&dgram->source_name,srcname,0,scope); + make_nmb_name(&dgram->dest_name,domain,0x1B,scope); + + ptr = &dgram->data[0]; + + /* Setup the smb part. */ + ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */ + memcpy(tmp,ptr,4); + set_message(ptr,17,17 + len,True); + memcpy(ptr,tmp,4); + + CVAL(ptr,smb_com) = SMBtrans; + SSVAL(ptr,smb_vwv1,len); + SSVAL(ptr,smb_vwv11,len); + SSVAL(ptr,smb_vwv12,70 + strlen(mailslot)); + SSVAL(ptr,smb_vwv13,3); + SSVAL(ptr,smb_vwv14,1); + SSVAL(ptr,smb_vwv15,1); + SSVAL(ptr,smb_vwv16,2); + p2 = smb_buf(ptr); + pstrcpy(p2,mailslot); + p2 = skip_string(p2,1); + + memcpy(p2,buffer,len); + p2 += len; + + dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */ + + p.ip = *pdc_ip; + p.port = DGRAM_PORT; + p.fd = sock; + p.timestamp = time(NULL); + p.packet_type = DGRAM_PACKET; + + GetTimeOfDay(&tval); + + if (!send_packet(&p)) { + DEBUG(0,("lookup_pdc_name: send_packet failed.\n")); + close(sock); + return False; + } + + retries--; + + while (1) { + struct timeval tval2; + struct packet_struct *p_ret; + + GetTimeOfDay(&tval2); + if (TvalDiff(&tval,&tval2) > retry_time) { + if (!retries) + break; + if (!send_packet(&p)) { + DEBUG(0,("lookup_pdc_name: send_packet failed.\n")); + close(sock); + return False; + } + GetTimeOfDay(&tval); + retries--; + } + + if ((p_ret = receive_packet(sock,NMB_PACKET,90))) { + struct nmb_packet *nmb2 = &p_ret->packet.nmb; + struct dgram_packet *dgram2 = &p_ret->packet.dgram; + char *buf; + char *buf2; + + debug_nmb_packet(p_ret); + + if (memcmp(&p.ip, &p_ret->ip, sizeof(p.ip))) { + /* + * Not for us. + */ + DEBUG(0,("lookup_pdc_name: datagram return IP %s doesn't match\n", inet_ntoa(p_ret->ip) )); + free_packet(p_ret); + continue; + } + + buf = &dgram2->data[0]; + buf -= 4; + + if (CVAL(buf,smb_com) != SMBtrans) { + DEBUG(0,("lookup_pdc_name: datagram type %u != SMBtrans(%u)\n", (unsigned int)CVAL(buf,smb_com), + (unsigned int)SMBtrans )); + free_packet(p_ret); + continue; + } + + len = SVAL(buf,smb_vwv11); + buf2 = smb_base(buf) + SVAL(buf,smb_vwv12); + + if (len <= 0) { + DEBUG(0,("lookup_pdc_name: datagram len < 0 (%d)\n", len )); + free_packet(p_ret); + continue; + } + + DEBUG(4,("lookup_pdc_name: datagram reply from %s to %s IP %s for %s of type %d len=%d\n", + nmb_namestr(&dgram2->source_name),nmb_namestr(&dgram2->dest_name), + inet_ntoa(p_ret->ip), smb_buf(buf),CVAL(buf2,0),len)); + + if(SVAL(buf,0) != QUERYFORPDC_R) { + DEBUG(0,("lookup_pdc_name: datagram type (%u) != QUERYFORPDC_R(%u)\n", + (unsigned int)SVAL(buf,0), (unsigned int)QUERYFORPDC_R )); + free_packet(p_ret); + continue; + } + + buf += 2; + /* Note this is safe as it is a bounded strcpy. */ + fstrcpy(ret_name, buf); + ret_name[sizeof(fstring)-1] = '\0'; + close(sock); + free_packet(p_ret); + return True; + } + } + + close(sock); + return False; +#endif /* I_HATE_WINDOWS_REPLY_CODE */ +} + +/******************************************************** + Get the IP address list of the PDC/BDC's of a Domain. +*********************************************************/ + +BOOL get_dc_list(char *group, struct in_addr **ip_list, int *count) +{ + return internal_resolve_name(group, 0x1C, ip_list, count); } diff --git a/source3/libsmb/nmblib.c b/source3/libsmb/nmblib.c index 006cb5f5ee..3b14fd2c6b 100644 --- a/source3/libsmb/nmblib.c +++ b/source3/libsmb/nmblib.c @@ -179,27 +179,34 @@ static int parse_nmb_name(char *inbuf,int offset,int length, struct nmb_name *na unsigned char *ubuf = (unsigned char *)inbuf; int ret = 0; BOOL got_pointer=False; + int loop_count=0; - if (length - offset < 2) return(0); + if (length - offset < 2) + return(0); /* handle initial name pointers */ - if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret)) return(0); + if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret)) + return(0); m = ubuf[offset]; - if (!m) return(0); - if ((m & 0xC0) || offset+m+2 > length) return(0); + if (!m) + return(0); + if ((m & 0xC0) || offset+m+2 > length) + return(0); - bzero((char *)name,sizeof(*name)); + memset((char *)name,'\0',sizeof(*name)); /* the "compressed" part */ - if (!got_pointer) ret += m + 2; + if (!got_pointer) + ret += m + 2; offset++; - while (m) { + while (m > 0) { unsigned char c1,c2; c1 = ubuf[offset++]-'A'; c2 = ubuf[offset++]-'A'; - if ((c1 & 0xF0) || (c2 & 0xF0) || (n > sizeof(name->name)-1)) return(0); + if ((c1 & 0xF0) || (c2 & 0xF0) || (n > sizeof(name->name)-1)) + return(0); name->name[n++] = (c1<<4) | c2; m -= 2; } @@ -213,21 +220,38 @@ static int parse_nmb_name(char *inbuf,int offset,int length, struct nmb_name *na /* remove trailing spaces */ name->name[15] = 0; n = 14; - while (n && name->name[n]==' ') name->name[n--] = 0; + while (n && name->name[n]==' ') + name->name[n--] = 0; } /* now the domain parts (if any) */ n = 0; while (ubuf[offset]) { /* we can have pointers within the domain part as well */ - if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret)) return(0); + if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret)) + return(0); m = ubuf[offset]; - if (!got_pointer) ret += m+1; - if (n) name->scope[n++] = '.'; - if (m+2+offset>length || n+m+1>sizeof(name->scope)) return(0); + /* + * Don't allow null domain parts. + */ + if (!m) + return(0); + if (!got_pointer) + ret += m+1; + if (n) + name->scope[n++] = '.'; + if (m+2+offset>length || n+m+1>sizeof(name->scope)) + return(0); offset++; - while (m--) name->scope[n++] = (char)ubuf[offset++]; + while (m--) + name->scope[n++] = (char)ubuf[offset++]; + + /* + * Watch for malicious loops. + */ + if (loop_count++ == 10) + return 0; } name->scope[n++] = 0; @@ -251,7 +275,7 @@ static int put_nmb_name(char *buf,int offset,struct nmb_name *name) if (strcmp(name->name,"*") == 0) { /* special case for wildcard name */ - bzero(buf1,20); + memset(buf1,'\0',20); buf1[0] = '*'; buf1[15] = name->name_type; } else { @@ -287,7 +311,6 @@ static int put_nmb_name(char *buf,int offset,struct nmb_name *name) return(ret); } - /******************************************************************* useful for debugging messages ******************************************************************/ @@ -297,24 +320,16 @@ char *nmb_namestr(struct nmb_name *n) static fstring ret[4]; char *p = ret[i]; - nmb_safe_namestr(n, p, sizeof(fstring)); + 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); } /******************************************************************* - useful for debugging messages - ******************************************************************/ -void nmb_safe_namestr(struct nmb_name *n, char *str, size_t len) -{ - if (!n->scope[0]) - slprintf(str, len-1, "%s<%02x>",n->name,n->name_type); - else - slprintf(str, len-1, "%s<%02x>.%s",n->name,n->name_type,n->scope); -} - -/******************************************************************* allocate and parse some resource records ******************************************************************/ static BOOL parse_alloc_res_rec(char *inbuf,int *offset,int length, @@ -324,13 +339,14 @@ static BOOL parse_alloc_res_rec(char *inbuf,int *offset,int length, *recs = (struct res_rec *)malloc(sizeof(**recs)*count); if (!*recs) return(False); - bzero(*recs,sizeof(**recs)*count); + memset((char *)*recs,'\0',sizeof(**recs)*count); for (i=0;i<count;i++) { int l = parse_nmb_name(inbuf,*offset,length,&(*recs)[i].rr_name); (*offset) += l; if (!l || (*offset)+10 > length) { free(*recs); + *recs = NULL; return(False); } (*recs)[i].rr_type = RSVAL(inbuf,(*offset)); @@ -341,6 +357,7 @@ static BOOL parse_alloc_res_rec(char *inbuf,int *offset,int length, if ((*recs)[i].rdlength>sizeof((*recs)[i].rdata) || (*offset)+(*recs)[i].rdlength > length) { free(*recs); + *recs = NULL; return(False); } memcpy((*recs)[i].rdata,inbuf+(*offset),(*recs)[i].rdlength); @@ -405,7 +422,7 @@ static BOOL parse_dgram(char *inbuf,int length,struct dgram_packet *dgram) int offset; int flags; - bzero((char *)dgram,sizeof(*dgram)); + memset((char *)dgram,'\0',sizeof(*dgram)); if (length < 14) return(False); @@ -447,7 +464,7 @@ static BOOL parse_nmb(char *inbuf,int length,struct nmb_packet *nmb) { int nm_flags,offset; - bzero((char *)nmb,sizeof(*nmb)); + memset((char *)nmb,'\0',sizeof(*nmb)); if (length < 12) return(False); @@ -563,12 +580,18 @@ static struct packet_struct *copy_nmb_packet(struct packet_struct *packet) free_and_exit: - if(copy_nmb->answers) + if(copy_nmb->answers) { free((char *)copy_nmb->answers); - if(copy_nmb->nsrecs) + copy_nmb->answers = NULL; + } + if(copy_nmb->nsrecs) { free((char *)copy_nmb->nsrecs); - if(copy_nmb->additional) + copy_nmb->nsrecs = NULL; + } + if(copy_nmb->additional) { free((char *)copy_nmb->additional); + copy_nmb->additional = NULL; + } free((char *)pkt_copy); DEBUG(0,("copy_nmb_packet: malloc fail in resource records.\n")); @@ -617,9 +640,18 @@ struct packet_struct *copy_packet(struct packet_struct *packet) ******************************************************************/ static void free_nmb_packet(struct nmb_packet *nmb) { - if (nmb->answers) free(nmb->answers); - if (nmb->nsrecs) free(nmb->nsrecs); - if (nmb->additional) free(nmb->additional); + if (nmb->answers) { + free(nmb->answers); + nmb->answers = NULL; + } + if (nmb->nsrecs) { + free(nmb->nsrecs); + nmb->nsrecs = NULL; + } + if (nmb->additional) { + free(nmb->additional); + nmb->additional = NULL; + } } /******************************************************************* @@ -641,6 +673,7 @@ void free_packet(struct packet_struct *packet) free_nmb_packet(&packet->packet.nmb); else if (packet->packet_type == DGRAM_PACKET) free_dgram_packet(&packet->packet.dgram); + ZERO_STRUCTPN(packet); free(packet); } @@ -651,47 +684,15 @@ void free_packet(struct packet_struct *packet) struct packet_struct *read_packet(int fd,enum packet_type packet_type) { extern struct in_addr lastip; - struct nmb_state con; extern int lastport; struct packet_struct *packet; char buf[MAX_DGRAM_SIZE]; int length; BOOL ok=False; - if (packet_type == NMB_SOCK_PACKET || packet_type == DGRAM_SOCK_PACKET) - { - uint16 trn_id = 0; - if (!read_nmb_sock(fd, &con)) - { - return False; - } - if (write(fd, &trn_id, sizeof(trn_id)) != sizeof(trn_id)) - { - return False; - } - } - - length = read_udp_socket(fd,buf,sizeof(buf)); - - dump_data(100, buf, length); - - if (packet_type == NMB_SOCK_PACKET || packet_type == DGRAM_SOCK_PACKET) - { - uint16 trn_id = 0; - if (write(fd, &trn_id, sizeof(trn_id)) != sizeof(trn_id)) - { - return False; - } - } - + length = read_udp_socket(fd,buf,sizeof(buf)); if (length < MIN_DGRAM_SIZE) return(NULL); - if (packet_type == NMB_SOCK_PACKET || packet_type == DGRAM_SOCK_PACKET) - { - lastip = con.ip; - lastport = con.port; - } - packet = (struct packet_struct *)malloc(sizeof(*packet)); if (!packet) return(NULL); @@ -706,19 +707,17 @@ struct packet_struct *read_packet(int fd,enum packet_type packet_type) switch (packet_type) { case NMB_PACKET: - case NMB_SOCK_PACKET: ok = parse_nmb(buf,length,&packet->packet.nmb); break; case DGRAM_PACKET: - case DGRAM_SOCK_PACKET: ok = parse_dgram(buf,length,&packet->packet.dgram); break; } if (!ok) { DEBUG(10,("read_packet: discarding packet id = %d\n", packet->packet.nmb.header.name_trn_id)); - free(packet); + free_packet(packet); return(NULL); } @@ -740,7 +739,7 @@ static BOOL send_udp(int fd,char *buf,int len,struct in_addr ip,int port) struct sockaddr_in sock_out; /* set the address and port */ - bzero((char *)&sock_out,sizeof(sock_out)); + memset((char *)&sock_out,'\0',sizeof(sock_out)); putip((char *)&sock_out.sin_addr,(char *)&ip); sock_out.sin_port = htons( port ); sock_out.sin_family = AF_INET; @@ -776,7 +775,7 @@ static int build_dgram(char *buf,struct packet_struct *p) /* put in the header */ ubuf[0] = dgram->header.msg_type; - ubuf[1] = (((unsigned int)dgram->header.flags.node_type)<<2); + ubuf[1] = (((int)dgram->header.flags.node_type)<<2); if (dgram->header.flags.more) ubuf[1] |= 1; if (dgram->header.flags.first) ubuf[1] |= 2; RSSVAL(ubuf,2,dgram->header.dgm_id); @@ -909,82 +908,23 @@ BOOL send_packet(struct packet_struct *p) char buf[1024]; int len=0; - DEBUG(100,("send_packet: %d %d\n", p->fd, p->packet_type)); - - bzero(buf,sizeof(buf)); + memset(buf,'\0',sizeof(buf)); switch (p->packet_type) { case NMB_PACKET: - case NMB_SOCK_PACKET: len = build_nmb(buf,p); debug_nmb_packet(p); break; case DGRAM_PACKET: - case DGRAM_SOCK_PACKET: len = build_dgram(buf,p); break; } if (!len) return(False); - switch (p->packet_type) - { - case DGRAM_PACKET: - case NMB_PACKET: - return(send_udp(p->fd,buf,len,p->ip,p->port)); - break; - - case NMB_SOCK_PACKET: - case DGRAM_SOCK_PACKET: - { - fstring qbuf; - struct nmb_state nmb; - int qlen; - uint16 trn_id; - char *q = qbuf + 4; - - nmb.ip = p->ip; - nmb.port = p->port; - - SSVAL(q, 0, 0); - q += 2; - SSVAL(q, 0, 0); - q += 2; - memcpy(q, &nmb, sizeof(nmb)); - q += sizeof(nmb); - - qlen = PTR_DIFF(q, qbuf); - SIVAL(qbuf, 0, qlen); - - dump_data(100, qbuf, qlen); - - if (write(p->fd,qbuf,qlen) != qlen) - { - DEBUG(0,("send_packet: write hdr failed\n")); - return False; - } - if (read(p->fd, &trn_id, sizeof(trn_id)) != sizeof(trn_id)) - { - DEBUG(0,("send_packet: 1st ack failed\n")); - return False; - } - if (write(p->fd,buf,len) != len) - { - DEBUG(0,("send_packet: write packet failed\n")); - return False; - } - if (read(p->fd, &trn_id, sizeof(trn_id)) != sizeof(trn_id)) - { - DEBUG(0,("send_packet: 2nd ack failed\n")); - return False; - } - return True; - } - } - - return False; + return(send_udp(p->fd,buf,len,p->ip,p->port)); } /**************************************************************************** @@ -1001,8 +941,7 @@ struct packet_struct *receive_packet(int fd,enum packet_type type,int t) timeout.tv_sec = t/1000; timeout.tv_usec = 1000*(t%1000); - DEBUG(100,("receive_packet: %d %d\n", fd, type)); - sys_select(fd+1,&fds,NULL, &timeout); + sys_select(fd+1,&fds,&timeout); if (FD_ISSET(fd,&fds)) return(read_packet(fd,type)); @@ -1055,76 +994,3 @@ void sort_query_replies(char *data, int n, struct in_addr ip) qsort(data, n, 6, QSORT_CAST name_query_comp); } - -BOOL read_nmb_sock(int c, struct nmb_state *con) -{ - fstring buf; - char *p = buf; - int rl; - uint32 len; - uint16 version; - uint16 command; - - ZERO_STRUCTP(con); - - rl = read(c, &buf, sizeof(len)); - - if (rl < 0) - { - DEBUG(0,("read_nmb_sock: error\n")); - return False; - } - if (rl != sizeof(len)) - { - DEBUG(0,("Unable to read length\n")); - dump_data(0, buf, sizeof(len)); - return False; - } - - len = IVAL(buf, 0); - - if (len > sizeof(buf)) - { - DEBUG(0,("length %d too long\n", len)); - return False; - } - - rl = read(c, buf, len); - - if (rl < 0) - { - DEBUG(0,("Unable to read from connection\n")); - return False; - } - -#ifdef DEBUG_PASSWORD - dump_data(100, buf, rl); -#endif - version = SVAL(p, 0); - p += 2; - command = SVAL(p, 0); - p += 2; - - memcpy(con, p, sizeof(*con)); - p += sizeof(*con); - - DEBUG(10,("read_nmb_sock: ip %s port: %d\n", - inet_ntoa(con->ip), con->port)); - - if (PTR_DIFF(p, buf) != rl) - { - DEBUG(0,("Buffer size %d %d!\n", - PTR_DIFF(p, buf), rl)); - return False; - } - - return True; -} - -int get_nmb_sock(void) -{ - fstring path; - slprintf(path, sizeof(path)-1, "/tmp/.nmb/agent"); - - return open_pipe_sock(path); -} diff --git a/source3/libsmb/nterr.c b/source3/libsmb/nterr.c index 9cf1fb8214..d2f9335000 100644 --- a/source3/libsmb/nterr.c +++ b/source3/libsmb/nterr.c @@ -514,18 +514,18 @@ nt_err_code_struct nt_errs[] = { "NT_STATUS_TOO_MANY_LINKS", NT_STATUS_TOO_MANY_LINKS }, { "NT_STATUS_QUOTA_LIST_INCONSISTENT", NT_STATUS_QUOTA_LIST_INCONSISTENT }, { "NT_STATUS_FILE_IS_OFFLINE", NT_STATUS_FILE_IS_OFFLINE }, - { "NT_STATUS_NO_SUCH_JOB", NT_STATUS_NO_SUCH_JOB }, { NULL, 0 } }; /***************************************************************************** returns an NT error message. not amazingly helpful, but better than a number. *****************************************************************************/ -void get_safe_nt_error_msg(uint32 nt_code, char *msg, size_t len) +char *get_nt_error_msg(uint32 nt_code) { + static pstring msg; int idx = 0; - snprintf(msg, len, "NT code %08x", nt_code); + pstrcpy(msg, "Unknown NT error"); nt_code &= 0xFFFF; @@ -533,19 +533,11 @@ void get_safe_nt_error_msg(uint32 nt_code, char *msg, size_t len) { if (nt_errs[idx].nt_errcode == nt_code) { - safe_strcpy(msg, nt_errs[idx].nt_errstr, len); - return; + pstrcpy(msg, nt_errs[idx].nt_errstr); + return msg; } idx++; } -} - -/***************************************************************************** - returns an NT error message. not amazingly helpful, but better than a number. - *****************************************************************************/ -char *get_nt_error_msg(uint32 nt_code) -{ - static pstring msg; - get_safe_nt_error_msg(nt_code, msg, sizeof(msg)); return msg; } + diff --git a/source3/libsmb/passchange.c b/source3/libsmb/passchange.c index b5552d4cea..b0b1188f32 100644 --- a/source3/libsmb/passchange.c +++ b/source3/libsmb/passchange.c @@ -36,6 +36,8 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name, struct cli_state cli; struct in_addr ip; + *err_str = '\0'; + if(!resolve_name( remote_machine, &ip, 0x20)) { slprintf(err_str, err_str_len-1, "unable to find an IP address for machine %s.\n", remote_machine ); @@ -75,7 +77,7 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name, * Thanks to <Nicholas.S.Jenkins@cdc.com> for this fix. */ - if (!cli_session_setup(&cli, global_myname, "", "", 0, "", 0, "")) { + if (!cli_session_setup(&cli, "", "", 0, "", 0, "")) { slprintf(err_str, err_str_len-1, "machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(&cli) ); cli_shutdown(&cli); diff --git a/source3/libsmb/pwd_cache.c b/source3/libsmb/pwd_cache.c index 29cf77dd55..94b60d3ff0 100644 --- a/source3/libsmb/pwd_cache.c +++ b/source3/libsmb/pwd_cache.c @@ -29,13 +29,11 @@ initialises a password structure ****************************************************************************/ void pwd_init(struct pwd_info *pwd) { - ZERO_STRUCT(pwd->password ); - ZERO_STRUCT(pwd->smb_lm_pwd); - ZERO_STRUCT(pwd->smb_nt_pwd); - ZERO_STRUCT(pwd->smb_lm_owf); - ZERO_STRUCT(pwd->smb_nt_owf); - ZERO_STRUCT(pwd->sess_key ); - pwd->nt_owf_len = 0; + memset((char *)pwd->password , '\0', sizeof(pwd->password )); + memset((char *)pwd->smb_lm_pwd, '\0', sizeof(pwd->smb_lm_pwd)); + memset((char *)pwd->smb_nt_pwd, '\0', sizeof(pwd->smb_nt_pwd)); + memset((char *)pwd->smb_lm_owf, '\0', sizeof(pwd->smb_lm_owf)); + memset((char *)pwd->smb_nt_owf, '\0', sizeof(pwd->smb_nt_owf)); pwd->null_pwd = True; /* safest option... */ pwd->cleartext = False; @@ -43,24 +41,16 @@ void pwd_init(struct pwd_info *pwd) } /**************************************************************************** -returns NULL password flag -****************************************************************************/ -BOOL pwd_is_nullpwd(const struct pwd_info *pwd) -{ - return pwd->null_pwd; -} - -/**************************************************************************** de-obfuscates a password ****************************************************************************/ -static void pwd_deobfuscate(const struct pwd_info *pwd) +static void pwd_deobfuscate(struct pwd_info *pwd) { } /**************************************************************************** obfuscates a password ****************************************************************************/ -static void pwd_obfuscate(const struct pwd_info *pwd) +static void pwd_obfuscate(struct pwd_info *pwd) { } @@ -72,59 +62,6 @@ void pwd_obfuscate_key(struct pwd_info *pwd, uint32 int_key, char *str_key) } /**************************************************************************** -compares two passwords. hmm, not as trivial as expected. hmm. -****************************************************************************/ -BOOL pwd_compare(struct pwd_info *pwd1, struct pwd_info *pwd2) -{ - pwd_deobfuscate(pwd1); - pwd_deobfuscate(pwd2); - if (pwd1->cleartext && pwd2->cleartext) - { - if (strequal(pwd1->password, pwd2->password)) - { - pwd_obfuscate(pwd1); - pwd_obfuscate(pwd2); - return True; - } - } - if (pwd1->null_pwd && pwd2->null_pwd) - { - pwd_obfuscate(pwd1); - pwd_obfuscate(pwd2); - return True; - } - - if (!pwd1->null_pwd && !pwd2->null_pwd && - !pwd1->cleartext && !pwd2->cleartext) - { -#ifdef DEBUG_PASSWORD - DEBUG(100,("pwd compare: nt#\n")); - dump_data(100, pwd1->smb_nt_pwd, 16); - dump_data(100, pwd2->smb_nt_pwd, 16); -#endif - if (memcmp(pwd1->smb_nt_pwd, pwd2->smb_nt_pwd, 16) == 0) - { - pwd_obfuscate(pwd1); - pwd_obfuscate(pwd2); - return True; - } -#ifdef DEBUG_PASSWORD - DEBUG(100,("pwd compare: lm#\n")); - dump_data(100, pwd1->smb_lm_pwd, 16); - dump_data(100, pwd2->smb_lm_pwd, 16); -#endif - if (memcmp(pwd1->smb_lm_pwd, pwd2->smb_lm_pwd, 16) == 0) - { - pwd_obfuscate(pwd1); - pwd_obfuscate(pwd2); - return True; - } - } - pwd_obfuscate(pwd1); - pwd_obfuscate(pwd2); - return False; -} -/**************************************************************************** reads a password ****************************************************************************/ void pwd_read(struct pwd_info *pwd, char *passwd_report, BOOL do_encrypt) @@ -169,6 +106,7 @@ void pwd_set_cleartext(struct pwd_info *pwd, char *clr) { pwd_init(pwd); fstrcpy(pwd->password, clr); + unix_to_dos(pwd->password,True); pwd->cleartext = True; pwd->null_pwd = False; pwd->crypted = False; @@ -185,6 +123,7 @@ void pwd_get_cleartext(struct pwd_info *pwd, char *clr) if (pwd->cleartext) { fstrcpy(clr, pwd->password); + dos_to_unix(clr, True); } else { @@ -206,7 +145,7 @@ void pwd_set_lm_nt_16(struct pwd_info *pwd, uchar lm_pwd[16], uchar nt_pwd[16]) } else { - bzero(pwd->smb_lm_pwd, 16); + memset((char *)pwd->smb_lm_pwd, '\0', 16); } if (nt_pwd) @@ -215,7 +154,7 @@ void pwd_set_lm_nt_16(struct pwd_info *pwd, uchar lm_pwd[16], uchar nt_pwd[16]) } else { - bzero(pwd->smb_nt_pwd, 16); + memset((char *)pwd->smb_nt_pwd, '\0', 16); } pwd->null_pwd = False; @@ -228,7 +167,7 @@ void pwd_set_lm_nt_16(struct pwd_info *pwd, uchar lm_pwd[16], uchar nt_pwd[16]) /**************************************************************************** gets lm and nt hashed passwords ****************************************************************************/ -void pwd_get_lm_nt_16(const struct pwd_info *pwd, uchar lm_pwd[16], uchar nt_pwd[16]) +void pwd_get_lm_nt_16(struct pwd_info *pwd, uchar lm_pwd[16], uchar nt_pwd[16]) { pwd_deobfuscate(pwd); if (lm_pwd != NULL) @@ -247,9 +186,14 @@ void pwd_get_lm_nt_16(const struct pwd_info *pwd, uchar lm_pwd[16], uchar nt_pwd ****************************************************************************/ void pwd_make_lm_nt_16(struct pwd_info *pwd, char *clr) { + pstring dos_passwd; + pwd_init(pwd); - nt_lm_owf_gen(clr, pwd->smb_nt_pwd, pwd->smb_lm_pwd); + pstrcpy(dos_passwd, clr); + unix_to_dos(dos_passwd, True); + + nt_lm_owf_gen(dos_passwd, pwd->smb_nt_pwd, pwd->smb_lm_pwd); pwd->null_pwd = False; pwd->cleartext = False; pwd->crypted = False; @@ -260,109 +204,31 @@ void pwd_make_lm_nt_16(struct pwd_info *pwd, char *clr) /**************************************************************************** makes lm and nt OWF crypts ****************************************************************************/ -void pwd_make_lm_nt_owf2(struct pwd_info *pwd, const uchar srv_key[8], - const char *user, const char *server, const char *domain) +void pwd_make_lm_nt_owf(struct pwd_info *pwd, uchar cryptkey[8]) { - uchar kr[16]; - - DEBUG(10,("pwd_make_lm_nt_owf2: user %s, srv %s, dom %s\n", - user, server, domain)); - pwd_deobfuscate(pwd); - SMBgenclientchals(pwd->lm_cli_chal, - pwd->nt_cli_chal, - &pwd->nt_cli_chal_len, - server, domain); - - ntv2_owf_gen(pwd->smb_nt_pwd, user, domain, kr); - - /* lm # */ - SMBOWFencrypt_ntv2(kr, - srv_key, 8, - pwd->lm_cli_chal, 8, - pwd->smb_lm_owf); - memcpy(&pwd->smb_lm_owf[16], pwd->lm_cli_chal, 8); - - /* nt # */ - SMBOWFencrypt_ntv2(kr, - srv_key, 8, - pwd->nt_cli_chal, pwd->nt_cli_chal_len, - pwd->smb_nt_owf); - memcpy(&pwd->smb_nt_owf[16], pwd->nt_cli_chal, pwd->nt_cli_chal_len); - pwd->nt_owf_len = pwd->nt_cli_chal_len + 16; - - SMBsesskeygen_ntv2(kr, pwd->smb_nt_owf, pwd->sess_key); - -#if DEBUG_PASSWORD -#endif - #ifdef DEBUG_PASSWORD - DEBUG(100,("server cryptkey: ")); - dump_data(100, srv_key, 8); - - DEBUG(100,("client lmv2 cryptkey: ")); - dump_data(100, pwd->lm_cli_chal, 8); - - DEBUG(100,("client ntv2 cryptkey: ")); - dump_data(100, pwd->nt_cli_chal, pwd->nt_cli_chal_len); - - DEBUG(100,("ntv2_owf_passwd: ")); - dump_data(100, pwd->smb_nt_owf, pwd->nt_owf_len); - DEBUG(100,("nt_sess_pwd: ")); - dump_data(100, pwd->smb_nt_pwd, sizeof(pwd->smb_nt_pwd)); - - DEBUG(100,("lmv2_owf_passwd: ")); - dump_data(100, pwd->smb_lm_owf, sizeof(pwd->smb_lm_owf)); - DEBUG(100,("lm_sess_pwd: ")); - dump_data(100, pwd->smb_lm_pwd, sizeof(pwd->smb_lm_pwd)); - - DEBUG(100,("session key:\n")); - dump_data(100, pwd->sess_key, sizeof(pwd->sess_key)); + DEBUG(100,("client cryptkey: ")); + dump_data(100, (char *)cryptkey, 8); #endif - pwd->crypted = True; - pwd_obfuscate(pwd); -} + SMBOWFencrypt(pwd->smb_nt_pwd, cryptkey, pwd->smb_nt_owf); -/**************************************************************************** - makes lm and nt OWF crypts - ****************************************************************************/ -void pwd_make_lm_nt_owf(struct pwd_info *pwd, uchar cryptkey[8]) -{ - if (pwd->null_pwd) - { #ifdef DEBUG_PASSWORD - DEBUG(100,("pwd_make_lm_nt_owf: NULL password\n")); + DEBUG(100,("nt_owf_passwd: ")); + dump_data(100, (char *)pwd->smb_nt_owf, sizeof(pwd->smb_nt_owf)); + DEBUG(100,("nt_sess_pwd: ")); + dump_data(100, (char *)pwd->smb_nt_pwd, sizeof(pwd->smb_nt_pwd)); #endif - pwd->nt_owf_len = 0; - return; - } - pwd_deobfuscate(pwd); - /* generate 24-byte hashes */ SMBOWFencrypt(pwd->smb_lm_pwd, cryptkey, pwd->smb_lm_owf); - SMBOWFencrypt(pwd->smb_nt_pwd, cryptkey, pwd->smb_nt_owf); - pwd->nt_owf_len = 24; - - SMBsesskeygen_ntv1(pwd->smb_nt_pwd, pwd->smb_nt_owf, pwd->sess_key); #ifdef DEBUG_PASSWORD - DEBUG(100,("client cryptkey: ")); - dump_data(100, cryptkey, 8); - - DEBUG(100,("nt_owf_passwd: ")); - dump_data(100, pwd->smb_nt_owf, pwd->nt_owf_len); - DEBUG(100,("nt_sess_pwd: ")); - dump_data(100, pwd->smb_nt_pwd, sizeof(pwd->smb_nt_pwd)); - DEBUG(100,("lm_owf_passwd: ")); - dump_data(100, pwd->smb_lm_owf, sizeof(pwd->smb_lm_owf)); + dump_data(100, (char *)pwd->smb_lm_owf, sizeof(pwd->smb_lm_owf)); DEBUG(100,("lm_sess_pwd: ")); - dump_data(100, pwd->smb_lm_pwd, sizeof(pwd->smb_lm_pwd)); - - DEBUG(100,("session key:\n")); - dump_data(100, pwd->sess_key, sizeof(pwd->sess_key)); + dump_data(100, (char *)pwd->smb_lm_pwd, sizeof(pwd->smb_lm_pwd)); #endif pwd->crypted = True; @@ -373,22 +239,8 @@ void pwd_make_lm_nt_owf(struct pwd_info *pwd, uchar cryptkey[8]) /**************************************************************************** gets lm and nt crypts ****************************************************************************/ -void pwd_get_lm_nt_owf(struct pwd_info *pwd, uchar lm_owf[24], - uchar *nt_owf, size_t *nt_owf_len, - uchar *sess_key) +void pwd_get_lm_nt_owf(struct pwd_info *pwd, uchar lm_owf[24], uchar nt_owf[24]) { - if (pwd->null_pwd) - { -#ifdef DEBUG_PASSWORD - DEBUG(100,("pwd_get_lm_nt_owf: NULL password\n")); -#endif - if (nt_owf_len != NULL) - { - *nt_owf_len = 0; - } - return; - } - pwd_deobfuscate(pwd); if (lm_owf != NULL) { @@ -396,16 +248,7 @@ void pwd_get_lm_nt_owf(struct pwd_info *pwd, uchar lm_owf[24], } if (nt_owf != NULL) { - memcpy(nt_owf, pwd->smb_nt_owf, pwd->nt_owf_len); - } - if (sess_key != NULL) - { - memcpy(sess_key, pwd->sess_key, 16); - } - if (nt_owf_len != NULL) - { - *nt_owf_len = pwd->nt_owf_len; + memcpy(nt_owf, pwd->smb_nt_owf, 24); } pwd_obfuscate(pwd); } - diff --git a/source3/libsmb/smbdes.c b/source3/libsmb/smbdes.c index e60b93d6a2..d0e1c6e85f 100644 --- a/source3/libsmb/smbdes.c +++ b/source3/libsmb/smbdes.c @@ -259,7 +259,7 @@ static void dohash(char *out, char *in, char *key, int forw) permute(out, rl, perm6, 64); } -static void str_to_key(const uchar *str, uchar *key) +static void str_to_key(unsigned char *str,unsigned char *key) { int i; @@ -277,7 +277,7 @@ static void str_to_key(const uchar *str, uchar *key) } -void smbhash(unsigned char *out, const uchar *in, const uchar *key, int forw) +static void smbhash(unsigned char *out, unsigned char *in, unsigned char *key, int forw) { int i; char outb[64]; @@ -365,10 +365,6 @@ void SamOEMhash( unsigned char *data, unsigned char *key, int val) unsigned char index_j = 0; unsigned char j = 0; int ind; - int len = 0; - if (val == 1) len = 516; - if (val == 0) len = 16; - if (val == 2) len = 68; for (ind = 0; ind < 256; ind++) { @@ -385,7 +381,7 @@ void SamOEMhash( unsigned char *data, unsigned char *key, int val) s_box[ind] = s_box[j]; s_box[j] = tc; } - for( ind = 0; ind < len; ind++) + for( ind = 0; ind < (val ? 516 : 16); ind++) { unsigned char tc; unsigned char t; @@ -401,16 +397,3 @@ void SamOEMhash( unsigned char *data, unsigned char *key, int val) data[ind] = data[ind] ^ s_box[t]; } } - -void sam_pwd_hash(uint32 rid, const uchar *in, uchar *out, int forw) -{ - unsigned char s[14]; - - s[0] = s[4] = s[8] = s[12] = (unsigned char)(rid & 0xFF); - s[1] = s[5] = s[9] = s[13] = (unsigned char)((rid >> 8) & 0xFF); - s[2] = s[6] = s[10] = (unsigned char)((rid >> 16) & 0xFF); - s[3] = s[7] = s[11] = (unsigned char)((rid >> 24) & 0xFF); - - smbhash(out, in, s, forw); - smbhash(out+8, in+8, s+7, forw); -} diff --git a/source3/libsmb/smbencrypt.c b/source3/libsmb/smbencrypt.c index 34e6f43975..b927e193dd 100644 --- a/source3/libsmb/smbencrypt.c +++ b/source3/libsmb/smbencrypt.c @@ -24,39 +24,30 @@ extern int DEBUGLEVEL; +#include "byteorder.h" + /* This implements the X/Open SMB password encryption It takes a password, a 8 byte "crypt key" and puts 24 bytes of encrypted password into p24 */ -void SMBencrypt(uchar *pwrd, uchar *c8, uchar *p24) +void SMBencrypt(uchar *passwd, uchar *c8, uchar *p24) { - uchar p21[21]; + uchar p14[15], p21[21]; - lm_owf_gen(pwrd, p21); - SMBOWFencrypt(p21, c8, p24); + memset(p21,'\0',21); + memset(p14,'\0',14); + StrnCpy((char *)p14,(char *)passwd,14); -#ifdef DEBUG_PASSWORD - DEBUG(100,("SMBencrypt: lm#, challenge, response\n")); - dump_data(100, p21, 16); - dump_data(100, c8, 8); - dump_data(100, p24, 24); -#endif -} + strupper((char *)p14); + E_P16(p14, p21); -void SMBNTencrypt(uchar *pwrd, uchar *c8, uchar *p24) -{ - uchar p21[21]; - - memset(p21,'\0',21); - - nt_owf_gen(pwrd, p21); SMBOWFencrypt(p21, c8, p24); #ifdef DEBUG_PASSWORD - DEBUG(100,("SMBNTencrypt: nt#, challenge, response\n")); - dump_data(100, p21, 16); - dump_data(100, c8, 8); - dump_data(100, p24, 24); + DEBUG(100,("SMBencrypt: lm#, challenge, response\n")); + dump_data(100, (char *)p21, 16); + dump_data(100, (char *)c8, 8); + dump_data(100, (char *)p24, 24); #endif } @@ -76,23 +67,7 @@ static int _my_wcslen(int16 *str) * format. */ -static int _my_mbstowcsupper(int16 *dst, const uchar *src, int len) -{ - int i; - int16 val; - - for(i = 0; i < len; i++) { - val = toupper(*src); - SSVAL(dst,0,val); - dst++; - src++; - if(val == 0) - break; - } - return i; -} - -static int _my_mbstowcs(int16 *dst, const uchar *src, int len) +static int _my_mbstowcs(int16 *dst, uchar *src, int len) { int i; int16 val; @@ -112,17 +87,17 @@ static int _my_mbstowcs(int16 *dst, const uchar *src, int len) * Creates the MD4 Hash of the users password in NT UNICODE. */ -void E_md4hash(uchar *pwrd, uchar *p16) +void E_md4hash(uchar *passwd, uchar *p16) { int len; int16 wpwd[129]; /* Password cannot be longer than 128 characters */ - len = strlen((char *)pwrd); + len = strlen((char *)passwd); if(len > 128) len = 128; /* Password must be converted to NT unicode */ - _my_mbstowcs(wpwd, pwrd, len); + _my_mbstowcs(wpwd, passwd, len); wpwd[len] = 0; /* Ensure string is null terminated */ /* Calculate length in bytes */ len = _my_wcslen(wpwd) * sizeof(int16); @@ -130,289 +105,98 @@ void E_md4hash(uchar *pwrd, uchar *p16) mdfour(p16, (unsigned char *)wpwd, len); } -/* Does the LM owf of a user's password */ -void lm_owf_genW(const UNISTR2 *pwd, uchar p16[16]) +/* Does both the NT and LM owfs of a user's password */ +void nt_lm_owf_gen(char *pwd, uchar nt_p16[16], uchar p16[16]) { - char pwrd[15]; - - memset(pwrd,'\0',15); - if (pwd != NULL) - { - unistr2_to_ascii( pwrd, pwd, sizeof(pwrd)-1); - } + char passwd[130]; - /* Mangle the passwords into Lanman format */ - pwrd[14] = '\0'; - strupper(pwrd); - - /* Calculate the SMB (lanman) hash functions of the password */ + memset(passwd,'\0',130); + safe_strcpy( passwd, pwd, sizeof(passwd)-1); - memset(p16, '\0', 16); - E_P16((uchar *) pwrd, (uchar *)p16); + /* Calculate the MD4 hash (NT compatible) of the password */ + memset(nt_p16, '\0', 16); + E_md4hash((uchar *)passwd, nt_p16); #ifdef DEBUG_PASSWORD - DEBUG(100,("nt_lm_owf_gen: pwd, lm#\n")); - dump_data(120, pwrd, strlen(pwrd)); - dump_data(100, p16, 16); + DEBUG(100,("nt_lm_owf_gen: pwd, nt#\n")); + dump_data(120, passwd, strlen(passwd)); + dump_data(100, (char *)nt_p16, 16); #endif - /* clear out local copy of user's password (just being paranoid). */ - bzero(pwrd, sizeof(pwrd)); -} - -/* Does the LM owf of a user's password */ -void lm_owf_gen(const char *pwd, uchar p16[16]) -{ - char pwrd[15]; - - memset(pwrd,'\0',15); - if (pwd != NULL) - { - safe_strcpy( pwrd, pwd, sizeof(pwrd)-1); - } /* Mangle the passwords into Lanman format */ - pwrd[14] = '\0'; - strupper(pwrd); + passwd[14] = '\0'; + strupper(passwd); /* Calculate the SMB (lanman) hash functions of the password */ memset(p16, '\0', 16); - E_P16((uchar *) pwrd, (uchar *)p16); + E_P16((uchar *) passwd, (uchar *)p16); #ifdef DEBUG_PASSWORD DEBUG(100,("nt_lm_owf_gen: pwd, lm#\n")); - dump_data(120, pwrd, strlen(pwrd)); - dump_data(100, p16, 16); -#endif - /* clear out local copy of user's password (just being paranoid). */ - bzero(pwrd, sizeof(pwrd)); -} - -/* Does both the NT and LM owfs of a user's password */ -void nt_owf_genW(const UNISTR2 *pwd, uchar nt_p16[16]) -{ - UNISTR2 pwrd; - - memset(&pwrd,'\0',sizeof(pwrd)); - if (pwd != NULL) - { - copy_unistr2(&pwrd, pwd); - } - - /* Calculate the MD4 hash (NT compatible) of the password */ - memset(nt_p16, '\0', 16); - mdfour(nt_p16, (unsigned char *)pwrd.buffer, pwrd.uni_str_len * 2); - -#ifdef DEBUG_PASSWORD - DEBUG(100,("nt_owf_gen: pwd, nt#\n")); - dump_data(120, (const char*)pwrd.buffer, pwrd.uni_str_len * 2); - dump_data(100, nt_p16, 16); -#endif - /* clear out local copy of user's password (just being paranoid). */ - memset(&pwrd, 0, sizeof(pwrd)); -} - -/* Does both the NT and LM owfs of a user's password */ -void nt_owf_gen(const char *pwd, uchar nt_p16[16]) -{ - char pwrd[130]; - - memset(pwrd,'\0',130); - if (pwd != NULL) - { - safe_strcpy( pwrd, pwd, sizeof(pwrd)-1); - } - - /* Calculate the MD4 hash (NT compatible) of the password */ - memset(nt_p16, '\0', 16); - E_md4hash((uchar *)pwrd, nt_p16); - -#ifdef DEBUG_PASSWORD - DEBUG(100,("nt_owf_gen: pwd, nt#\n")); - dump_data(120, pwrd, strlen(pwrd)); - dump_data(100, nt_p16, 16); + dump_data(120, passwd, strlen(passwd)); + dump_data(100, (char *)p16, 16); #endif /* clear out local copy of user's password (just being paranoid). */ - bzero(pwrd, sizeof(pwrd)); -} - -/* Does both the NT and LM owfs of a user's UNICODE password */ -void nt_lm_owf_genW(const UNISTR2 *pwd, uchar nt_p16[16], uchar lm_p16[16]) -{ - nt_owf_genW(pwd, nt_p16); - lm_owf_genW(pwd, lm_p16); -} - -/* Does both the NT and LM owfs of a user's password */ -void nt_lm_owf_gen(const char *pwd, uchar nt_p16[16], uchar lm_p16[16]) -{ - nt_owf_gen(pwd, nt_p16); - lm_owf_gen(pwd, lm_p16); + memset(passwd, '\0', sizeof(passwd)); } /* Does the des encryption from the NT or LM MD4 hash. */ -void SMBOWFencrypt(uchar pwrd[16], uchar *c8, uchar p24[24]) +void SMBOWFencrypt(uchar passwd[16], uchar *c8, uchar p24[24]) { uchar p21[21]; memset(p21,'\0',21); - memcpy(p21, pwrd, 16); + memcpy(p21, passwd, 16); E_P24(p21, c8, p24); } -void SMBOWFencrypt_ntv2(const uchar kr[16], - const uchar *srv_chal, int srv_chal_len, - const uchar *cli_chal, int cli_chal_len, - char resp_buf[16]) -{ - HMACMD5Context ctx; - - hmac_md5_init_limK_to_64(kr, 16, &ctx); - hmac_md5_update(srv_chal, srv_chal_len, &ctx); - hmac_md5_update(cli_chal, cli_chal_len, &ctx); - hmac_md5_final(resp_buf, &ctx); - -#ifdef DEBUG_PASSWORD - DEBUG(100,("SMBOWFencrypt_ntv2: srv_chal, cli_chal, resp_buf\n")); - dump_data(100, srv_chal, srv_chal_len); - dump_data(100, cli_chal, cli_chal_len); - dump_data(100, resp_buf, 16); -#endif -} - -void SMBsesskeygen_ntv2(const uchar kr[16], - const uchar *nt_resp, - char sess_key[16]) -{ - HMACMD5Context ctx; - - hmac_md5_init_limK_to_64(kr, 16, &ctx); - hmac_md5_update(nt_resp, 16, &ctx); - hmac_md5_final(sess_key, &ctx); - -#ifdef DEBUG_PASSWORD - DEBUG(100,("SMBsesskeygen_ntv2:\n")); - dump_data(100, sess_key, 16); -#endif -} - -void SMBsesskeygen_ntv1(const uchar kr[16], - const uchar *nt_resp, - char sess_key[16]) +/* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */ +void NTLMSSPOWFencrypt(uchar passwd[8], uchar *ntlmchalresp, uchar p24[24]) { - mdfour(sess_key, kr, 16); + uchar p21[21]; + + memset(p21,'\0',21); + memcpy(p21, passwd, 8); + memset(p21 + 8, 0xbd, 8); + E_P24(p21, ntlmchalresp, p24); #ifdef DEBUG_PASSWORD - DEBUG(100,("SMBsesskeygen_ntv2:\n")); - dump_data(100, sess_key, 16); + DEBUG(100,("NTLMSSPOWFencrypt: p21, c8, p24\n")); + dump_data(100, (char *)p21, 21); + dump_data(100, (char *)ntlmchalresp, 8); + dump_data(100, (char *)p24, 24); #endif } -void SMBgenclientchals(char *lm_cli_chal, - char *nt_cli_chal, int *nt_cli_chal_len, - const char *srv, const char *dom) -{ - NTTIME nt_time; - int srv_len = strlen(srv); - int dom_len = strlen(dom); - fstring server; - fstring domain; - fstrcpy(server, srv); - fstrcpy(domain, dom); - strupper(server); - strupper(domain); - - generate_random_buffer(lm_cli_chal, 8, False); - unix_to_nt_time(&nt_time, time(NULL)); - - CVAL(nt_cli_chal,0) = 0x1; - CVAL(nt_cli_chal,1) = 0x1; - SSVAL(nt_cli_chal, 2, 0x0); - SIVAL(nt_cli_chal, 4, 0x0); - SIVAL(nt_cli_chal, 8, nt_time.low); - SIVAL(nt_cli_chal, 12, nt_time.high); - memcpy(nt_cli_chal+16, lm_cli_chal, 8); - /* fill in offset 24, size of structure, later */ - - *nt_cli_chal_len = 28; - - SSVAL(nt_cli_chal, *nt_cli_chal_len, 2); - *nt_cli_chal_len += 2; - SSVAL(nt_cli_chal, *nt_cli_chal_len, dom_len*2); - *nt_cli_chal_len += 2; - ascii_to_unibuf(nt_cli_chal+(*nt_cli_chal_len), domain, dom_len*2); - *nt_cli_chal_len += dom_len*2; - *nt_cli_chal_len += 4 - ((*nt_cli_chal_len) % 4); - - SSVAL(nt_cli_chal, *nt_cli_chal_len, 2); - *nt_cli_chal_len += 2; - SSVAL(nt_cli_chal, 30, srv_len*2); - *nt_cli_chal_len += 2; - ascii_to_unibuf(nt_cli_chal+(*nt_cli_chal_len), server, srv_len*2); - *nt_cli_chal_len += srv_len*2; - - SSVAL(nt_cli_chal, 24, (*nt_cli_chal_len)+16); - SSVAL(nt_cli_chal, 26, (*nt_cli_chal_len)+15); - - DEBUG(100,("SMBgenclientchals: srv %s, dom %s\n", server, domain)); - dump_data(100, nt_cli_chal, *nt_cli_chal_len); -} - -void ntv2_owf_gen(const uchar owf[16], - const char *user_n, - const char *domain_n, - uchar kr_buf[16]) -{ - pstring user_u; - pstring dom_u; - HMACMD5Context ctx; - - int user_l = strlen(user_n ); - int domain_l = strlen(domain_n); - - _my_mbstowcsupper((int16*)user_u, user_n , user_l*2 ); - _my_mbstowcsupper((int16*)dom_u , domain_n, domain_l*2); - - hmac_md5_init_limK_to_64(owf, 16, &ctx); - hmac_md5_update(user_u, user_l*2, &ctx); - hmac_md5_update(dom_u, domain_l*2, &ctx); - hmac_md5_final(kr_buf, &ctx); -#ifdef DEBUG_PASSWORD - DEBUG(100,("ntv2_owf_gen: user, domain, owfkey, kr\n")); - dump_data(100, user_u, user_l*2); - dump_data(100, dom_u, domain_l*2); - dump_data(100, owf, 16); - dump_data(100, kr_buf, 16); -#endif -} - -/* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */ -void NTLMSSPOWFencrypt(uchar pwrd[8], uchar *ntlmchalresp, uchar p24[24]) +/* Does the NT MD4 hash then des encryption. */ + +void SMBNTencrypt(uchar *passwd, uchar *c8, uchar *p24) { uchar p21[21]; memset(p21,'\0',21); - memcpy(p21, pwrd, 8); - memset(p21 + 8, 0xbd, 8); + + E_md4hash(passwd, p21); + SMBOWFencrypt(p21, c8, p24); - E_P24(p21, ntlmchalresp, p24); #ifdef DEBUG_PASSWORD - DEBUG(100,("NTLMSSPOWFencrypt: p21, c8, p24\n")); - dump_data(100, p21, 21); - dump_data(100, ntlmchalresp, 8); - dump_data(100, p24, 24); + DEBUG(100,("SMBNTencrypt: nt#, challenge, response\n")); + dump_data(100, (char *)p21, 16); + dump_data(100, (char *)c8, 8); + dump_data(100, (char *)p24, 24); #endif } -BOOL make_oem_passwd_hash(char data[516], const char *pwrd, uchar old_pw_hash[16], BOOL unicode) +BOOL make_oem_passwd_hash(char data[516], const char *passwd, uchar old_pw_hash[16], BOOL unicode) { - int new_pw_len = strlen(pwrd) * (unicode ? 2 : 1); + int new_pw_len = strlen(passwd) * (unicode ? 2 : 1); if (new_pw_len > 512) { - DEBUG(0,("make_oem_pwrd_hash: new password is too long.\n")); + DEBUG(0,("make_oem_passwd_hash: new password is too long.\n")); return False; } @@ -425,16 +209,18 @@ BOOL make_oem_passwd_hash(char data[516], const char *pwrd, uchar old_pw_hash[16 generate_random_buffer((unsigned char *)data, 516, False); if (unicode) { - ascii_to_unibuf(&data[512 - new_pw_len], pwrd, new_pw_len); + /* Note that passwd should be in DOS oem character set. */ + dos_struni2( &data[512 - new_pw_len], passwd, 512); } else { - fstrcpy( &data[512 - new_pw_len], pwrd); + /* Note that passwd should be in DOS oem character set. */ + fstrcpy( &data[512 - new_pw_len], passwd); } SIVAL(data, 512, new_pw_len); #ifdef DEBUG_PASSWORD - DEBUG(100,("make_oem_pwrd_hash\n")); + DEBUG(100,("make_oem_passwd_hash\n")); dump_data(100, data, 516); #endif SamOEMhash( (unsigned char *)data, (unsigned char *)old_pw_hash, True); @@ -442,138 +228,3 @@ BOOL make_oem_passwd_hash(char data[516], const char *pwrd, uchar old_pw_hash[16 return True; } -BOOL nt_decrypt_string2(STRING2 *out, const STRING2 *in, const uchar *key) -{ - uchar bufhdr[8]; - int datalen; - - const uchar *keyptr = key; - const uchar *keyend = key + 16; - - uchar *outbuf = (uchar *)out->buffer; - const uchar *inbuf = (const uchar *)in->buffer; - const uchar *inbufend; - - smbhash(bufhdr, inbuf, keyptr, 0); - datalen = IVAL(bufhdr, 0); - - if ((datalen > in->str_str_len) || (datalen > MAX_STRINGLEN)) - { - DEBUG(0, ("nt_decrypt_string2: failed\n")); - return False; - } - - out->str_max_len = out->str_str_len = datalen; - inbuf += 8; - inbufend = inbuf + datalen; - - while (inbuf < inbufend) - { - keyptr += 7; - if (keyptr + 7 > keyend) - { - keyptr = (keyend - keyptr) + key; - } - - smbhash(outbuf, inbuf, keyptr, 0); - - inbuf += 8; - outbuf += 8; - } - - return True; -} - -/******************************************************************* - creates a DCE/RPC bind authentication response - - - initialises the parse structure. - - dynamically allocates the header data structure - - caller is expected to free the header data structure once used. - - ********************************************************************/ -void create_ntlmssp_resp(struct pwd_info *pwd, - char *domain, char *user_name, char *my_name, - uint32 ntlmssp_cli_flgs, - prs_struct *auth_resp) -{ - RPC_AUTH_NTLMSSP_RESP ntlmssp_resp; - unsigned char lm_owf[24]; - unsigned char nt_owf[128]; - size_t nt_owf_len; - - pwd_get_lm_nt_owf(pwd, lm_owf, nt_owf, &nt_owf_len, NULL); - - make_rpc_auth_ntlmssp_resp(&ntlmssp_resp, - lm_owf, nt_owf, nt_owf_len, - domain, user_name, my_name, - ntlmssp_cli_flgs); - - smb_io_rpc_auth_ntlmssp_resp("ntlmssp_resp", &ntlmssp_resp, auth_resp, 0); - mem_realloc_data(auth_resp->data, auth_resp->offset); -} - -/*********************************************************** - decode a password buffer -************************************************************/ -BOOL decode_pw_buffer(const char buffer[516], char *new_pwrd, - int new_pwrd_size, uint32 *new_pw_len) -{ - /* - * The length of the new password is in the last 4 bytes of - * the data buffer. - */ - - (*new_pw_len) = IVAL(buffer, 512); - -#ifdef DEBUG_PASSWORD - dump_data(100, buffer, 516); -#endif - - if ((*new_pw_len) < 0 || (*new_pw_len) > new_pwrd_size - 1) - { - DEBUG(0,("check_oem_password: incorrect password length (%d).\n", (*new_pw_len))); - return False; - } - - memcpy(new_pwrd, &buffer[512-(*new_pw_len)], (*new_pw_len)); - new_pwrd[(*new_pw_len)] = '\0'; - - return True; -} - -/*********************************************************** - encode a password buffer -************************************************************/ -BOOL encode_pw_buffer(char buffer[516], const char *new_pass, - int new_pw_len, BOOL nt_pass_set) -{ - generate_random_buffer(buffer, 516, True); - - if (nt_pass_set) - { - /* - * nt passwords are in unicode. last char overwrites NULL - * in ascii_to_unibuf, so use SIVAL *afterwards*. - */ - new_pw_len *= 2; - ascii_to_unibuf(&buffer[512-new_pw_len], new_pass, new_pw_len); - } - else - { - memcpy(&buffer[512-new_pw_len], new_pass, new_pw_len); - } - - /* - * The length of the new password is in the last 4 bytes of - * the data buffer. - */ - - SIVAL(buffer, 512, new_pw_len); - -#ifdef DEBUG_PASSWORD - dump_data(100, buffer, 516); -#endif - - return True; -} diff --git a/source3/libsmb/smberr.c b/source3/libsmb/smberr.c index 228eee5892..c2d8884d73 100644 --- a/source3/libsmb/smberr.c +++ b/source3/libsmb/smberr.c @@ -143,70 +143,39 @@ struct {0xFF,"ERRCMD",NULL}, {-1,NULL,NULL}}; -char *smb_err_msg(uint8 class, uint32 num) -{ - static pstring ret; - smb_safe_err_msg(class, num, ret, sizeof(ret)); - return ret; -} - /**************************************************************************** return a SMB error string from a SMB buffer ****************************************************************************/ -BOOL smb_safe_err_msg(uint8 class, uint32 num, char *ret, size_t len) +char *smb_errstr(char *inbuf) { - int i,j; - - for (i=0;err_classes[i].class;i++) - { - if (err_classes[i].code == class) + static pstring ret; + int class = CVAL(inbuf,smb_rcls); + int num = SVAL(inbuf,smb_err); + int i,j; + + for (i=0;err_classes[i].class;i++) + if (err_classes[i].code == class) + { + if (err_classes[i].err_msgs) + { + err_code_struct *err = err_classes[i].err_msgs; + for (j=0;err[j].name;j++) + if (num == err[j].code) { - err_code_struct *err = err_classes[i].err_msgs; - if (err != NULL) - { - for (j=0;err[j].name;j++) - { - if (num == err[j].code) - { - if (DEBUGLEVEL > 0) - { - slprintf(ret, len - 1, "%s - %s (%s)",err_classes[i].class, - err[j].name,err[j].message); - } - else - { - slprintf(ret, len - 1, "%s - %s",err_classes[i].class,err[j].name); - } - return True; - } - } - } - slprintf(ret, len - 1, "%s - %d",err_classes[i].class, num); - return True; + if (DEBUGLEVEL > 0) + slprintf(ret, sizeof(ret) - 1, "%s - %s (%s)",err_classes[i].class, + err[j].name,err[j].message); + else + slprintf(ret, sizeof(ret) - 1, "%s - %s",err_classes[i].class,err[j].name); + return ret; } + } - } - - slprintf(ret, len - 1, "Error: Unknown error (%d,%d)",class,num); - return False; -} - -/**************************************************************************** -return a SMB error string from a SMB buffer -****************************************************************************/ -BOOL smb_safe_errstr(char *inbuf, char *msg, size_t len) -{ - return smb_safe_err_msg(CVAL(inbuf,smb_rcls), SVAL(inbuf,smb_err), - msg, len); -} - -/**************************************************************************** -return a SMB error string from a SMB buffer -****************************************************************************/ -char *smb_errstr(char *inbuf) -{ - static fstring errmsg; - (void)smb_safe_errstr(inbuf, errmsg, sizeof(errmsg)); - return errmsg; + slprintf(ret, sizeof(ret) - 1, "%s - %d",err_classes[i].class,num); + return ret; + } + + slprintf(ret, sizeof(ret) - 1, "Error: Unknown error (%d,%d)",class,num); + return(ret); } |