summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>1998-11-26 03:03:09 +0000
committerJeremy Allison <jra@samba.org>1998-11-26 03:03:09 +0000
commit2113d7f440a5b6940962059b8a04a52490c2f769 (patch)
tree18c82e2c91942c3a912b8a3d8c8321809d17cdef
parent4c0e765b10d8085c1ee2e417ac5d4eaf1b655b57 (diff)
downloadsamba-2113d7f440a5b6940962059b8a04a52490c2f769.tar.gz
I have done the evil thing :-).
I have added the 'crap applience' mode code to the 2.0 branch. This allows smbd in security=server or security=domain mode to create a UNIX user on the fly if the password server accepts them but there is no local UNIX user. It uses two new parameters add user script delete user script and replaces %u with the username. Note that I have violated my own rules by not yet documenting this :-). But I intend to, after some more testing. It seems ok - but needs more testing. Jeremy.
-rw-r--r--source/include/proto.h7
-rw-r--r--source/libsmb/clientgen.c28
-rw-r--r--source/param/loadparm.c6
-rw-r--r--source/rpc_client/cli_pipe.c4
-rw-r--r--source/rpc_client/ntclienttrust.c4
-rw-r--r--source/smbd/password.c13
-rw-r--r--source/smbd/reply.c90
-rw-r--r--source/smbwrapper/smbw.c2
-rw-r--r--source/utils/torture.c2
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",