diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/include/proto.h | 7 | ||||
-rw-r--r-- | source/libsmb/clientgen.c | 28 | ||||
-rw-r--r-- | source/param/loadparm.c | 6 | ||||
-rw-r--r-- | source/rpc_client/cli_pipe.c | 4 | ||||
-rw-r--r-- | source/rpc_client/ntclienttrust.c | 4 | ||||
-rw-r--r-- | source/smbd/password.c | 13 | ||||
-rw-r--r-- | source/smbd/reply.c | 90 | ||||
-rw-r--r-- | source/smbwrapper/smbw.c | 2 | ||||
-rw-r--r-- | source/utils/torture.c | 2 |
9 files changed, 127 insertions, 29 deletions
diff --git a/source/include/proto.h b/source/include/proto.h index 4848c5e70fb..d69f715f0ec 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -458,7 +458,7 @@ BOOL cli_session_request(struct cli_state *cli, BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip); struct cli_state *cli_initialise(struct cli_state *cli); void cli_shutdown(struct cli_state *cli); -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); void cli_sockopt(struct cli_state *cli, char *options); uint16 cli_setpid(struct cli_state *cli, uint16 pid); BOOL cli_reestablish_connection(struct cli_state *cli); @@ -980,6 +980,8 @@ char *lp_nis_home_map_name(void); char *lp_netbios_aliases(void); char *lp_driverfile(void); char *lp_panic_action(void); +char *lp_adduser_script(void); +char *lp_deluser_script(void); char *lp_domain_groups(void); char *lp_domain_admin_group(void); char *lp_domain_guest_group(void); @@ -2466,7 +2468,8 @@ BOOL server_validate(char *user, char *domain, char *ntpass, int ntpasslen); BOOL domain_client_validate( char *user, char *domain, char *smb_apasswd, int smb_apasslen, - char *smb_ntpasswd, int smb_ntpasslen); + char *smb_ntpasswd, int smb_ntpasslen, + BOOL *user_exists); /*The following definitions come from smbd/pipes.c */ diff --git a/source/libsmb/clientgen.c b/source/libsmb/clientgen.c index 550f7cc391d..c9d221bd337 100644 --- a/source/libsmb/clientgen.c +++ b/source/libsmb/clientgen.c @@ -108,6 +108,7 @@ char *cli_errstr(struct cli_state *cli) static fstring error_message; uint8 errclass; uint32 errnum; + uint32 nt_rpc_error; int i; /* @@ -117,7 +118,7 @@ char *cli_errstr(struct cli_state *cli) * 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) { @@ -128,13 +129,13 @@ char *cli_errstr(struct cli_state *cli) * Was it an NT error ? */ - if (cli->nt_error) + if (nt_rpc_error) { - char *nt_msg = get_nt_error_msg(cli->nt_error); + char *nt_msg = get_nt_error_msg(nt_rpc_error); if (nt_msg == NULL) { - slprintf(error_message, sizeof(fstring) - 1, "NT code %d", cli->nt_error); + slprintf(error_message, sizeof(fstring) - 1, "NT code %d", nt_rpc_error); } else { @@ -338,7 +339,7 @@ static BOOL cli_receive_trans(struct cli_state *cli,int trans, return(False); } - if (cli_error(cli, NULL, NULL)) + if (cli_error(cli, NULL, NULL, NULL)) { return(False); } @@ -391,7 +392,7 @@ 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, NULL, NULL, NULL)) { return(False); } @@ -1650,7 +1651,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); } @@ -2013,7 +2014,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; @@ -2427,7 +2428,7 @@ 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 = SVAL(cli->inbuf,smb_flg2); char rcls; @@ -2435,6 +2436,7 @@ int cli_error(struct cli_state *cli, uint8 *eclass, uint32 *num) 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) { /* 32 bit error codes detected */ @@ -2831,7 +2833,7 @@ BOOL cli_chkpath(struct cli_state *cli, char *path) return False; } - if (cli_error(cli, NULL, NULL)) return False; + if (cli_error(cli, NULL, NULL, NULL)) return False; return True; } @@ -2868,7 +2870,7 @@ BOOL cli_message_start(struct cli_state *cli, char *host, char *username, 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); @@ -2901,7 +2903,7 @@ BOOL cli_message_text(struct cli_state *cli, char *msg, int len, int grp) return False; } - if (cli_error(cli, NULL, NULL)) return False; + if (cli_error(cli, NULL, NULL, NULL)) return False; return True; } @@ -2926,7 +2928,7 @@ BOOL cli_message_end(struct cli_state *cli, int grp) return False; } - if (cli_error(cli, NULL, NULL)) return False; + if (cli_error(cli, NULL, NULL, NULL)) return False; return True; } diff --git a/source/param/loadparm.c b/source/param/loadparm.c index 8b351168586..6f270eb0f55 100644 --- a/source/param/loadparm.c +++ b/source/param/loadparm.c @@ -155,6 +155,8 @@ typedef struct char *szLdapRoot; char *szLdapRootPassword; char *szPanicAction; + char *szAddUserScript; + char *szDelUserScript; int max_log_size; int mangled_stack; int max_xmit; @@ -691,6 +693,8 @@ static struct parm_struct parm_table[] = {"machine password timeout", P_INTEGER, P_GLOBAL, &Globals.machine_password_timeout, NULL, NULL, 0}, {"Logon Options", P_SEP, P_SEPARATOR}, + {"add user script", P_STRING, P_GLOBAL, &Globals.szAddUserScript, NULL, NULL, 0}, + {"delete user script",P_STRING, P_GLOBAL, &Globals.szDelUserScript, NULL, NULL, 0}, {"logon script", P_STRING, P_GLOBAL, &Globals.szLogonScript, NULL, NULL, 0}, {"logon path", P_STRING, P_GLOBAL, &Globals.szLogonPath, NULL, NULL, 0}, {"logon drive", P_STRING, P_GLOBAL, &Globals.szLogonDrive, NULL, NULL, 0}, @@ -1124,6 +1128,8 @@ static FN_GLOBAL_STRING(lp_announce_version,&Globals.szAnnounceVersion) FN_GLOBAL_STRING(lp_netbios_aliases,&Globals.szNetbiosAliases) FN_GLOBAL_STRING(lp_driverfile,&Globals.szDriverFile) FN_GLOBAL_STRING(lp_panic_action,&Globals.szPanicAction) +FN_GLOBAL_STRING(lp_adduser_script,&Globals.szAddUserScript) +FN_GLOBAL_STRING(lp_deluser_script,&Globals.szDelUserScript) FN_GLOBAL_STRING(lp_domain_groups,&Globals.szDomainGroups) FN_GLOBAL_STRING(lp_domain_admin_group,&Globals.szDomainAdminGroup) diff --git a/source/rpc_client/cli_pipe.c b/source/rpc_client/cli_pipe.c index 579eeebdac1..a9e0449c950 100644 --- a/source/rpc_client/cli_pipe.c +++ b/source/rpc_client/cli_pipe.c @@ -93,7 +93,7 @@ static BOOL rpc_read(struct cli_state *cli, file_offset += num_read; data += num_read; - if (cli_error(cli, NULL, &err)) return False; + if (cli_error(cli, NULL, &err, NULL)) return False; } while (num_read > 0 && data_to_read > 0); /* && err == (0x80000000 | STATUS_BUFFER_OVERFLOW)); */ @@ -378,7 +378,7 @@ static BOOL rpc_api_pipe(struct cli_state *cli, uint16 cmd, prs_mem_free(&hps); - if (cli_error(cli, NULL, &err)) return False; + if (cli_error(cli, NULL, &err, NULL)) return False; if (first) { diff --git a/source/rpc_client/ntclienttrust.c b/source/rpc_client/ntclienttrust.c index 04860171817..e55d325294f 100644 --- a/source/rpc_client/ntclienttrust.c +++ b/source/rpc_client/ntclienttrust.c @@ -93,7 +93,7 @@ BOOL trust_account_check(struct in_addr dest_ip, char *dest_host, if (!server_connect_init(&cli_trust, myhostname, dest_ip, dest_host)) { - cli_error(&cli_trust, &err_cls, &err_num); + cli_error(&cli_trust, &err_cls, &err_num, NULL); DEBUG(1,("server_connect_init failed (%s)\n", cli_errstr(&cli_trust))); cli_shutdown(&cli_trust); @@ -141,7 +141,7 @@ BOOL trust_account_check(struct in_addr dest_ip, char *dest_host, return False; } - cli_error(&cli_trust, &err_cls, &err_num); + cli_error(&cli_trust, &err_cls, &err_num, NULL); if (err_num == (0xC0000000 | NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)) { diff --git a/source/smbd/password.c b/source/smbd/password.c index 0ff498737d2..50a0ebd79e0 100644 --- a/source/smbd/password.c +++ b/source/smbd/password.c @@ -1142,7 +1142,8 @@ use this machine as the password server.\n")); BOOL domain_client_validate( char *user, char *domain, char *smb_apasswd, int smb_apasslen, - char *smb_ntpasswd, int smb_ntpasslen) + char *smb_ntpasswd, int smb_ntpasslen, + BOOL *user_exists) { unsigned char local_challenge[8]; unsigned char local_lm_response[24]; @@ -1158,6 +1159,9 @@ BOOL domain_client_validate( char *user, char *domain, BOOL connected_ok = False; struct nmb_name calling, called; + if(user_exists != NULL) + *user_exists = True; /* Only set false on a very specific error. */ + /* * Check that the requested domain is not our own machine name. * If it is, we should never check the PDC here, we use our own local @@ -1346,11 +1350,18 @@ machine %s. Error was : %s.\n", remote_machine, cli_errstr(&cli))); ((smb_apasslen != 0) ? smb_apasswd : NULL), ((smb_ntpasslen != 0) ? smb_ntpasswd : NULL), &ctr, &info3) == False) { + uint32 nt_rpc_err; + + cli_error(&cli, NULL, NULL, &nt_rpc_err); DEBUG(0,("domain_client_validate: unable to validate password for user %s in domain \ %s to Domain controller %s. Error was %s.\n", user, domain, remote_machine, cli_errstr(&cli))); cli_nt_session_close(&cli); cli_ulogoff(&cli); cli_shutdown(&cli); + + if((nt_rpc_err == NT_STATUS_NO_SUCH_USER) && (user_exists != NULL)) + *user_exists = False; + return False; } diff --git a/source/smbd/reply.c b/source/smbd/reply.c index 69894d4cb10..f61b89f8ddb 100644 --- a/source/smbd/reply.c +++ b/source/smbd/reply.c @@ -448,35 +448,111 @@ static int session_trust_account(connection_struct *conn, char *inbuf, char *out } /**************************************************************************** + Create a UNIX user on demand. +****************************************************************************/ + +static int smb_create_user(char *unix_user) +{ + pstring add_script; + int ret; + + pstrcpy(add_script, lp_adduser_script()); + string_sub(add_script, "%u", unix_user); + ret = smbrun(add_script,NULL,False); + DEBUG(3,("smb_create_user: Running the command `%s' gave %d\n",add_script,ret)); + return ret; +} + +/**************************************************************************** + Delete a UNIX user on demand. +****************************************************************************/ + +static int smb_delete_user(char *unix_user) +{ + pstring del_script; + int ret; + + pstrcpy(del_script, lp_deluser_script()); + string_sub(del_script, "%u", unix_user); + ret = smbrun(del_script,NULL,False); + DEBUG(3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret)); + return ret; +} + +/**************************************************************************** Check for a valid username and password in security=server mode. ****************************************************************************/ -static BOOL check_server_security(char *orig_user, char *domain, +static BOOL check_server_security(char *orig_user, char *domain, char *unix_user, char *smb_apasswd, int smb_apasslen, char *smb_ntpasswd, int smb_ntpasslen) { + BOOL ret = False; + if(lp_security() != SEC_SERVER) return False; - return server_validate(orig_user, domain, + ret = server_validate(orig_user, domain, smb_apasswd, smb_apasslen, smb_ntpasswd, smb_ntpasslen); + if(ret) { + /* + * User validated ok against Domain controller. + * If the admin wants us to try and create a UNIX + * user on the fly, do so. + * Note that we can never delete users when in server + * level security as we never know if it was a failure + * due to a bad password, or the user really doesn't exist. + */ + if(lp_adduser_script() && !Get_Pwnam(unix_user,True)) { + smb_create_user(unix_user); + } + } + + return ret; } /**************************************************************************** Check for a valid username and password in security=domain mode. ****************************************************************************/ -static BOOL check_domain_security(char *orig_user, char *domain, +static BOOL check_domain_security(char *orig_user, char *domain, char *unix_user, char *smb_apasswd, int smb_apasslen, char *smb_ntpasswd, int smb_ntpasslen) { + BOOL ret = False; + BOOL user_exists = True; + if(lp_security() != SEC_DOMAIN) return False; - return domain_client_validate(orig_user, domain, + ret = domain_client_validate(orig_user, domain, smb_apasswd, smb_apasslen, - smb_ntpasswd, smb_ntpasslen); + smb_ntpasswd, smb_ntpasslen, + &user_exists); + + if(ret) { + /* + * User validated ok against Domain controller. + * If the admin wants us to try and create a UNIX + * user on the fly, do so. + */ + if(user_exists && lp_adduser_script() && !Get_Pwnam(unix_user,True)) { + smb_create_user(unix_user); + } + } else { + /* + * User failed to validate ok against Domain controller. + * If the failure was "user doesn't exist" and admin + * wants us to try and delete that UNIX user on the fly, + * do so. + */ + if(!user_exists && lp_deluser_script() && Get_Pwnam(unix_user,True)) { + smb_delete_user(unix_user); + } + } + + return ret; } /**************************************************************************** @@ -669,10 +745,10 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int */ if (!guest && - !check_server_security(orig_user, domain, + !check_server_security(orig_user, domain, user, smb_apasswd, smb_apasslen, smb_ntpasswd, smb_ntpasslen) && - !check_domain_security(orig_user, domain, + !check_domain_security(orig_user, domain, user, smb_apasswd, smb_apasslen, smb_ntpasswd, smb_ntpasslen) && !check_hosts_equiv(user) diff --git a/source/smbwrapper/smbw.c b/source/smbwrapper/smbw.c index faaa9f047b0..6ae6146ed22 100644 --- a/source/smbwrapper/smbw.c +++ b/source/smbwrapper/smbw.c @@ -378,7 +378,7 @@ int smbw_errno(struct cli_state *c) uint32 ecode; int ret; - ret = cli_error(c, &eclass, &ecode); + ret = cli_error(c, &eclass, &ecode, NULL); if (ret) { DEBUG(3,("smbw_error %d %d (0x%x) -> %d\n", diff --git a/source/utils/torture.c b/source/utils/torture.c index 81fa33fc750..54b42819dd8 100644 --- a/source/utils/torture.c +++ b/source/utils/torture.c @@ -107,7 +107,7 @@ static BOOL check_error(struct cli_state *c, uint8 class; uint32 num; int eno; - eno = cli_error(c, &class, &num); + eno = cli_error(c, &class, &num, NULL); if ((eclass != class || ecode != num) && num != (nterr&0xFFFFFF)) { printf("unexpected error code class=%d code=%d\n", |