From e357d9106895b165bfa3f8331b9f186004c9a6cd Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sun, 9 Nov 1997 17:30:10 +0000 Subject: attempting to mark up 32 bit error codes, needed for NT domains. separated out smb server-mode password validation into a separate file. added called and calling netbios names to client gen state: referenced section in rfc1002.txt. created workstation trust account checking code in ntclient.c there might be a bug in reply_session_setup_andX. i indented and added { } around single-line if statements: the lm password checking code now doesn't look right (around the GUEST_SESSSETUP bits). *no code semantics have been changed by the indentation process*. (This used to be commit f27966957fa7f16d337a4a58719239d036deab4c) --- source3/client/client.c | 2 +- source3/client/ntclient.c | 127 ++++++++++++++++++-- source3/include/proto.h | 41 +++++-- source3/include/smb.h | 50 +++++++- source3/libsmb/clientgen.c | 146 +++++++++++++---------- source3/libsmb/nterr.c | 30 ++++- source3/libsmb/smbencrypt.c | 22 +++- source3/libsmb/smberr.c | 26 ++++- source3/nmbsync.c | 3 +- source3/passdb/smbpass.c | 2 +- source3/pwd_validate.c | 276 ++++++++++++++++++++++++++++++++++++++++++++ source3/smbd/password.c | 140 +--------------------- source3/smbd/reply.c | 89 ++++++++------ source3/smbd/server.c | 93 +++++++++------ source3/utils/torture.c | 6 +- 15 files changed, 731 insertions(+), 322 deletions(-) create mode 100644 source3/pwd_validate.c diff --git a/source3/client/client.c b/source3/client/client.c index 52f4b837a6..082118e0ba 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -3900,7 +3900,7 @@ static void usage(char *pname) { if (!cli_send_login(NULL,NULL,True,True)) return(1); - do_nt_login(desthost, myhostname, Client, cnum); + do_nt_login(dest_ip, desthost, myhostname, Client, cnum); cli_send_logout(); close_sockets(); diff --git a/source3/client/ntclient.c b/source3/client/ntclient.c index 7e360981c0..a32f6e690d 100644 --- a/source3/client/ntclient.c +++ b/source3/client/ntclient.c @@ -25,6 +25,7 @@ #endif #include "includes.h" +#include "nterr.h" extern int DEBUGLEVEL; extern pstring username; @@ -35,11 +36,110 @@ extern pstring workgroup; #ifdef NTDOMAIN +/************************************************************************ + check workstation trust account status + ************************************************************************/ +BOOL wksta_trust_account_check(struct in_addr dest_ip, char *dest_host, + char *myhostname, char *domain) +{ + pstring tmp; + struct cli_state wksta_trust; + fstring mach_acct; + fstring mach_pwd; + fstring new_mach_pwd; + uchar lm_owf_mach_pwd[16]; + uchar nt_owf_mach_pwd[16]; + uchar lm_sess_pwd[24]; + uchar nt_sess_pwd[24]; + BOOL right_error_code = False; + + char *start_mach_pwd; + char *change_mach_pwd; + + fstrcpy(mach_acct, myhostname); + strlower(mach_pwd); + + fstrcpy(mach_pwd , myhostname); + strcat(mach_acct, "$"); + strupper(mach_acct); + + sprintf(tmp, "Enter Workstation Trust Account password for [%s].\nDefault is [%s]. Password: ", + mach_acct, mach_pwd); + + start_mach_pwd = (char*)getpass(tmp); + + if (start_mach_pwd[0] != 0) + { + fstrcpy(mach_pwd, start_mach_pwd); + } + + sprintf(tmp, "Enter new Workstation Trust Account password for [%s]\nPress Return to leave at old value. Password: ", + mach_acct); + + change_mach_pwd = (char*)getpass(tmp); + + fstrcpy(new_mach_pwd, change_mach_pwd); + + if (!cli_initialise(&wksta_trust)) + { + DEBUG(1,("cli_initialise failed for wksta_trust\n")); + return False; + } + + if (!server_connect_init(&wksta_trust, myhostname, dest_ip, dest_host)) + { + int err_cls; + int err_num; + cli_error(&wksta_trust, &err_cls, &err_num); + DEBUG(1,("server_connect_init failed (%s)\n", cli_errstr(&wksta_trust))); + + cli_shutdown(&wksta_trust); + return False; + } + + nt_lm_owf_gen(mach_pwd, nt_owf_mach_pwd, lm_owf_mach_pwd); + + DEBUG(5,("generating nt owf from initial machine pwd: %s\n", mach_pwd)); + SMBOWFencrypt(nt_owf_mach_pwd, wksta_trust.cryptkey, nt_sess_pwd); + SMBOWFencrypt(lm_owf_mach_pwd, wksta_trust.cryptkey, lm_sess_pwd); + + right_error_code = False; + + if (!server_validate2(&wksta_trust, mach_acct, domain, + lm_sess_pwd, sizeof(lm_sess_pwd), + nt_sess_pwd, sizeof(nt_sess_pwd))) + { + int err_cls; + int err_num; + cli_error(&wksta_trust, &err_cls, &err_num); + + if (err_cls == 0xC000 && err_num == NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT) + { + DEBUG(1,("server_validate: valid workstation trust account exists\n")); + right_error_code = True; + } + + if (err_cls == 0xC000 && err_num == NT_STATUS_NO_SUCH_USER) + { + DEBUG(1,("server_validate: workstation trust account does not exist\n")); + right_error_code = False; + } + } + + if (!right_error_code) + { + DEBUG(1,("server_validate failed (%s)\n", cli_errstr(&wksta_trust))); + } + + cli_shutdown(&wksta_trust); + return right_error_code; +} /**************************************************************************** experimental nt login. ****************************************************************************/ -BOOL do_nt_login(char *desthost, char *myhostname, +BOOL do_nt_login(struct in_addr dest_ip, char *dest_host, + char *myhostname, int Client, int cnum) { DOM_CHAL clnt_chal; @@ -66,9 +166,12 @@ BOOL do_nt_login(char *desthost, char *myhostname, uchar sess_key[8]; char nt_owf_mach_pwd[16]; + + fstring server_name; fstring mach_acct; + fstring mach_pwd; - fstring server_name; + fstring new_mach_pwd; RPC_IFACE abstract; RPC_IFACE transfer; @@ -88,6 +191,8 @@ BOOL do_nt_login(char *desthost, char *myhostname, uint32 call_id = 0; char *inbuf,*outbuf; + /******************** initialise ********************************/ + zerotime.time = 0; inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); @@ -99,6 +204,10 @@ BOOL do_nt_login(char *desthost, char *myhostname, return False; } + /************ check workstation trust account *******************/ + + wksta_trust_account_check(dest_ip, dest_host, myhostname, workgroup); + /******************* open the \PIPE\lsarpc file *****************/ if ((fnum = rpc_pipe_open(inbuf, outbuf, PIPE_LSARPC, Client, cnum)) == 0xffff) @@ -216,17 +325,11 @@ BOOL do_nt_login(char *desthost, char *myhostname, /******************* Request Challenge ********************/ - fstrcpy(mach_acct, myhostname); - strlower(mach_pwd); - - fstrcpy(mach_pwd , myhostname); - strcat(mach_acct, "$"); - SIVAL(clnt_chal.data, 0, 0x11111111); SIVAL(clnt_chal.data, 4, 0x22222222); /* send a client challenge; receive a server challenge */ - if (!do_lsa_req_chal(fnum, ++call_id, desthost, myhostname, &clnt_chal, &srv_chal)) + if (!do_lsa_req_chal(fnum, ++call_id, dest_host, myhostname, &clnt_chal, &srv_chal)) { cli_smb_close(inbuf, outbuf, Client, cnum, fnum); free(inbuf); free(outbuf); @@ -268,7 +371,7 @@ BOOL do_nt_login(char *desthost, char *myhostname, cred_create(sess_key, &clnt_chal, zerotime, &(clnt_cred.challenge)); /* send client auth-2 challenge; receive an auth-2 challenge */ - if (!do_lsa_auth2(fnum, ++call_id, desthost, mach_acct, 2, myhostname, + if (!do_lsa_auth2(fnum, ++call_id, dest_host, mach_acct, 2, myhostname, &(clnt_cred.challenge), 0x000001ff, &auth2_srv_chal)) { cli_smb_close(inbuf, outbuf, Client, cnum, fnum); @@ -311,7 +414,7 @@ BOOL do_nt_login(char *desthost, char *myhostname, /* send client sam-logon challenge; receive a sam-logon challenge */ if (!do_lsa_sam_logon(fnum, ++call_id, sess_key, &clnt_cred, - desthost, mach_acct, + dest_host, mach_acct, &sam_logon_clnt_cred, &sam_logon_rtn_cred, 1, 1, &id1, &user_info1, &sam_logon_srv_cred)) @@ -332,7 +435,7 @@ BOOL do_nt_login(char *desthost, char *myhostname, /* send client sam-logoff challenge; receive a sam-logoff challenge */ if (!do_lsa_sam_logoff(fnum, ++call_id, sess_key, &clnt_cred, - desthost, mach_acct, + dest_host, mach_acct, &sam_logoff_clnt_cred, &sam_logoff_rtn_cred, 1, 1, &id1, &sam_logoff_srv_cred)) diff --git a/source3/include/proto.h b/source3/include/proto.h index 98c671ea86..cffa297413 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -61,13 +61,14 @@ BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int int cli_read(struct cli_state *cli, int fnum, char *buf, uint32 offset, uint16 size); int cli_write(struct cli_state *cli, int fnum, char *buf, uint32 offset, uint16 size); BOOL cli_negprot(struct cli_state *cli); -BOOL cli_session_request(struct cli_state *cli, char *host, int name_type, - char *myname); +BOOL cli_session_request(struct cli_state *cli, + char *called_host_name , int called_name_type, + char calling_netbios_name[16], int calling_name_type); BOOL cli_connect(struct cli_state *cli, char *host, struct in_addr *ip); BOOL cli_initialise(struct cli_state *cli); void cli_shutdown(struct cli_state *cli); char *cli_errstr(struct cli_state *cli); -void cli_error(struct cli_state *cli, int *eclass, int *num); +BOOL cli_error(struct cli_state *cli, uint8 *eclass, uint32 *num); void cli_sockopt(struct cli_state *cli, char *options); int cli_setpid(struct cli_state *cli, int pid); @@ -627,9 +628,16 @@ void sync_browse_lists(struct subnet_record *d, struct work_record *work, /*The following definitions come from ntclient.c */ -BOOL do_nt_login(char *desthost, char *myhostname, +BOOL wksta_trust_account_check(struct in_addr dest_ip, char *dest_host, + char *myhostname, char *domain); +BOOL do_nt_login(struct in_addr dest_ip, char *dest_host, + char *myhostname, int Client, int cnum); +/*The following definitions come from nterr.c */ + +char *get_nt_error_msg(uint16 nt_code); + /*The following definitions come from params.c */ BOOL pm_process( char *FileName, @@ -654,11 +662,6 @@ BOOL user_ok(char *user,int snum); BOOL authorise_login(int snum,char *user,char *password, int pwlen, BOOL *guest,BOOL *force,uint16 vuid); BOOL check_hosts_equiv(char *user); -struct cli_state *server_client(void); -struct cli_state *server_cryptkey(void); -BOOL server_validate(char *user, char *domain, - char *pass, int passlen, - char *ntpass, int ntpasslen); /*The following definitions come from pcap.c */ @@ -692,6 +695,18 @@ void status_printjob(int cnum,int snum,int jobid,int status); int printjob_encode(int snum, int job); void printjob_decode(int jobid, int *snum, int *job); +/*The following definitions come from pwd_validate.c */ + +BOOL server_connect_init(struct cli_state *clnt, char my_netbios_name[16], + struct in_addr dest_ip, char *desthost); +BOOL server_cryptkey(struct cli_state *clnt, char my_netbios_name[16]); +BOOL server_validate2(struct cli_state *clnt, char *user, char *domain, + char *pass, int passlen, + char *ntpass, int ntpasslen); +BOOL server_validate(struct cli_state *clnt, char *user, char *domain, + char *pass, int passlen, + char *ntpass, int ntpasslen); + /*The following definitions come from quotas.c */ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize); @@ -1029,6 +1044,7 @@ char* wks_io_r_unknown_0(BOOL io, WKS_R_UNKNOWN_0 *r_u, char *q, char *base, int /*The following definitions come from server.c */ +struct cli_state *pwd_server_connection(void); void *dflt_sig(void); void killkids(void); mode_t unix_mode(int cnum,int dosmode); @@ -1096,10 +1112,11 @@ void cred_hash2(unsigned char *out,unsigned char *in,unsigned char *key); /*The following definitions come from smbencrypt.c */ -void SMBencrypt(uchar *passwd, uchar *c8, uchar *p24); +void SMBencrypt(uchar *passwd, uchar *c8, uchar p24[24]); void E_md4hash(uchar *passwd, uchar *p16); -void SMBNTencrypt(uchar *passwd, uchar *c8, uchar *p24); -void nt_lm_owf_gen(char *pwd, char *nt_p16, char *p16); +void SMBOWFencrypt(char passwd[16], uchar *c8, uchar p24[24]); +void SMBNTencrypt(uchar *passwd, uchar *c8, uchar p24[24]); +void nt_lm_owf_gen(char *pwd, char nt_p16[16], char p16[16]); /*The following definitions come from smberr.c */ diff --git a/source3/include/smb.h b/source3/include/smb.h index afa9e3d9b9..687f14b9ca 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -1363,9 +1363,13 @@ struct cli_state { int protocol; int sec_mode; int error; - int privilages; + int privileges; fstring eff_name; - fstring desthost; + + fstring full_dest_host_name; + char called_netbios_name[16]; + char calling_netbios_name[16]; + char cryptkey[8]; uint32 sesskey; int serverzone; @@ -2020,6 +2024,15 @@ char *Strstr(char *s, char *p); #define BROWSER_CONSTANT 0xaa55 +/* NT Flags2 bits - cifs6.txt section 3.1.2 */ + +#define FLAGS2_LONG_PATH_COMPONENTS 0x0001 +#define FLAGS2_EXTENDED_ATTRIBUTES 0x0002 +#define FLAGS2_DFS_PATHNAMES 0x1000 +#define FLAGS2_READ_PERMIT_NO_EXECUTE 0x2000 +#define FLAGS2_32_BIT_ERROR_CODES 0x4000 +#define FLAGS2_UNICODE_STRINGS 0x8000 + /* Capabilities. see ftp.microsoft.com/developr/drg/cifs/cifs/cifs4.txt */ #define CAP_RAW_MODE 0x0001 @@ -2037,14 +2050,39 @@ char *Strstr(char *s, char *p); /* protocol types. It assumes that higher protocols include lower protocols as subsets */ -enum protocol_types {PROTOCOL_NONE,PROTOCOL_CORE,PROTOCOL_COREPLUS,PROTOCOL_LANMAN1,PROTOCOL_LANMAN2,PROTOCOL_NT1}; +enum protocol_types +{ + PROTOCOL_NONE, + PROTOCOL_CORE, + PROTOCOL_COREPLUS, + PROTOCOL_LANMAN1, + PROTOCOL_LANMAN2, + PROTOCOL_NT1 +}; /* security levels */ -enum security_types {SEC_SHARE,SEC_USER,SEC_SERVER}; +enum security_types +{ + SEC_SHARE, + SEC_USER, + SEC_SERVER +}; + +/* bit-masks for security mode. see cifs6.txt Negprot 4.1.1 server response */ +#define USE_USER_LEVEL_SECURITY 1 +#define USE_CHALLENGE_RESPONSE 2 /* printing types */ -enum printing_types {PRINT_BSD,PRINT_SYSV,PRINT_AIX,PRINT_HPUX, - PRINT_QNX,PRINT_PLP,PRINT_LPRNG}; +enum printing_types +{ + PRINT_BSD, + PRINT_SYSV, + PRINT_AIX, + PRINT_HPUX, + PRINT_QNX, + PRINT_PLP, + PRINT_LPRNG +}; /* Remote architectures we know about. */ enum remote_arch_types {RA_UNKNOWN, RA_WFWG, RA_OS2, RA_WIN95, RA_WINNT, RA_SAMBA}; diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index b98f2fca69..78bbf8115f 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -104,7 +104,7 @@ static BOOL cli_send_trans(struct cli_state *cli, if (this_ldata < ldata || this_lparam < lparam) { /* receive interim response */ if (!receive_smb(cli->fd,cli->inbuf,cli->timeout) || - CVAL(cli->inbuf,smb_rcls) != 0) { + cli_error(cli,NULL, NULL)) { return(False); } @@ -176,8 +176,7 @@ static BOOL cli_receive_trans(struct cli_state *cli, CVAL(cli->inbuf,smb_com))); return(False); } - if (CVAL(cli->inbuf,smb_rcls) != 0) - return(False); + if (cli_error(cli,NULL, NULL)) return(False); /* parse out the lengths */ total_data = SVAL(cli->inbuf,smb_tdrcnt); @@ -227,8 +226,7 @@ static BOOL cli_receive_trans(struct cli_state *cli, CVAL(cli->inbuf,smb_com))); return(False); } - if (CVAL(cli->inbuf,smb_rcls) != 0) - return(False); + if (cli_error(cli,NULL, NULL)) return(False); } return(True); @@ -300,7 +298,7 @@ BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation) if (cli->error == 0) { DEBUG(4,("NetWkstaUserLogon success\n")); - cli->privilages = SVAL(p, 24); + cli->privileges = SVAL(p, 24); fstrcpy(cli->eff_name,p+2); } else { DEBUG(1,("NetwkstaUserLogon gave error %d\n", cli->error)); @@ -424,15 +422,22 @@ BOOL cli_session_setup(struct cli_state *cli, return False; } - if ((cli->sec_mode & 2) && *pass && passlen != 24) { + if ((cli->sec_mode & USE_CHALLENGE_RESPONSE) && *pass && passlen != 24) + { passlen = 24; SMBencrypt((uchar *)pass,(uchar *)cli->cryptkey,(uchar *)pword); - } else { + } + else + { memcpy(pword, pass, passlen); } /* if in share level security then don't send a password now */ - if (!(cli->sec_mode & 1)) {fstrcpy(pword, "");passlen=1;} + if (!(cli->sec_mode & USE_USER_LEVEL_SECURITY)) + { + fstrcpy(pword, ""); + passlen=1; + } /* send a session setup command */ bzero(cli->outbuf,smb_size); @@ -487,9 +492,7 @@ BOOL cli_session_setup(struct cli_state *cli, show_msg(cli->inbuf); - if (CVAL(cli->inbuf,smb_rcls) != 0) { - return False; - } + if (cli_error(cli,NULL, NULL)) return(False); /* use the returned uid from now on */ cli->uid = SVAL(cli->inbuf,smb_uid); @@ -509,19 +512,19 @@ BOOL cli_send_tconX(struct cli_state *cli, bzero(cli->outbuf,smb_size); bzero(cli->inbuf,smb_size); - if (cli->sec_mode & 1) { + if (cli->sec_mode & USE_USER_LEVEL_SECURITY) { passlen = 1; pass = ""; } - if ((cli->sec_mode & 2) && *pass && passlen != 24) { + if ((cli->sec_mode & USE_CHALLENGE_RESPONSE) && *pass && passlen != 24) { passlen = 24; SMBencrypt((uchar *)pass,(uchar *)cli->cryptkey,(uchar *)pword); } else { memcpy(pword, pass, passlen); } - sprintf(fullshare, "\\\\%s\\%s", cli->desthost, share); + sprintf(fullshare, "\\\\%s\\%s", cli->called_netbios_name, share); set_message(cli->outbuf,4, 2 + strlen(fullshare) + passlen + strlen(dev),True); @@ -544,9 +547,7 @@ BOOL cli_send_tconX(struct cli_state *cli, if (!receive_smb(cli->fd,cli->inbuf,cli->timeout)) return False; - if (CVAL(cli->inbuf,smb_rcls) != 0) { - return False; - } + if (cli_error(cli,NULL, NULL)) return(False); cli->cnum = SVAL(cli->inbuf,smb_tid); return True; @@ -568,7 +569,7 @@ BOOL cli_tdis(struct cli_state *cli) if (!receive_smb(cli->fd,cli->inbuf,cli->timeout)) return False; - return CVAL(cli->inbuf,smb_rcls) == 0; + return !cli_error(cli,NULL, NULL); } /**************************************************************************** @@ -599,9 +600,7 @@ BOOL cli_unlink(struct cli_state *cli, char *fname) return False; } - if (CVAL(cli->inbuf,smb_rcls) != 0) { - return False; - } + if (cli_error(cli,NULL, NULL)) return False; return True; } @@ -659,9 +658,7 @@ int cli_open(struct cli_state *cli, char *fname, int flags, int share_mode) return -1; } - if (CVAL(cli->inbuf,smb_rcls) != 0) { - return -1; - } + if (cli_error(cli,NULL, NULL)) return -1; return SVAL(cli->inbuf,smb_vwv2); } @@ -692,9 +689,7 @@ BOOL cli_close(struct cli_state *cli, int fnum) return False; } - if (CVAL(cli->inbuf,smb_rcls) != 0) { - return False; - } + if (cli_error(cli,NULL, NULL)) return False; return True; } @@ -733,9 +728,7 @@ BOOL cli_lock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int ti return False; } - if (CVAL(cli->inbuf,smb_rcls) != 0) { - return False; - } + if (cli_error(cli,NULL, NULL)) return False; return True; } @@ -773,9 +766,7 @@ BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int return False; } - if (CVAL(cli->inbuf,smb_rcls) != 0) { - return False; - } + if (cli_error(cli,NULL, NULL)) return False; return True; } @@ -808,9 +799,7 @@ int cli_read(struct cli_state *cli, int fnum, char *buf, uint32 offset, uint16 s return -1; } - if (CVAL(cli->inbuf,smb_rcls) != 0) { - return -1; - } + if (cli_error(cli,NULL, NULL)) return -1; size = SVAL(cli->inbuf, smb_vwv5); p = smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_vwv6); @@ -852,9 +841,7 @@ int cli_write(struct cli_state *cli, int fnum, char *buf, uint32 offset, uint16 return -1; } - if (CVAL(cli->inbuf,smb_rcls) != 0) { - return -1; - } + if (cli_error(cli,NULL, NULL)) return -1; return SVAL(cli->inbuf, smb_vwv2); } @@ -899,10 +886,8 @@ BOOL cli_negprot(struct cli_state *cli) show_msg(cli->inbuf); - if (CVAL(cli->inbuf,smb_rcls) != 0 || - ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots)) { - return(False); - } + if (cli_error(cli,NULL, NULL)) return False; + if ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots) return(False); cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot; @@ -936,33 +921,43 @@ BOOL cli_negprot(struct cli_state *cli) return True; } +#define TRUNCATE_NETBIOS_NAME 1 /**************************************************************************** - send a session request + send a session request. see rfc1002.txt 4.3 and 4.3.2 ****************************************************************************/ -BOOL cli_session_request(struct cli_state *cli, char *host, int name_type, - char *myname) +BOOL cli_session_request(struct cli_state *cli, + char *called_host_name , int called_name_type, + char calling_netbios_name[16], int calling_name_type) { - fstring dest; char *p; int len = 4; /* send a session request (RFC 1002) */ - fstrcpy(dest,host); + strncpy(cli->called_netbios_name , called_host_name , sizeof(cli->called_netbios_name )); + strncpy(cli->calling_netbios_name, calling_netbios_name, sizeof(cli->calling_netbios_name)); - p = strchr(dest,'.'); + /* sorry, don't trust strncpy to null-terminate the string... */ + cli->called_netbios_name [sizeof(cli->called_netbios_name )-1] = 0; + cli->calling_netbios_name[sizeof(cli->calling_netbios_name)-1] = 0; + +#ifdef TRUNCATE_NETBIOS_NAME + /* ok. this is because of a stupid microsoft-ism. if the called host + name contains a '.', microsoft clients expect you to truncate the + netbios name up to and including the '.' + */ + p = strchr(cli->called_netbios_name, '.'); if (p) *p = 0; - - fstrcpy(cli->desthost, dest); +#endif /* TRUNCATE_NETBIOS_NAME */ /* put in the destination name */ p = cli->outbuf+len; - name_mangle(dest,p,name_type); + name_mangle(cli->called_netbios_name, p, called_name_type); len += name_len(p); /* and my name */ p = cli->outbuf+len; - name_mangle(myname,p,0); + name_mangle(cli->calling_netbios_name, p, calling_name_type); len += name_len(p); /* setup the packet length */ @@ -990,26 +985,27 @@ BOOL cli_connect(struct cli_state *cli, char *host, struct in_addr *ip) { struct in_addr dest_ip; - fstrcpy(cli->desthost, host); + fstrcpy(cli->full_dest_host_name, host); - if (!ip) { + if (!ip) + { + /* no ip specified - look up the name */ struct hostent *hp; - if ((hp = Get_Hostbyname(cli->desthost)) == 0) { + if ((hp = Get_Hostbyname(host)) == 0) { return False; } putip((char *)&dest_ip,(char *)hp->h_addr); } else { + /* use the given ip address */ dest_ip = *ip; } - + /* open the socket */ cli->fd = open_socket_out(SOCK_STREAM, &dest_ip, 139, cli->timeout); - if (cli->fd == -1) - return False; - return True; + return (cli->fd != -1); } @@ -1059,10 +1055,32 @@ char *cli_errstr(struct cli_state *cli) /**************************************************************************** return error codes for the last packet ****************************************************************************/ -void cli_error(struct cli_state *cli, int *eclass, int *num) +BOOL cli_error(struct cli_state *cli, uint8 *eclass, uint32 *num) { - *eclass = CVAL(cli->inbuf,smb_rcls); - *num = SVAL(cli->inbuf,smb_err); + int flgs2 = SVAL(cli->inbuf,smb_flg2); + + if (eclass) *eclass = 0; + if (num ) *num = 0; + + 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; + return (nt_err != 0); + } + else + { + /* dos 16 bit error codes detected */ + char rcls = CVAL(cli->inbuf,smb_rcls); + if (rcls != 0) + { + if (eclass) *eclass = rcls; + if (num ) *num = SVAL(cli->inbuf,smb_err); + return True; + } + } + return False; } /**************************************************************************** diff --git a/source3/libsmb/nterr.c b/source3/libsmb/nterr.c index bda0f882a6..7dd2234e1d 100644 --- a/source3/libsmb/nterr.c +++ b/source3/libsmb/nterr.c @@ -1,12 +1,16 @@ +/* NT error codes. please read nterr.h */ +#include "includes.h" #include "nterr.h" -static struct +typedef struct { char *nt_errstr; uint16 nt_errcode; -} nt_errs[] = +} nt_err_code_struct; + +nt_err_code_struct nt_errs[] = { { "NT_STATUS_UNSUCCESSFUL", NT_STATUS_UNSUCCESSFUL }, { "NT_STATUS_NOT_IMPLEMENTED", NT_STATUS_NOT_IMPLEMENTED }, @@ -512,3 +516,25 @@ static struct { NULL, 0 } }; +/***************************************************************************** + returns an NT error message. not amazingly helpful, but better than a number. + *****************************************************************************/ +char *get_nt_error_msg(uint16 nt_code) +{ + static pstring msg; + int idx = 0; + + strcpy(msg, "Unknown NT error"); + + while (nt_errs[idx].nt_errstr != NULL) + { + if (nt_errs[idx].nt_errcode == nt_code) + { + strcpy(msg, nt_errs[idx].nt_errstr); + return msg; + } + idx++; + } + return NULL; +} + diff --git a/source3/libsmb/smbencrypt.c b/source3/libsmb/smbencrypt.c index 38d414cf23..1bf0bcc8e6 100644 --- a/source3/libsmb/smbencrypt.c +++ b/source3/libsmb/smbencrypt.c @@ -29,8 +29,9 @@ extern int DEBUGLEVEL; /* 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 *passwd, uchar *c8, uchar *p24) + encrypted password into p24 + */ +void SMBencrypt(uchar *passwd, uchar *c8, uchar p24[24]) { uchar p14[15], p21[21]; @@ -97,9 +98,19 @@ void E_md4hash(uchar *passwd, uchar *p16) mdfour(p16, (unsigned char *)wpwd, len); } -/* Does the NT MD4 hash then des encryption. */ +/* Does the des encryption from the NT or LM MD4 hash. */ +void SMBOWFencrypt(char passwd[16], uchar *c8, uchar p24[24]) +{ + uchar p21[21]; + + memset(p21,'\0',21); -void SMBNTencrypt(uchar *passwd, uchar *c8, uchar *p24) + memcpy(p21, passwd, sizeof(passwd)); + E_P24(p21, c8, p24); +} + +/* Does the NT MD4 hash then des encryption. */ +void SMBNTencrypt(uchar *passwd, uchar *c8, uchar p24[24]) { uchar p21[21]; @@ -110,8 +121,7 @@ void SMBNTencrypt(uchar *passwd, uchar *c8, uchar *p24) } /* Does both the NT and LM owfs of a user's password */ - -void nt_lm_owf_gen(char *pwd, char *nt_p16, char *p16) +void nt_lm_owf_gen(char *pwd, char nt_p16[16], char p16[16]) { char passwd[130]; StrnCpy(passwd, pwd, sizeof(passwd)-1); diff --git a/source3/libsmb/smberr.c b/source3/libsmb/smberr.c index 5149568c04..35cd0bf88f 100644 --- a/source3/libsmb/smberr.c +++ b/source3/libsmb/smberr.c @@ -151,9 +151,28 @@ return a SMB error string from a SMB buffer char *smb_errstr(char *inbuf) { static pstring ret; + int i,j; + BOOL nt_errors = (SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES) == FLAGS2_32_BIT_ERROR_CODES; + + if (nt_errors) + { + char *nt_errstr = NULL; + uint32 nt_err = IVAL(inbuf, smb_rcls); + uint16 nt_num = nt_err & 0x0000ffff; + uint16 class = (nt_err & 0xffff0000) >> 16; + + /* maybe lookup the error message in the nt error codes... */ + if ((nt_errstr = get_nt_error_msg(nt_num)) != NULL) + { + sprintf(ret,"NT Error: (%4x, %s)", class, nt_errstr); + return ret; + } + sprintf(ret,"NT Error: Unknown error (%4x %4x)", class, nt_num); + } + else + { 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) @@ -176,7 +195,8 @@ char *smb_errstr(char *inbuf) sprintf(ret,"%s - %d",err_classes[i].class,num); return ret; } - - sprintf(ret,"Error: Unknown error (%d,%d)",class,num); + sprintf(ret,"Error: Unknown error (%4x,%d)", class, num); + } + return(ret); } diff --git a/source3/nmbsync.c b/source3/nmbsync.c index c1db37ff5c..7fc422d254 100644 --- a/source3/nmbsync.c +++ b/source3/nmbsync.c @@ -77,7 +77,8 @@ void sync_browse_lists(struct subnet_record *d, struct work_record *work, DEBUG(1,("Failed to start browse sync with %s\n", name)); } - if (!cli_session_request(&cli, name, nm_type, local_machine)) { + if (!cli_session_request(&cli, name, nm_type, local_machine, 0x0)) + { DEBUG(1,("%s rejected the browse sync session\n",name)); cli_shutdown(&cli); return; diff --git a/source3/passdb/smbpass.c b/source3/passdb/smbpass.c index cc0e1fd26d..e74a8f7610 100644 --- a/source3/passdb/smbpass.c +++ b/source3/passdb/smbpass.c @@ -508,7 +508,7 @@ Error was %s\n", } sprintf(new_entry, "%s:%u:", pwd->smb_name, (unsigned)pwd->smb_userid); - p = &new_entry[strlen(new_entry)]; + p = (unsigned char*)(&new_entry[strlen(new_entry)]); for( i = 0; i < 16; i++) { diff --git a/source3/pwd_validate.c b/source3/pwd_validate.c new file mode 100644 index 0000000000..2eefa1e5f0 --- /dev/null +++ b/source3/pwd_validate.c @@ -0,0 +1,276 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Password and authentication handling + Copyright (C) Andrew Tridgell 1992-1997 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +extern int DEBUGLEVEL; +extern int Protocol; + + +/**************************************************************************** +initiates a connection to a user-level server. +****************************************************************************/ +BOOL server_connect_init(struct cli_state *clnt, char my_netbios_name[16], + struct in_addr dest_ip, char *desthost) +{ + DEBUG(5,("password server connection requested: %s [%s]\n", + desthost, inet_ntoa(dest_ip))); + + if (clnt == NULL || !clnt->initialised) + { + DEBUG(1,("password server client state not initialised\n", desthost)); + return(False); + } + + if (!cli_connect(clnt, desthost, &dest_ip)) + { + DEBUG(3,("connected to password server %s\n", desthost)); + return False; + } + + if (!cli_session_request(clnt, desthost, 0x20, my_netbios_name, 0x0)) + { + DEBUG(1,("%s rejected the session\n", desthost)); + return False; + } + + DEBUG(3,("got session\n")); + + if (!cli_negprot(clnt)) + { + DEBUG(1,("%s rejected the negprot\n", desthost)); + return False; + } + + if (clnt->protocol < PROTOCOL_LANMAN2 || !(clnt->sec_mode & 1)) + { + DEBUG(1,("%s isn't in user level security mode\n", desthost)); + return False; + } + + DEBUG(3,("password server OK\n")); + + return True; +} + +/**************************************************************************** +support for server level security +****************************************************************************/ +BOOL server_cryptkey(struct cli_state *clnt, char my_netbios_name[16]) +{ + fstring desthost; + struct in_addr dest_ip; + char *p; + BOOL connection_found = False; + + if (clnt == NULL || !cli_initialise(clnt)) + { + DEBUG(1,("server_cryptkey: failed to initialise client state\n")); + return False; + } + + for (p = strtok(lp_passwordserver(),LIST_SEP); p && !connection_found; p = strtok(NULL,LIST_SEP)) + { + fstrcpy(desthost,p); + standard_sub_basic(desthost); + strupper(desthost); + + dest_ip = *interpret_addr2(desthost); + + if (zero_ip(dest_ip)) + { + DEBUG(1,("Can't resolve address for %s\n",p)); + continue; + } + + if (ismyip(dest_ip)) + { + DEBUG(1,("Password server loop - disabling password server %s\n", p)); + continue; + } + + connection_found = server_connect_init(clnt, my_netbios_name, dest_ip, desthost); + } + + if (!p && !connection_found) + { + DEBUG(1,("password server not available\n")); + cli_shutdown(clnt); + return False; + } + + DEBUG(3,("password server OK\n")); + + return True; +} + +/**************************************************************************** +validate a password +****************************************************************************/ +BOOL server_validate2(struct cli_state *clnt, char *user, char *domain, + char *pass, int passlen, + char *ntpass, int ntpasslen) +{ + BOOL pwd_ok = False; + + DEBUG(4,("server_validate2: user:[%s] domain:[%s]\n", user, domain)); + + if (clnt == NULL) + { + DEBUG(1,("server_validate2: NULL client_state. cannot validate\n")); + return(False); + } + + if (pass == NULL && ntpass == NULL) + { + DEBUG(1,("server_validate2: both lm and nt passwords are NULL. cannot validate\n")); + return(False); + } + + if (!clnt->initialised) + { + DEBUG(1,("server %s is not connected\n", clnt->full_dest_host_name)); + return(False); + } + + if (!cli_session_setup(clnt, user, pass, passlen, ntpass, ntpasslen, domain)) { + DEBUG(1,("server %s rejected the password\n", clnt->full_dest_host_name)); + return False; + } + + /* if logged in as guest then reject */ + if ((SVAL(clnt->inbuf,smb_vwv2) & 1) != 0) { + DEBUG(1,("server %s gave us guest only\n", clnt->full_dest_host_name)); + return(False); + } + + pwd_ok = False; + + if (!pwd_ok) + { + pwd_ok = pass != NULL && !cli_send_tconX(clnt, "IPC$", "IPC", pass, passlen); + } + + if (!pwd_ok) + { + DEBUG(1,("server %s refused IPC$ connect with LM password\n", clnt->full_dest_host_name)); + } + + if (!pwd_ok) + { + pwd_ok = ntpass != NULL && !cli_send_tconX(clnt, "IPC$", "IPC", ntpass, ntpasslen); + } + + if (!pwd_ok) + { + DEBUG(1,("server %s refused IPC$ connect with NT password\n", clnt->full_dest_host_name)); + return False; + } + + if (!pwd_ok) + { + DEBUG(3,("server %s rejected the password\n", clnt->full_dest_host_name)); + } + else + { + DEBUG(3,("server %s accepted the password\n", clnt->full_dest_host_name)); + } + + cli_tdis(clnt); + + return(True); +} + + +/**************************************************************************** +validate a password with the password server. here's some good code to go +into an SMB pam, by the way... +****************************************************************************/ +BOOL server_validate(struct cli_state *clnt, char *user, char *domain, + char *pass, int passlen, + char *ntpass, int ntpasslen) +{ + if (clnt == NULL) + { + DEBUG(1,("server_validate: NULL client_state. cannot validate\n")); + return(False); + } + + if (!clnt->initialised) { + DEBUG(1,("password server %s is not connected\n", clnt->full_dest_host_name)); + return(False); + } + + if (!cli_session_setup(clnt, user, pass, passlen, ntpass, ntpasslen, domain)) { + DEBUG(1,("password server %s rejected the password\n", clnt->full_dest_host_name)); + return False; + } + + /* if logged in as guest then reject */ + if ((SVAL(clnt->inbuf,smb_vwv2) & 1) != 0) { + DEBUG(1,("password server %s gave us guest only\n", clnt->full_dest_host_name)); + return(False); + } + + + if (!cli_send_tconX(clnt, "IPC$", "IPC", "", 1)) + { + DEBUG(1,("password server %s refused IPC$ connect\n", clnt->full_dest_host_name)); + return False; + } + + + if (!cli_send_tconX(clnt, "IPC$", "IPC", "", 1)) { + DEBUG(1,("password server %s refused IPC$ connect\n", clnt->full_dest_host_name)); + return False; + } + + + if (!cli_NetWkstaUserLogon(clnt, user, clnt->called_netbios_name)) + { + DEBUG(1,("password server %s failed NetWkstaUserLogon\n", clnt->full_dest_host_name)); + cli_tdis(clnt); + return False; + } + + if (clnt->privileges == 0) + { + DEBUG(1,("password server %s gave guest privilages\n", clnt->full_dest_host_name)); + cli_tdis(clnt); + return False; + } + + if (!strequal(clnt->eff_name, user)) { + DEBUG(1,("password server %s gave different username %s\n", + clnt->full_dest_host_name, + clnt->eff_name)); + cli_tdis(clnt); + return False; + } + + DEBUG(3,("password server %s accepted the password\n", clnt->full_dest_host_name)); + + cli_tdis(clnt); + + return(True); +} + + diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 185fc68f5a..7dd2133406 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -21,7 +21,7 @@ #include "includes.h" -#if (defined(NETGROUP) && defined (AUTOMOUNT)) +#ifdef NETGROUP #include "rpcsvc/ypclnt.h" #endif @@ -1475,141 +1475,3 @@ BOOL check_hosts_equiv(char *user) return(False); } - -static struct cli_state cli; - -/**************************************************************************** -return the client state structure -****************************************************************************/ -struct cli_state *server_client(void) -{ - return &cli; -} - -/**************************************************************************** -support for server level security -****************************************************************************/ -struct cli_state *server_cryptkey(void) -{ - fstring desthost; - struct in_addr dest_ip; - extern fstring local_machine; - char *p; - - if (!cli_initialise(&cli)) - return NULL; - - for (p=strtok(lp_passwordserver(),LIST_SEP); p ; p = strtok(NULL,LIST_SEP)) { - fstrcpy(desthost,p); - standard_sub_basic(desthost); - strupper(desthost); - - dest_ip = *interpret_addr2(desthost); - if (zero_ip(dest_ip)) { - DEBUG(1,("Can't resolve address for %s\n",p)); - continue; - } - - if (ismyip(dest_ip)) { - DEBUG(1,("Password server loop - disabling password server %s\n",p)); - continue; - } - - if (cli_connect(&cli, desthost, &dest_ip)) { - DEBUG(3,("connected to password server %s\n",p)); - break; - } - } - - if (!p) { - DEBUG(1,("password server not available\n")); - cli_shutdown(&cli); - return NULL; - } - - if (!cli_session_request(&cli, desthost, 0x20, local_machine)) { - DEBUG(1,("%s rejected the session\n",desthost)); - cli_shutdown(&cli); - return NULL; - } - - DEBUG(3,("got session\n")); - - if (!cli_negprot(&cli)) { - DEBUG(1,("%s rejected the negprot\n",desthost)); - cli_shutdown(&cli); - return NULL; - } - - if (cli.protocol < PROTOCOL_LANMAN2 || - !(cli.sec_mode & 1)) { - DEBUG(1,("%s isn't in user level security mode\n",desthost)); - cli_shutdown(&cli); - return NULL; - } - - DEBUG(3,("password server OK\n")); - - return &cli; -} - -/**************************************************************************** -validate a password with the password server -****************************************************************************/ -BOOL server_validate(char *user, char *domain, - char *pass, int passlen, - char *ntpass, int ntpasslen) -{ - extern fstring local_machine; - - if (!cli.initialised) { - DEBUG(1,("password server %s is not connected\n", cli.desthost)); - return(False); - } - - if (!cli_session_setup(&cli, user, pass, passlen, ntpass, ntpasslen, domain)) { - DEBUG(1,("password server %s rejected the password\n", cli.desthost)); - return False; - } - - /* if logged in as guest then reject */ - if ((SVAL(cli.inbuf,smb_vwv2) & 1) != 0) { - DEBUG(1,("password server %s gave us guest only\n", cli.desthost)); - return(False); - } - - - if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) { - DEBUG(1,("password server %s refused IPC$ connect\n", cli.desthost)); - return False; - } - - - if (!cli_NetWkstaUserLogon(&cli,user,local_machine)) { - DEBUG(1,("password server %s failed NetWkstaUserLogon\n", cli.desthost)); - cli_tdis(&cli); - return False; - } - - if (cli.privilages == 0) { - DEBUG(1,("password server %s gave guest privilages\n", cli.desthost)); - cli_tdis(&cli); - return False; - } - - if (!strequal(cli.eff_name, user)) { - DEBUG(1,("password server %s gave different username %s\n", - cli.desthost, - cli.eff_name)); - cli_tdis(&cli); - return False; - } - - DEBUG(3,("password server %s accepted the password\n", cli.desthost)); - - cli_tdis(&cli); - - return(True); -} - - diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 78dad6f02f..532fc583c2 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -395,6 +395,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) static BOOL done_sesssetup = False; BOOL doencrypt = SMBENCRYPT(); char *domain = ""; + struct cli_state *pwd_srv = NULL; *smb_apasswd = 0; *smb_ntpasswd = 0; @@ -518,19 +519,17 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (!smb_pass) { /* lkclXXXX: if workstation entry doesn't exist, indicate logon failure */ - DEBUG(4,("Workstation trust account %s doesn't exist.",user)); - SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */ - CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */ - return(ERROR(NT_STATUS_LOGON_FAILURE, 0xc000)); /* decimal 109 NT error, 0xc000 */ + DEBUG(4,("Workstation trust account %s doesn't exist\n",user)); + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); /* PAXX: Someone please unhack this */ + return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); /* decimal 109; critical NT error */ } else { /* PAXX: This is the NO LOGON workstation trust account stuff */ /* lkclXXXX: if the workstation *does* exist, indicate failure differently! */ - DEBUG(4,("No Workstation trust account %s",user)); - SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */ - CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */ - return(ERROR(NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT, 0xc000)); /* decimal 409 NT error, 0xc000 */ + DEBUG(4,("No Workstation trust account %s\n",user)); + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); /* PAXX: Someone please unhack this */ + return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)); /* decimal 409; critical NT error */ } computer_id = True; @@ -563,43 +562,59 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) */ if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0)) + { guest = True; + } - if (!guest && !(lp_security() == SEC_SERVER && - server_validate(user, domain, - smb_apasswd, smb_apasslen, - smb_ntpasswd, smb_ntpasslen)) && - !check_hosts_equiv(user)) - { - - /* now check if it's a valid username/password */ - /* If an NT password was supplied try and validate with that - first. This is superior as the passwords are mixed case - 128 length unicode */ - if(smb_ntpasslen) - { - if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL)) - DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n")); - else - valid_nt_password = True; - } - if (!valid_nt_password && !password_ok(user,smb_apasswd,smb_apasslen,NULL)) + if (!guest && !(lp_security() == SEC_SERVER && + ((pwd_srv = pwd_server_connection()) != NULL) && + server_validate(pwd_srv, user, domain, + smb_apasswd, smb_apasslen, + smb_ntpasswd, smb_ntpasslen)) && + !check_hosts_equiv(user)) { - if (!computer_id && lp_security() >= SEC_USER) { + + /* now check if it's a valid username/password */ + /* If an NT password was supplied try and validate with that + first. This is superior as the passwords are mixed case + 128 length unicode */ + + if (smb_ntpasslen) + { + /* check the NT password, if there is one. */ + if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL)) + { + DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n")); + } + else + { + valid_nt_password = True; + } + } + + /* check the LM password instead */ + if (!valid_nt_password && !password_ok(user,smb_apasswd,smb_apasslen,NULL)) + { + if (!computer_id && lp_security() >= SEC_USER) + { #if (GUEST_SESSSETUP == 0) - return(ERROR(ERRSRV,ERRbadpw)); + return(ERROR(ERRSRV,ERRbadpw)); #endif #if (GUEST_SESSSETUP == 1) - if (Get_Pwnam(user,True)) - return(ERROR(ERRSRV,ERRbadpw)); + if (Get_Pwnam(user,True)) + return(ERROR(ERRSRV,ERRbadpw)); #endif - } - if (*smb_apasswd || !Get_Pwnam(user,True)) - strcpy(user,lp_guestaccount(-1)); - DEBUG(3,("Registered username %s for guest access\n",user)); - guest = True; + } + + /* no lm or nt password specified: username doesn't exist. allow guest access */ + if (*smb_apasswd || !Get_Pwnam(user,True)) + { + strcpy(user, lp_guestaccount(-1)); + DEBUG(3,("Registered username %s for guest access\n",user)); + guest = True; + } + } } - } if (!Get_Pwnam(user,True)) { DEBUG(3,("No such user %s - using guest account\n",user)); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 908cf984b8..a42b4deea2 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -25,6 +25,7 @@ pstring servicesf = CONFIGFILE; extern pstring debugf; extern pstring sesssetup_user; +extern pstring local_machine; extern fstring myworkgroup; char *InBuffer = NULL; @@ -114,6 +115,21 @@ static int find_free_connection(int hash); #define IS_DOS_SYSTEM(test_mode) (((test_mode) & aSYSTEM) != 0) #define IS_DOS_HIDDEN(test_mode) (((test_mode) & aHIDDEN) != 0) +/* use this to validate user against a password server. "security = server" */ +static struct cli_state pwd_srv; + +/**************************************************************************** + for use in reply.c, to access the password server connection. +****************************************************************************/ +struct cli_state *pwd_server_connection(void) +{ + if (pwd_srv.initialised) + { + return &pwd_srv; + } + return NULL; +} + /**************************************************************************** when exiting, take the whole family ****************************************************************************/ @@ -2257,21 +2273,30 @@ int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int { int outsize = set_message(outbuf,0,0,True); int cmd; - cmd = CVAL(inbuf,smb_com); - - CVAL(outbuf,smb_rcls) = error_class; - SSVAL(outbuf,smb_err,error_code); + int flgs2; + cmd = CVAL(inbuf,smb_com); + flgs2 = SVAL(outbuf,smb_flg2); - DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n", - timestring(), - line, - (int)CVAL(inbuf,smb_com), - smb_fn_name(CVAL(inbuf,smb_com)), - error_class, - error_code)); + if ((flgs2 & FLAGS2_32_BIT_ERROR_CODES) == FLAGS2_32_BIT_ERROR_CODES) + { + SIVAL(outbuf,smb_rcls,error_code); + + DEBUG(3,("%s 32 bit error packet at line %d cmd=%d (%s) eclass=%08x [%s]\n", + timestring(), line, cmd, smb_fn_name(cmd), error_code, smb_errstr(outbuf))); + } + else + { + CVAL(outbuf,smb_rcls) = error_class; + SSVAL(outbuf,smb_err,error_code); + DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n", + timestring(), line, cmd, smb_fn_name(cmd), error_class, error_code)); + } + if (errno != 0) - DEBUG(3,("error string = %s\n",strerror(errno))); + { + DEBUG(3,("error string = %s\n", strerror(errno))); + } return(outsize); } @@ -2328,12 +2353,13 @@ static int sig_cld() **************************************************************************/ static int sig_pipe() { - struct cli_state *cli; BlockSignals(True,SIGPIPE); - if ((cli = server_client()) && cli->initialised) { + if (pwd_srv.initialised) + { DEBUG(3,("lost connection to password server\n")); - cli_shutdown(cli); + cli_shutdown(&pwd_srv); + #ifndef DONT_REINSTALL_SIG signal(SIGPIPE, SIGNAL_CAST sig_pipe); #endif @@ -3684,29 +3710,27 @@ int reply_lanman2(char *outbuf) int secword=0; BOOL doencrypt = SMBENCRYPT(); time_t t = time(NULL); - struct cli_state *cli = NULL; char cryptkey[8]; char crypt_len = 0; - if (lp_security() == SEC_SERVER) { - cli = server_cryptkey(); - } - - if (cli) { + if (lp_security() == SEC_SERVER && server_cryptkey(&pwd_srv, local_machine)) + { DEBUG(3,("using password server validation\n")); - doencrypt = ((cli->sec_mode & 2) != 0); + doencrypt = ((pwd_srv.sec_mode & 2) != 0); } if (lp_security()>=SEC_USER) secword |= 1; if (doencrypt) secword |= 2; - if (doencrypt) { + if (doencrypt) + { crypt_len = 8; - if (!cli) { + if (pwd_srv.initialised) + { generate_next_challenge(cryptkey); } else { - memcpy(cryptkey, cli->cryptkey, 8); - set_challenge(cli->cryptkey); + memcpy(cryptkey, pwd_srv.cryptkey, 8); + set_challenge(pwd_srv.cryptkey); } } @@ -3751,16 +3775,14 @@ int reply_nt1(char *outbuf) char cryptkey[8]; char crypt_len = 0; - if (lp_security() == SEC_SERVER) { - cli = server_cryptkey(); - } - - if (cli) { + if (lp_security() == SEC_SERVER && server_cryptkey(&pwd_srv, local_machine)) + { DEBUG(3,("using password server validation\n")); - doencrypt = ((cli->sec_mode & 2) != 0); + doencrypt = ((pwd_srv.sec_mode & 2) != 0); } - if (doencrypt) { + if (doencrypt) + { crypt_len = 8; if (!cli) { generate_next_challenge(cryptkey); @@ -4862,15 +4884,14 @@ static void process(void) if (keepalive && (counter-last_keepalive)>keepalive) { - struct cli_state *cli = server_client(); if (!send_keepalive(Client)) { DEBUG(2,("%s Keepalive failed - exiting\n",timestring())); return; } /* also send a keepalive to the password server if its still connected */ - if (cli && cli->initialised) - send_keepalive(cli->fd); + if (pwd_srv.initialised) + send_keepalive(pwd_srv.fd); last_keepalive = counter; } diff --git a/source3/utils/torture.c b/source3/utils/torture.c index 506f31481c..a0e32ff395 100644 --- a/source3/utils/torture.c +++ b/source3/utils/torture.c @@ -46,12 +46,14 @@ static double end_timer() static BOOL open_connection(struct cli_state *c) { - if (!cli_initialise(c) || !cli_connect(c, host, NULL)) { + if (!cli_initialise(c) || !cli_connect(c, host, NULL)) + { printf("Failed to connect with %s\n", host); return False; } - if (!cli_session_request(c, host, 0x20, myname)) { + if (!cli_session_request(c, host, 0x20, myname, 0x0)) + { printf("%s rejected the session\n",host); cli_shutdown(c); return False; -- cgit