1
0
mirror of https://github.com/samba-team/samba.git synced 2025-08-02 00:22:11 +03:00

the first independent msrpc daemon - lsarpcd.

one horrible cut / paste job from smbd, plus a code split of shared
components between the two.

the job is not _yet_ complete, as i need to be able to do a become_user()
call for security reasons.  i picked lsarpcd first because you don't
_need_ security on it (microsoft botched so badly on this one, it's not
real.  at least they fixed this in nt5 with restrictanonymous=0x2).
fixing this involves sending the current smb and unix credentials down
the unix pipe so that the daemon it eventually goes to can pick them
up at the other end.

i can't believe this all worked!!!
(This used to be commit 2245b0c6d1)
This commit is contained in:
Luke Leighton
1999-12-06 00:44:32 +00:00
parent 7c53f158ba
commit a0ba234cf9
18 changed files with 1904 additions and 550 deletions

View File

@ -37,6 +37,7 @@ INSTALLPERMS = 0755
# These can be overridden by command line switches (see smbd(8))
# or in smb.conf (see smb.conf(5))
SMBLOGFILE = $(VARDIR)/log.smb
LSARPCLOGFILE = $(VARDIR)/log.lsarpc
NMBLOGFILE = $(VARDIR)/log.nmb
CONFIGFILE = $(LIBDIR)/smb.conf
LMHOSTSFILE = $(LIBDIR)/lmhosts
@ -77,14 +78,21 @@ PASSWD_FLAGS = \
-DSMB_PASSGRP_FILE=\"$(SMB_PASSGRP_FILE)\" \
-DSMB_GROUP_FILE=\"$(SMB_GROUP_FILE)\" \
-DSMB_ALIAS_FILE=\"$(SMB_ALIAS_FILE)\"
FLAGS1 = $(CFLAGS) -Iinclude -I$(srcdir)/include -I$(srcdir)/ubiqx -I$(srcdir)/smbwrapper $(CPPFLAGS) -DSMBLOGFILE=\"$(SMBLOGFILE)\" -DNMBLOGFILE=\"$(NMBLOGFILE)\"
FLAGS1 = $(CFLAGS) \
-Iinclude -I$(srcdir)/include \
-I$(srcdir)/ubiqx \
-I$(srcdir)/smbwrapper \
$(CPPFLAGS) \
-DLSARPCLOGFILE=\"$(LSARPCLOGFILE)\" \
-DSMBLOGFILE=\"$(SMBLOGFILE)\" \
-DNMBLOGFILE=\"$(NMBLOGFILE)\"
FLAGS2 = -DCONFIGFILE=\"$(CONFIGFILE)\" -DLMHOSTSFILE=\"$(LMHOSTSFILE)\"
FLAGS3 = -DSWATDIR=\"$(SWATDIR)\" -DSBINDIR=\"$(SBINDIR)\" -DLOCKDIR=\"$(LOCKDIR)\" -DSMBRUN=\"$(SMBRUN)\" -DCODEPAGEDIR=\"$(CODEPAGEDIR)\"
FLAGS4 = -DDRIVERFILE=\"$(DRIVERFILE)\" -DBINDIR=\"$(BINDIR)\" -DFORMSFILE=\"$(FORMSFILE)\" -DNTDRIVERSDIR=\"$(NTDRIVERSDIR)\"
FLAGS5 = $(FLAGS1) $(FLAGS2) $(FLAGS3) $(FLAGS4) -DHAVE_INCLUDES_H
FLAGS = $(FLAGS5) $(PASSWD_FLAGS)
SPROGS = bin/smbd bin/nmbd bin/swat
SPROGS = bin/smbd bin/lsarpcd bin/nmbd bin/swat
PROGS1 = bin/smbclient bin/testparm bin/testprns bin/smbrun bin/smbstatus
PROGS2 = bin/rpcclient bin/smbpasswd bin/make_smbcodepage bin/debug2html
PROGS3 = @WRAP@ @WRAP32@
@ -107,6 +115,7 @@ LIB_OBJ = lib/charcnv.o lib/charset.o lib/debug.o lib/fault.o \
lib/membuffer.o lib/netmask.o lib/pidfile.o lib/replace.o \
lib/signal.o lib/slprintf.o lib/system.o lib/doscalls.o lib/time.o \
lib/ufc.o lib/util.o lib/genrand.o lib/username.o \
lib/vuser.o \
lib/access.o lib/smbrun.o \
lib/bitmap.o lib/crc32.o lib/util_sid.o lib/snprintf.o \
lib/util_str.o lib/util_unistr.o \
@ -114,7 +123,8 @@ LIB_OBJ = lib/charcnv.o lib/charset.o lib/debug.o lib/fault.o \
lib/util_sock.o lib/unix_sec_ctxt.o \
lib/util_array.o \
lib/vagent.o \
lib/util_hnd.o
lib/util_hnd.o \
lib/passcheck.o
UBIQX_OBJ = ubiqx/ubi_BinTree.o ubiqx/ubi_Cache.o ubiqx/ubi_SplayTree.o \
ubiqx/ubi_dLinkList.o ubiqx/ubi_sLinkList.o
@ -126,20 +136,24 @@ LIBSMB_OBJ = libsmb/clientgen.o libsmb/namequery.o libsmb/nmblib.o \
libsmb/smberr.o libsmb/credentials.o libsmb/pwd_cache.o \
libsmb/passchange.o
RPC_SERVER_OBJ = \
RPC_SRVUTIL_OBJ = \
rpc_server/srv_pipe_hnd.o \
rpc_server/srv_lookup.o \
rpc_server/srv_pipe.o
RPC_SERVER_OBJ1 = \
rpc_server/srv_lsa.o \
rpc_server/srv_netlog.o \
rpc_server/srv_pipe_hnd.o \
rpc_server/srv_reg.o \
rpc_server/srv_samr.o \
rpc_server/srv_srvsvc.o \
rpc_server/srv_svcctl.o \
rpc_server/srv_pipe.o \
rpc_server/srv_lookup.o \
rpc_server/srv_wkssvc.o \
rpc_server/srv_brs.o \
rpc_server/srv_spoolss.o
RPC_SERVER_OBJ = $(RPC_SERVER_OBJ1) $(RPC_SRVUTIL_OBJ)
RPC_PARSE_OBJ1 = rpc_parse/parse_lsa.o \
rpc_parse/parse_net.o \
rpc_parse/parse_reg.o \
@ -204,16 +218,28 @@ SMBD_OBJ1 = smbd/server.o smbd/files.o smbd/chgpasswd.o smbd/connection.o \
smbd/$(QUOTAOBJS) smbd/reply.o smbd/ssl.o smbd/trans2.o smbd/uid.o \
smbd/dosmode.o smbd/filename.o smbd/open.o smbd/close.o smbd/blocking.o \
smbd/process.o smbd/oplock.o smbd/service.o smbd/error.o smbd/vfs.o \
smbd/vfs-wrap.o printing/nt_printing.o smbd/dfs.o
smbd/vfs-wrap.o printing/nt_printing.o smbd/dfs.o \
smbd/challenge.o
PRINTING_OBJ = printing/pcap.o printing/print_svid.o printing/printing.o
LSARPCD_OBJ1 = lsarpcd/lsarpcd.o \
lsarpcd/lsarpcd_process.o \
rpc_server/srv_lsa.o \
smbd/uid.o
SMBD_OBJ = $(SMBD_OBJ1) $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) \
$(RPC_SERVER_OBJ) $(RPC_CLIENT_OBJ) $(RPC_PARSE_OBJ) \
$(LOCKING_OBJ) $(SAMPASSDB_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
$(LIBSTATUS_OBJ) $(PRINTING_OBJ) $(PROFILE_OBJ) $(LIB_OBJ)
LSARPCD_OBJ = $(LSARPCD_OBJ1) $(PARAM_OBJ) $(LIBSMB_OBJ) \
$(UBIQX_OBJ) \
$(RPC_SRVUTIL_OBJ) $(RPC_CLIENT_OBJ) $(RPC_PARSE_OBJ) \
$(LOCKING_OBJ) $(SAMPASSDB_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
$(LIBSTATUS_OBJ) $(PRINTING_OBJ) $(PROFILE_OBJ) $(LIB_OBJ)
NMBD_OBJ1 = nmbd/asyncdns.o nmbd/nmbd.o nmbd/nmbd_become_dmb.o \
nmbd/nmbd_become_lmb.o nmbd/nmbd_browserdb.o \
nmbd/nmbd_browsesync.o nmbd/nmbd_elections.o \
@ -331,7 +357,7 @@ RPCTORTURE_OBJ = utils/rpctorture.o \
$(RPC_CLIENT_OBJ) $(RPC_PARSE_OBJ) \
$(PASSDB_OBJ)
PROTO_OBJ = $(SMBD_OBJ) $(NMBD_OBJ) $(SWAT_OBJ) $(CLIENT_OBJ) \
PROTO_OBJ = $(LSARPCD_OBJ) $(SMBD_OBJ) $(NMBD_OBJ) $(SWAT_OBJ) $(CLIENT_OBJ) \
$(RPCCLIENT_OBJ) $(SMBWRAPPER_OBJ)
PICOBJS = $(SMBWRAPPER_OBJ:.o=.po)
@ -421,6 +447,10 @@ bin/smbd: $(SMBD_OBJ) bin/.dummy
@echo Linking $@
@$(CC) $(FLAGS) -o $@ $(SMBD_OBJ) $(LDFLAGS) $(LIBS)
bin/lsarpcd: $(LSARPCD_OBJ) bin/.dummy
@echo Linking $@
@$(CC) $(FLAGS) -o $@ $(LSARPCD_OBJ) $(LDFLAGS) $(LIBS)
bin/nmbd: $(NMBD_OBJ) bin/.dummy
@echo Linking $@
@$(CC) $(FLAGS) -o $@ $(NMBD_OBJ) $(LDFLAGS) $(LIBS)

View File

@ -74,6 +74,8 @@ typedef struct pipes_struct
fstring name;
fstring pipe_srv_name;
struct msrpc_state *m;
prs_struct rhdr; /* output header */
prs_struct rfault; /* fault */
prs_struct rdata; /* output data */

View File

@ -287,6 +287,8 @@ void start_msrpc_agent(char *pipe_name);
/*The following definitions come from lib/msrpc-client.c */
BOOL msrpc_receive(struct msrpc_state *msrpc);
BOOL msrpc_send_prs(struct msrpc_state *msrpc, prs_struct *ps);
BOOL msrpc_receive_prs(struct msrpc_state *msrpc, prs_struct *ps);
BOOL msrpc_send(struct msrpc_state *msrpc, BOOL show);
BOOL msrpc_connect(struct msrpc_state *msrpc, const char *pipe_name);
void msrpc_init_creds(struct msrpc_state *msrpc, const struct user_credentials *usr);
@ -317,6 +319,18 @@ void msrpc_net_use_enum(uint32 *num_cons, struct use_info ***use);
int get_netmask(struct in_addr *ipaddr, struct in_addr *nmask);
/*The following definitions come from lib/passcheck.c */
BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar challenge[8],
const char *user, const char *domain,
uchar *lm_pass, size_t lm_pwd_len,
uchar *nt_pass, size_t nt_pwd_len,
uchar sess_key[16]);
BOOL pass_check_smb(struct smb_passwd *smb_pass, char *domain, uchar *chal,
uchar *lm_pwd, size_t lm_pwd_len,
uchar *nt_pwd, size_t nt_pwd_len,
struct passwd *pwd, uchar user_sess_key[16]);
/*The following definitions come from lib/pidfile.c */
pid_t pidfile_pid(char *name);
@ -429,6 +443,7 @@ char *uidtoname(uid_t uid);
char *get_home_dir(char *user);
BOOL map_username(char *user);
const struct passwd *Get_Pwnam(char *user,BOOL allow_change);
BOOL user_ok(char *user,int snum);
BOOL user_in_list(char *user,char *list);
/*The following definitions come from lib/util.c */
@ -716,6 +731,13 @@ void init_sock_redir(struct vagent_ops*va);
void free_sock_redir(struct vagent_ops*va);
void start_agent(struct vagent_ops *va);
/*The following definitions come from lib/vuser.c */
user_struct *get_valid_user_struct(uint16 vuid);
void invalidate_vuid(uint16 vuid);
char *validated_username(uint16 vuid);
uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, BOOL guest, uchar user_sess_key[16]);
/*The following definitions come from libsmb/clientgen.c */
void copy_user_creds(struct user_credentials *to,
@ -1016,6 +1038,17 @@ struct shmem_ops *smb_shm_open(int ronly);
struct shmem_ops *sysv_shm_open(int ronly);
/*The following definitions come from lsarpcd/lsarpcd.c */
BOOL reload_services(BOOL test);
void exit_server(char *reason);
/*The following definitions come from lsarpcd/lsarpcd_process.c */
BOOL receive_next_smb(char *inbuf, int bufsize, int timeout);
void process_smb(char *inbuf, char *outbuf);
void lsarpcd_process(void);
/*The following definitions come from mem_man/mem_man.c */
void *smb_mem_malloc(size_t size,char *file,int line);
@ -2697,6 +2730,7 @@ BOOL net_io_r_sam_sync(char *desc, uint8 sess_key[16],
/*The following definitions come from rpc_parse/parse_prs.c */
void prs_debug(prs_struct *ps, int depth, char *desc, char *fn_name);
void prs_debug_out(prs_struct *ps, int level);
void prs_init(prs_struct *ps, uint32 size,
uint8 align, uint32 margin,
BOOL io);
@ -3622,6 +3656,10 @@ BOOL api_netlog_rpc(pipes_struct *p, prs_struct *data);
BOOL create_rpc_reply(pipes_struct *p,
uint32 data_start, uint32 data_end);
void close_msrpc_command_processor(void);
void add_msrpc_command_processor(char* pipe_name,
char* process_name,
BOOL (*fn) (pipes_struct *, prs_struct *));
BOOL rpc_command(pipes_struct *p, prs_struct *pd);
BOOL api_rpcTNP(pipes_struct *p, char *rpc_name, struct api_struct *api_rpc_cmds,
prs_struct *data);
@ -3977,6 +4015,12 @@ void remove_pending_lock_requests_by_fid(files_struct *fsp);
void remove_pending_lock_requests_by_mid(int mid);
void process_blocking_lock_queue(time_t t);
/*The following definitions come from smbd/challenge.c */
void generate_next_challenge(char *challenge);
BOOL set_challenge(unsigned char *challenge);
BOOL last_challenge(unsigned char *challenge);
/*The following definitions come from smbd/chgpasswd.c */
BOOL chgpasswd(char *name,char *oldpass,char *newpass, BOOL as_root);
@ -4181,25 +4225,9 @@ void check_kernel_oplocks(void);
/*The following definitions come from smbd/password.c */
void generate_next_challenge(char *challenge);
BOOL set_challenge(unsigned char *challenge);
user_struct *get_valid_user_struct(uint16 vuid);
void invalidate_vuid(uint16 vuid);
char *validated_username(uint16 vuid);
uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, BOOL guest, uchar user_sess_key[16]);
void add_session_user(char *user);
BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar chal[8],
const char *user, const char *domain,
uchar *lm_pass, size_t lm_pwd_len,
uchar *nt_pass, size_t nt_pwd_len,
uchar sess_key[16]);
BOOL pass_check_smb(struct smb_passwd *smb_pass, char *domain, uchar *chal,
uchar *lm_pwd, size_t lm_pwd_len,
uchar *nt_pwd, size_t nt_pwd_len,
struct passwd *pwd, uchar user_sess_key[16]);
BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd,
uchar user_sess_key[16]);
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);

View File

@ -254,8 +254,9 @@ void start_msrpc_agent(char *pipe_name)
0
};
CatchChild();
start_agent(&va);
if (fork() == 0)
{
start_agent(&va);
}
}

View File

@ -34,6 +34,54 @@ BOOL msrpc_receive(struct msrpc_state *msrpc)
return receive_smb(msrpc->fd,msrpc->inbuf,0);
}
/****************************************************************************
send an smb to a fd and re-establish if necessary
****************************************************************************/
BOOL msrpc_send_prs(struct msrpc_state *msrpc, prs_struct *ps)
{
size_t len = mem_buf_len(ps->data);
_smb_setlen(msrpc->outbuf, len);
mem_buf_copy(&msrpc->outbuf[4], ps->data, 0, len);
if (msrpc_send(msrpc, True))
{
prs_mem_free(ps);
return True;
}
return False;
}
/****************************************************************************
receive msrpc packet
****************************************************************************/
BOOL msrpc_receive_prs(struct msrpc_state *msrpc, prs_struct *ps)
{
int len;
char *data;
if (!msrpc_receive(msrpc))
{
return False;
}
len = smb_len(msrpc->inbuf);
dump_data(10, msrpc->inbuf, len+4);
prs_init(ps, len, 4, 0, False);
ps->offset = len;
data = mem_data(&ps->data, 0);
if (data == NULL || len <= 0)
{
return False;
}
memcpy(data, smb_base(msrpc->inbuf), len);
return True;
}
/****************************************************************************
send an smb to a fd and re-establish if necessary
****************************************************************************/
@ -62,8 +110,6 @@ BOOL msrpc_send(struct msrpc_state *msrpc, BOOL show)
return True;
}
/****************************************************************************
open the msrpcent sockets
****************************************************************************/
@ -115,7 +161,7 @@ void msrpc_sockopt(struct msrpc_state *msrpc, char *options)
}
static int msrpc_init_redirect(struct msrpc_state *msrpc,
static BOOL msrpc_init_redirect(struct msrpc_state *msrpc,
const char* pipe_name,
const struct user_credentials *usr)
{
@ -135,7 +181,7 @@ static int msrpc_init_redirect(struct msrpc_state *msrpc,
if (sock < 0)
{
return sock;
return False;
}
ZERO_STRUCT(data);
@ -196,7 +242,7 @@ static int msrpc_init_redirect(struct msrpc_state *msrpc,
msrpc->fd = sock;
msrpc->usr.reuse = False;
return sock;
return True;
}
BOOL msrpc_connect_auth(struct msrpc_state *msrpc,

289
source3/lib/passcheck.c Normal file
View File

@ -0,0 +1,289 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
Password and authentication handling
Copyright (C) Andrew Tridgell 1992-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
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;
extern pstring scope;
extern pstring global_myname;
extern fstring global_myworkgroup;
/****************************************************************************
core of smb password checking routine.
****************************************************************************/
static BOOL smb_pwd_check_ntlmv1(char *password, unsigned char *part_passwd,
unsigned char *c8,
uchar sess_key[16])
{
/* Finish the encryption of part_passwd. */
unsigned char p24[24];
if (part_passwd == NULL)
DEBUG(10,("No password set - allowing access\n"));
/* No password set - always true ! */
if (part_passwd == NULL)
return True;
SMBOWFencrypt(part_passwd, c8, p24);
if (sess_key != NULL)
{
SMBsesskeygen_ntv1(part_passwd, NULL, sess_key);
}
#if DEBUG_PASSWORD
DEBUG(100,("Part password (P16) was |"));
dump_data(100, part_passwd, 16);
DEBUG(100,("Password from client was |"));
dump_data(100, password, 24);
DEBUG(100,("Given challenge was |"));
dump_data(100, c8, 8);
DEBUG(100,("Value from encryption was |"));
dump_data(100, p24, 24);
#endif
return (memcmp(p24, password, 24) == 0);
}
/****************************************************************************
core of smb password checking routine.
****************************************************************************/
static BOOL smb_pwd_check_ntlmv2(char *password, size_t pwd_len,
unsigned char *part_passwd,
unsigned char const *c8,
const char *user, const char *domain,
char *sess_key)
{
/* Finish the encryption of part_passwd. */
unsigned char kr[16];
unsigned char resp[16];
if (part_passwd == NULL)
{
DEBUG(10,("No password set - allowing access\n"));
}
/* No password set - always true ! */
if (part_passwd == NULL)
{
return True;
}
ntv2_owf_gen(part_passwd, user, domain, kr);
SMBOWFencrypt_ntv2(kr, c8, 8, password+16, pwd_len-16, resp);
if (sess_key != NULL)
{
SMBsesskeygen_ntv2(kr, resp, sess_key);
}
#if DEBUG_PASSWORD
DEBUG(100,("Part password (P16) was |"));
dump_data(100, part_passwd, 16);
DEBUG(100,("Password from client was |"));
dump_data(100, password, pwd_len);
DEBUG(100,("Given challenge was |"));
dump_data(100, c8, 8);
DEBUG(100,("Value from encryption was |"));
dump_data(100, resp, 16);
#endif
return (memcmp(resp, password, 16) == 0);
}
/****************************************************************************
Do a specific test for an smb password being correct, given a smb_password and
the lanman and NT responses.
****************************************************************************/
BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar challenge[8],
const char *user, const char *domain,
uchar *lm_pass, size_t lm_pwd_len,
uchar *nt_pass, size_t nt_pwd_len,
uchar sess_key[16])
{
if (smb_pass == NULL)
{
return False;
}
DEBUG(4,("Checking SMB password for user %s\n",
smb_pass->unix_name));
if (smb_pass->acct_ctrl & ACB_DISABLED)
{
DEBUG(3,("account for user %s was disabled.\n",
smb_pass->unix_name));
return False;
}
if (challenge == NULL)
{
DEBUG(1,("no challenge available - password failed\n"));
return False;
}
if ((Protocol >= PROTOCOL_NT1) && (smb_pass->smb_nt_passwd != NULL))
{
/* We have the NT MD4 hash challenge available - see if we can
use it (ie. does it exist in the smbpasswd file).
*/
if (lp_server_ntlmv2() != False && nt_pwd_len > 24)
{
DEBUG(4,("smb_password_ok: Check NTLMv2 password\n"));
if (smb_pwd_check_ntlmv2(nt_pass, nt_pwd_len,
(uchar *)smb_pass->smb_nt_passwd,
challenge, user, domain,
sess_key))
{
return True;
}
}
if (lp_server_ntlmv2() != True && nt_pwd_len == 24)
{
DEBUG(4,("smb_password_ok: Check NT MD4 password\n"));
if (smb_pwd_check_ntlmv1((char *)nt_pass,
(uchar *)smb_pass->smb_nt_passwd,
challenge,
sess_key))
{
DEBUG(4,("NT MD4 password check succeeded\n"));
return True;
}
}
DEBUG(4,("NT MD4 password check failed\n"));
}
if (lp_server_ntlmv2() == True)
{
DEBUG(4,("Not checking LM MD4 password\n"));
return False;
}
/* Try against the lanman password. smb_pass->smb_passwd == NULL means
no password, allow access. */
DEBUG(4,("Checking LM MD4 password\n"));
if ((smb_pass->smb_passwd == NULL) &&
(smb_pass->acct_ctrl & ACB_PWNOTREQ))
{
DEBUG(4,("no password required for user %s\n",
smb_pass->unix_name));
return True;
}
if ((smb_pass->smb_passwd != NULL) &&
smb_pwd_check_ntlmv1((char *)lm_pass,
(uchar *)smb_pass->smb_passwd,
challenge, NULL))
{
DEBUG(4,("LM MD4 password check succeeded\n"));
return(True);
}
DEBUG(4,("LM MD4 password check failed\n"));
return False;
}
/****************************************************************************
check if a username/password is OK assuming the password is a 24 byte
SMB hash
return True if the password is correct, False otherwise
****************************************************************************/
BOOL pass_check_smb(struct smb_passwd *smb_pass, char *domain, uchar *chal,
uchar *lm_pwd, size_t lm_pwd_len,
uchar *nt_pwd, size_t nt_pwd_len,
struct passwd *pwd, uchar user_sess_key[16])
{
const struct passwd *pass;
struct passwd pw;
char *user = NULL;
if (smb_pass == NULL)
{
DEBUG(3,("Couldn't find user %s in smb_passwd file.\n", user));
return False;
}
user = smb_pass->unix_name;
if (lm_pwd == NULL || nt_pwd == NULL)
{
return False;
}
if (pwd != NULL && user == NULL)
{
pass = (struct passwd *) pwd;
user = pass->pw_name;
}
else
{
pass = Get_Pwnam(user,True);
if (pass == NULL)
{
DEBUG(3,("Couldn't find user %s\n",user));
return False;
}
memcpy(&pw, pass, sizeof(struct passwd));
pass = &pw;
}
/* Quit if the account was disabled. */
if (smb_pass->acct_ctrl & ACB_DISABLED) {
DEBUG(3,("account for user %s was disabled.\n", user));
return False;
}
/* Ensure the uid's match */
if (smb_pass->unix_uid != pass->pw_uid)
{
DEBUG(3,("Error : UNIX (%d) and SMB (%d) uids in password files do not match !\n", pass->pw_uid, smb_pass->unix_uid));
return False;
}
if (lm_pwd[0] == '\0' && IS_BITS_SET_ALL(smb_pass->acct_ctrl, ACB_PWNOTREQ) && lp_null_passwords())
{
DEBUG(3,("account for user %s has no password and null passwords are allowed.\n", smb_pass->unix_name));
return(True);
}
if (smb_password_ok(smb_pass, chal, user, domain,
lm_pwd, lm_pwd_len,
nt_pwd, nt_pwd_len,
user_sess_key))
{
if (user_sess_key != NULL)
{
#ifdef DEBUG_PASSWORD
DEBUG(100,("user session key: "));
dump_data(100, user_sess_key, 16);
#endif
}
return(True);
}
DEBUG(3,("Error pass_check_smb failed\n"));
return False;
}

View File

@ -565,6 +565,35 @@ static BOOL user_in_group_list(char *user,char *gname)
return False;
}
/****************************************************************************
check if a username is valid
****************************************************************************/
BOOL user_ok(char *user,int snum)
{
pstring valid, invalid;
BOOL ret;
StrnCpy(valid, lp_valid_users(snum), sizeof(pstring));
StrnCpy(invalid, lp_invalid_users(snum), sizeof(pstring));
string_sub(valid,"%S",lp_servicename(snum));
string_sub(invalid,"%S",lp_servicename(snum));
ret = !user_in_list(user,invalid);
if (ret && valid && *valid) {
ret = user_in_list(user,valid);
}
if (ret && lp_onlyuser(snum)) {
char *user_list = lp_username(snum);
string_sub(user_list,"%S",lp_servicename(snum));
ret = user_in_list(user,user_list);
}
return(ret);
}
/****************************************************************************
check if a user is in a user list - can check combinations of UNIX
and netgroup lists.

View File

@ -901,6 +901,9 @@ int create_pipe_socket(char *dir, int dir_perms,
int s;
struct sockaddr_un sa;
DEBUG(10,("create_pipe_socket: %s %d %s %d\n",
dir, dir_perms, path, path_perms));
mkdir(dir, dir_perms);
if (chmod(dir, dir_perms) < 0)
@ -912,7 +915,6 @@ int create_pipe_socket(char *dir, int dir_perms,
if (!remove(path))
{
DEBUG(0, ("remove on %s failed\n", path));
return -1;
}
/* start listening on unix socket */
@ -954,5 +956,7 @@ int create_pipe_socket(char *dir, int dir_perms,
return -1;
}
DEBUG(5,("unix socket opened: %s\n", path));
return s;
}

169
source3/lib/vuser.c Normal file
View File

@ -0,0 +1,169 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
Password and authentication handling
Copyright (C) Andrew Tridgell 1992-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
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;
/* this holds info on user ids that are already validated for this VC */
static user_struct *validated_users = NULL;
static int num_validated_users = 0;
/****************************************************************************
check if a uid has been validated, and return an pointer to the user_struct
if it has. NULL if not. vuid is biased by an offset. This allows us to
tell random client vuid's (normally zero) from valid vuids.
****************************************************************************/
user_struct *get_valid_user_struct(uint16 vuid)
{
if (vuid == UID_FIELD_INVALID)
return NULL;
vuid -= VUID_OFFSET;
if ((vuid >= (uint16)num_validated_users) ||
(validated_users[vuid].uid == (uid_t)-1) || (validated_users[vuid].gid == (gid_t)-1))
return NULL;
return &validated_users[vuid];
}
/****************************************************************************
invalidate a uid
****************************************************************************/
void invalidate_vuid(uint16 vuid)
{
user_struct *vuser = get_valid_user_struct(vuid);
if (vuser == NULL) return;
vuser->uid = (uid_t)-1;
vuser->gid = (gid_t)-1;
vuser->n_sids = 0;
/* same number of igroups as groups */
vuser->n_groups = 0;
if (vuser->groups)
free((char *)vuser->groups);
if (vuser->sids)
free((char *)vuser->sids);
vuser->sids = NULL;
vuser->groups = NULL;
}
/****************************************************************************
return a validated username
****************************************************************************/
char *validated_username(uint16 vuid)
{
user_struct *vuser = get_valid_user_struct(vuid);
if (vuser == NULL)
return 0;
return(vuser->name);
}
/****************************************************************************
register a uid/name pair as being valid and that a valid password
has been given. vuid is biased by an offset. This allows us to
tell random client vuid's (normally zero) from valid vuids.
****************************************************************************/
uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, BOOL guest, uchar user_sess_key[16])
{
user_struct *vuser;
struct passwd *pwfile; /* for getting real name from passwd file */
/* Ensure no vuid gets registered in share level security. */
if(lp_security() == SEC_SHARE)
return UID_FIELD_INVALID;
#if 0
/*
* After observing MS-Exchange services writing to a Samba share
* I belive this code is incorrect. Each service does its own
* sessionsetup_and_X for the same user, and as each service shuts
* down, it does a user_logoff_and_X. As we are consolidating multiple
* sessionsetup_and_X's onto the same vuid here, when the first service
* shuts down, it invalidates all the open files for the other services.
* Hence I am removing this code and forcing each sessionsetup_and_X
* to get a new vuid.
* Jeremy Allison. (jallison@whistle.com).
*/
int i;
for(i = 0; i < num_validated_users; i++) {
vuser = &validated_users[i];
if ( vuser->uid == uid )
return (uint16)(i + VUID_OFFSET); /* User already validated */
}
#endif
validated_users = (user_struct *)Realloc(validated_users,
sizeof(user_struct)*
(num_validated_users+1));
if (!validated_users)
{
DEBUG(0,("Failed to realloc users struct!\n"));
num_validated_users = 0;
return UID_FIELD_INVALID;
}
vuser = &validated_users[num_validated_users];
num_validated_users++;
vuser->uid = uid;
vuser->gid = gid;
vuser->guest = guest;
fstrcpy(vuser->name,unix_name);
fstrcpy(vuser->requested_name,requested_name);
memcpy(vuser->dc.user_sess_key, user_sess_key, sizeof(vuser->dc.user_sess_key));
vuser->n_sids = 0;
vuser->sids = NULL;
vuser->n_groups = 0;
vuser->groups = NULL;
/* Find all the groups this uid is in and store them.
Used by become_user() */
get_unixgroups(unix_name,uid,gid,
&vuser->n_groups,
&vuser->groups);
DEBUG(3,("uid %d registered to name %s\n",(int)uid,unix_name));
DEBUG(3, ("Clearing default real name\n"));
fstrcpy(vuser->real_name, "<Full Name>\0");
if (lp_unix_realname()) {
if ((pwfile=hashed_getpwnam(vuser->name))!= NULL)
{
DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->name,pwfile->pw_gecos));
fstrcpy(vuser->real_name, pwfile->pw_gecos);
}
}
return (uint16)((num_validated_users - 1) + VUID_OFFSET);
}

653
source3/lsarpcd/lsarpcd.c Normal file
View File

@ -0,0 +1,653 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
Main SMB server routines
Copyright (C) Andrew Tridgell 1992-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
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"
#include "trans2.h"
pstring servicesf = CONFIGFILE;
extern pstring debugf;
extern pstring global_myname;
int am_parent = 1;
/* the last message the was processed */
int last_message = -1;
/* a useful macro to debug the last message processed */
#define LAST_MESSAGE() smb_fn_name(last_message)
extern pstring scope;
extern int DEBUGLEVEL;
extern fstring remote_machine;
extern pstring myhostname;
/****************************************************************************
when exiting, take the whole family
****************************************************************************/
static void *dflt_sig(void)
{
exit_server("caught signal");
return NULL;
}
/****************************************************************************
Send a SIGTERM to our process group.
*****************************************************************************/
static void killkids(void)
{
if(am_parent) kill(0,SIGTERM);
}
/****************************************************************************
open and listen to a socket
****************************************************************************/
static int open_server_socket(void)
{
int s;
fstring dir;
fstring path;
slprintf(dir, sizeof(dir)-1, "/tmp/.msrpc");
slprintf(path, sizeof(path)-1, "%s/lsarpc", dir);
s = create_pipe_socket(dir, 0777, path, 0777);
if (s == -1)
return -1;
/* ready to listen */
if (listen(s, 5) == -1) {
DEBUG(0,("listen: %s\n", strerror(errno)));
close(s);
return -1;
}
return s;
}
/****************************************************************************
open the socket communication
****************************************************************************/
static BOOL open_sockets(BOOL is_daemon)
{
extern int Client;
int num_interfaces = iface_count();
int fd_listenset;
fd_set listen_set;
int s;
memset(&fd_listenset, 0, sizeof(fd_listenset));
#ifdef HAVE_ATEXIT
{
static int atexit_set;
if(atexit_set == 0) {
atexit_set=1;
atexit(killkids);
}
}
#endif
/* Stop zombies */
CatchChild();
FD_ZERO(&listen_set);
/* Just bind to 0.0.0.0 - accept connections
from anywhere. */
num_interfaces = 1;
/* open an incoming socket */
s = open_server_socket();
if (s == -1)
return(False);
fd_listenset = s;
FD_SET(s,&listen_set);
/* now accept incoming connections - forking a new process
for each incoming connection */
DEBUG(2,("waiting for a connection\n"));
while (1)
{
struct sockaddr_un addr;
int in_addrlen = sizeof(addr);
fd_set lfds;
int num;
memcpy((char *)&lfds, (char *)&listen_set,
sizeof(listen_set));
num = sys_select(256,&lfds,NULL, NULL);
if (num == -1 && errno == EINTR)
continue;
/* Find the sockets that are read-ready -
accept on these. */
s = -1;
if(FD_ISSET(fd_listenset,&lfds))
{
s = fd_listenset;
}
/* Clear this so we don't look at it again. */
FD_CLR(s,&lfds);
Client = accept(s,(struct sockaddr*)&addr,&in_addrlen);
if (Client == -1 && errno == EINTR)
continue;
if (Client == -1)
{
DEBUG(0,("open_sockets: accept: %s\n",
strerror(errno)));
continue;
}
if (Client != -1 && fork()==0)
{
/* Child code ... */
/* close the listening socket(s) */
close(fd_listenset);
/* close our standard file
descriptors */
close_low_fds();
am_parent = 0;
/* Reset global variables in util.c so
that client substitutions will be
done correctly in the process. */
reset_globals_after_fork();
/*
* Ensure this child has kernel oplock
* capabilities, but not it's children.
*/
set_process_capability(KERNEL_OPLOCK_CAPABILITY, True);
set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY, False);
return True;
}
/* The parent doesn't need this socket */
close(Client);
/* Force parent to check log size after
* spawning child. Fix from
* klausr@ITAP.Physik.Uni-Stuttgart.De. The
* parent lsarpcd will log to logserver.smb. It
* writes only two messages for each child
* started/finished. But each child writes,
* say, 50 messages also in logserver.smb,
* begining with the debug_count of the
* parent, before the child opens its own log
* file logserver.client. In a worst case
* scenario the size of logserver.smb would be
* checked after about 50*50=2500 messages
* (ca. 100kb).
* */
force_check_log_size();
} /* end while 1 */
/* NOTREACHED return True; */
}
/****************************************************************************
reload the services file
**************************************************************************/
BOOL reload_services(BOOL test)
{
BOOL ret;
if (lp_loaded()) {
pstring fname;
pstrcpy(fname,lp_configfile());
if (file_exist(fname,NULL) && !strcsequal(fname,servicesf)) {
pstrcpy(servicesf,fname);
test = False;
}
}
reopen_logs();
if (test && !lp_file_list_changed())
return(True);
lp_killunused(NULL);
ret = lp_load(servicesf,False,False,True);
load_printers();
/* perhaps the config filename is now set */
if (!test)
reload_services(True);
reopen_logs();
load_interfaces();
return(ret);
}
/****************************************************************************
this prevents zombie child processes
****************************************************************************/
BOOL reload_after_sighup = False;
static void sig_hup(int sig)
{
BlockSignals(True,SIGHUP);
DEBUG(0,("Got SIGHUP\n"));
/*
* Fix from <branko.cibej@hermes.si> here.
* We used to reload in the signal handler - this
* is a *BIG* no-no.
*/
reload_after_sighup = True;
BlockSignals(False,SIGHUP);
}
#if DUMP_CORE
/*******************************************************************
prepare to dump a core file - carefully!
********************************************************************/
static BOOL dump_core(void)
{
char *p;
pstring dname;
pstrcpy(dname,debugf);
if ((p=strrchr(dname,'/'))) *p=0;
pstrcat(dname,"/corefiles");
mkdir(dname,0700);
sys_chown(dname,getuid(),getgid());
chmod(dname,0700);
if (chdir(dname)) return(False);
umask(~(0700));
#ifdef HAVE_GETRLIMIT
#ifdef RLIMIT_CORE
{
struct rlimit rlp;
getrlimit(RLIMIT_CORE, &rlp);
rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
setrlimit(RLIMIT_CORE, &rlp);
getrlimit(RLIMIT_CORE, &rlp);
DEBUG(3,("Core limits now %d %d\n",
(int)rlp.rlim_cur,(int)rlp.rlim_max));
}
#endif
#endif
DEBUG(0,("Dumping core in %s\n",dname));
abort();
return(True);
}
#endif
/****************************************************************************
exit the server
****************************************************************************/
void exit_server(char *reason)
{
static int firsttime=1;
extern char *last_inbuf;
if (!firsttime) exit(0);
firsttime = 0;
unbecome_user();
DEBUG(2,("Closing connections\n"));
#ifdef WITH_DFS
if (dcelogin_atmost_once) {
dfs_unlogin();
}
#endif
if (!reason) {
int oldlevel = DEBUGLEVEL;
DEBUGLEVEL = 10;
if (last_inbuf)
show_msg(last_inbuf);
DEBUGLEVEL = oldlevel;
DEBUG(0,("===============================================================\n"));
#if DUMP_CORE
if (dump_core()) return;
#endif
}
locking_end();
DEBUG(3,("Server exit (%s)\n", (reason ? reason : "")));
#ifdef MEM_MAN
{
extern FILE *dbf;
smb_mem_write_verbose(dbf);
dbgflush();
}
#endif
exit(0);
}
/****************************************************************************
initialise connect, service and file structs
****************************************************************************/
static void init_structs(void)
{
#if 0
conn_init();
#endif
init_rpc_pipe_hnd(); /* for RPC pipes */
if (!init_policy_hnd(MAX_SERVER_POLICY_HANDLES))
{
exit_server("could not allocate policy handles\n");
}
}
/****************************************************************************
usage on the program
****************************************************************************/
static void usage(char *pname)
{
DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n"));
printf("Usage: %s [-D] [-p port] [-d debuglevel] ", pname);
printf("[-l log basename] [-s services file]\n" );
printf("Version %s\n",VERSION);
printf("\t-D become a daemon\n");
printf("\t-p port listen on the specified port\n");
printf("\t-d debuglevel set the debuglevel\n");
printf("\t-l log basename. Basename for log/debug files\n");
printf("\t-s services file. Filename of services file\n");
printf("\t-P passive only\n");
printf("\t-a append to log file (default)\n");
printf("\t-o overwrite log file, don't append\n");
printf("\t-i scope NetBIOS scope to use (default none)\n");
printf("\n");
}
/****************************************************************************
main program
****************************************************************************/
int main(int argc,char *argv[])
{
extern BOOL append_log;
/* shall I run as a daemon */
BOOL is_daemon = False;
int opt;
extern char *optarg;
#ifdef HAVE_SET_AUTH_PARAMETERS
set_auth_parameters(argc,argv);
#endif
#ifdef HAVE_SETLUID
/* needed for SecureWare on SCO */
setluid(0);
#endif
append_log = True;
TimeInit();
pstrcpy(debugf,LSARPCLOGFILE);
pstrcpy(remote_machine, "lsarpcd");
setup_logging(argv[0],False);
charset_initialise();
/* make absolutely sure we run as root - to handle cases where people
are crazy enough to have it setuid */
#ifdef HAVE_SETRESUID
setresuid(0,0,0);
#else
setuid(0);
seteuid(0);
setuid(0);
seteuid(0);
#endif
fault_setup((void (*)(void *))exit_server);
CatchSignal(SIGTERM , SIGNAL_CAST dflt_sig);
/* we are never interested in SIGPIPE */
BlockSignals(True,SIGPIPE);
/* we want total control over the permissions on created files,
so set our umask to 0 */
umask(0);
init_uid();
/* this is for people who can't start the program correctly */
while (argc > 1 && (*argv[1] != '-')) {
argv++;
argc--;
}
while ( EOF != (opt = getopt(argc, argv, "i:l:s:d:Dh?Paof:")) )
switch (opt) {
case 'i':
pstrcpy(scope,optarg);
break;
case 'P':
{
extern BOOL passive;
passive = True;
}
break;
case 's':
pstrcpy(servicesf,optarg);
break;
case 'l':
pstrcpy(debugf,optarg);
break;
case 'a':
append_log = True;
break;
case 'o':
append_log = False;
break;
case 'D':
is_daemon = True;
break;
case 'd':
if (*optarg == 'A')
DEBUGLEVEL = 10000;
else
DEBUGLEVEL = atoi(optarg);
break;
case 'h':
case '?':
usage(argv[0]);
exit(0);
break;
default:
usage(argv[0]);
exit(1);
}
reopen_logs();
DEBUG(1,( "lsarpcd version %s started.\n", VERSION));
DEBUGADD(1,( "Copyright Andrew Tridgell 1992-1999\n"));
DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
(int)getuid(),(int)getgid(),(int)geteuid(),(int)getegid()));
if (sizeof(uint16) < 2 || sizeof(uint32) < 4) {
DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
exit(1);
}
get_myname(myhostname,NULL);
if (!reload_services(False))
return(-1);
init_structs();
#ifdef WITH_PROFILE
if (!profile_setup(False)) {
DEBUG(0,("ERROR: failed to setup profiling\n"));
return -1;
}
#endif
/*
* Set the machine NETBIOS name if not already
* set from the config file.
*/
if (!*global_myname)
{
fstrcpy(global_myname, dns_to_netbios_name(myhostname));
}
strupper(global_myname);
add_msrpc_command_processor( "lsarpc", argv[0], api_ntlsa_rpc );
codepage_initialise(lp_client_code_page());
if (!pwdb_initialise(True))
{
exit(1);
}
if(!initialise_sam_password_db())
{
exit(1);
}
if(!initialise_passgrp_db())
{
exit(1);
}
if(!initialise_group_db())
{
exit(1);
}
if(!initialise_alias_db())
{
exit(1);
}
if(!initialise_builtin_db())
{
exit(1);
}
if (!get_member_domain_sid())
{
DEBUG(0,("ERROR: Samba cannot obtain PDC SID from PDC(s) %s.\n",
lp_passwordserver()));
exit(1);
}
CatchSignal(SIGHUP,SIGNAL_CAST sig_hup);
/* Setup the signals that allow the debug log level
to by dynamically changed. */
/* If we are using the malloc debug code we can't use
SIGUSR1 and SIGUSR2 to do debug level changes. */
#ifndef MEM_MAN
#if defined(SIGUSR1)
CatchSignal( SIGUSR1, SIGNAL_CAST sig_usr1 );
#endif /* SIGUSR1 */
#if defined(SIGUSR2)
CatchSignal( SIGUSR2, SIGNAL_CAST sig_usr2 );
#endif /* SIGUSR2 */
#endif /* MEM_MAN */
DEBUG(3,( "loaded services\n"));
if (!is_daemon && !is_a_socket(0)) {
DEBUG(0,("standard input is not a socket, assuming -D option\n"));
is_daemon = True;
}
if (is_daemon) {
DEBUG( 3, ( "Becoming a daemon.\n" ) );
become_daemon();
}
if (!directory_exist(lp_lockdir(), NULL)) {
mkdir(lp_lockdir(), 0755);
}
if (is_daemon) {
pidfile_create("lsarpcd");
}
if (!open_sockets(is_daemon))
exit(1);
if (!locking_init(0))
exit(1);
/* possibly reload the services file. */
reload_services(True);
if (*lp_rootdir()) {
if (sys_chroot(lp_rootdir()) == 0)
DEBUG(2,("Changed root to %s\n", lp_rootdir()));
}
lsarpcd_process();
close_sockets();
exit_server("normal exit");
return(0);
}

View File

@ -0,0 +1,401 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
process incoming packets - main loop
Copyright (C) Andrew Tridgell 1992-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
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;
time_t smb_last_time=(time_t)0;
static struct pipes_struct static_pipe;
char *InBuffer = NULL;
char *OutBuffer = NULL;
char *last_inbuf = NULL;
/*
* Size of data we can send to client. Set
* by the client for all protocols above CORE.
* Set by us for CORE protocol.
*/
int max_send = BUFFER_SIZE;
/*
* Size of the data we can receive. Set by us.
* Can be modified by the max xmit parameter.
*/
int max_recv = BUFFER_SIZE;
extern int last_message;
extern pstring sesssetup_user;
extern char *last_inbuf;
extern char *InBuffer;
extern char *OutBuffer;
extern int smb_read_error;
extern BOOL reload_after_sighup;
extern int max_send;
/****************************************************************************
Do a select on an two fd's - with timeout.
If a local udp message has been pushed onto the
queue (this can only happen during oplock break
processing) return this first.
If a pending smb message has been pushed onto the
queue (this can only happen during oplock break
processing) return this next.
If the first smbfd is ready then read an smb from it.
if the second (loopback UDP) fd is ready then read a message
from it and setup the buffer header to identify the length
and from address.
Returns False on timeout or error.
Else returns True.
The timeout is in milli seconds
****************************************************************************/
static BOOL receive_message_or_smb(char *buffer, int buffer_len,
int timeout, BOOL *got_smb)
{
extern int Client;
fd_set fds;
int selrtn;
struct timeval to;
int maxfd;
smb_read_error = 0;
*got_smb = False;
/*
* Check to see if we already have a message on the smb queue.
* If so - copy and return it.
*/
/*
* Setup the select read fd set.
*/
FD_ZERO(&fds);
FD_SET(Client,&fds);
maxfd = 0;
to.tv_sec = timeout / 1000;
to.tv_usec = (timeout % 1000) * 1000;
selrtn = sys_select(MAX(maxfd,Client)+1,&fds,NULL, timeout>0?&to:NULL);
/* Check if error */
if(selrtn == -1) {
/* something is wrong. Maybe the socket is dead? */
smb_read_error = READ_ERROR;
return False;
}
/* Did we timeout ? */
if (selrtn == 0) {
smb_read_error = READ_TIMEOUT;
return False;
}
if (FD_ISSET(Client,&fds))
{
*got_smb = True;
return receive_smb(Client, buffer, 0);
}
return False;
}
/****************************************************************************
Get the next SMB packet, doing the local message processing automatically.
****************************************************************************/
BOOL receive_next_smb(char *inbuf, int bufsize, int timeout)
{
BOOL got_smb = False;
BOOL ret;
do
{
ret = receive_message_or_smb(inbuf,bufsize,timeout,&got_smb);
if(ret && !got_smb)
{
continue;
}
if(ret && (CVAL(inbuf,0) == 0x85))
{
/* Keepalive packet. */
got_smb = False;
}
}
while(ret && !got_smb);
return ret;
}
/*
These flags determine some of the permissions required to do an operation
Note that I don't set NEED_WRITE on some write operations because they
are used by some brain-dead clients when printing, and I don't want to
force write permissions on print services.
*/
#define AS_USER (1<<0)
#define NEED_WRITE (1<<1)
#define TIME_INIT (1<<2)
#define CAN_IPC (1<<3)
#define AS_GUEST (1<<5)
#define QUEUE_IN_OPLOCK (1<<6)
/*
define a list of possible SMB messages and their corresponding
functions. Any message that has a NULL function is unimplemented -
please feel free to contribute implementations!
*/
/****************************************************************************
do a switch on the message type, and return the response size
****************************************************************************/
static int do_message(char *inbuf,char *outbuf,int size,int bufsize)
{
static int pid= -1;
pipes_struct *p = &static_pipe;
prs_struct pd;
int outsize = -1;
/* make a static data parsing structure from the api_fd_reply data */
prs_init(&pd, 0, 4, 0, True);
mem_create(pd.data, smb_base(inbuf), 0, smb_len(inbuf), 0, False);
if (pid == -1)
pid = getpid();
/* dce/rpc command */
if (rpc_command(p, &pd))
{
char *copy_into = smb_base(outbuf);
outsize = mem_buf_len(p->rhdr.data);
if (!mem_buf_copy(copy_into, p->rhdr.data, 0, outsize))
{
return -1;
}
}
mem_free_data(pd.data);
mem_free_data(p->rhdr .data);
mem_free_data(p->rfault .data);
mem_free_data(p->rdata .data);
mem_free_data(p->rdata_i.data);
mem_free_data(p->rauth .data);
mem_free_data(p->rverf .data);
mem_free_data(p->rntlm .data);
return outsize;
}
/****************************************************************************
construct a reply to the incoming packet
****************************************************************************/
static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
{
int outsize = 0;
smb_last_time = time(NULL);
outsize = do_message(inbuf,outbuf,size,bufsize) + 4;
if(outsize > 4)
_smb_setlen(outbuf,outsize - 4);
return(outsize);
}
/****************************************************************************
process an smb from the client - split out from the process() code so
it can be used by the oplock break code.
****************************************************************************/
void process_smb(char *inbuf, char *outbuf)
{
extern int Client;
static int trans_num;
int32 len = smb_len(inbuf);
int nread = len + 4;
if (trans_num == 0) {
/* on the first packet, check the global hosts allow/ hosts
deny parameters before doing any parsing of the packet
passed to us by the client. This prevents attacks on our
parsing code from hosts not in the hosts allow list */
if (!check_access(Client, lp_hostsallow(-1), lp_hostsdeny(-1))) {
/* send a negative session response "not listining on calling
name" */
DEBUG( 1, ( "Connection denied from %s\n",
client_addr(Client) ) );
exit_server("connection denied");
}
}
DEBUG( 6, ( "got message of len 0x%x\n", len ) );
DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) );
dump_data(10, inbuf, len);
#ifdef WITH_VTP
if(trans_num == 1 && VT_Check(inbuf))
{
VT_Process();
return;
}
#endif
nread = construct_reply(inbuf,outbuf,nread,max_send);
if(nread > 0)
{
dump_data(10, outbuf, nread);
if (nread != smb_len(outbuf) + 4)
{
DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
nread, smb_len(outbuf)));
}
else
send_smb(Client,outbuf);
}
trans_num++;
}
/****************************************************************************
process commands from the client
****************************************************************************/
void lsarpcd_process(void)
{
ZERO_STRUCT(static_pipe);
fstrcpy(static_pipe.name, "lsarpc");
InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
if ((InBuffer == NULL) || (OutBuffer == NULL))
return;
InBuffer += SMB_ALIGNMENT;
OutBuffer += SMB_ALIGNMENT;
max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
/* re-initialise the timezone */
TimeInit();
while (True)
{
int deadtime = lp_deadtime()*60;
int counter;
int service_load_counter = 0;
BOOL got_smb = False;
if (deadtime <= 0)
deadtime = DEFAULT_SMBD_TIMEOUT;
#if USE_READ_PREDICTION
if (lp_readprediction())
do_read_prediction();
#endif
errno = 0;
for (counter=SMBD_SELECT_LOOP;
!receive_message_or_smb(InBuffer,BUFFER_SIZE,
SMBD_SELECT_LOOP*1000,&got_smb);
counter += SMBD_SELECT_LOOP)
{
time_t t;
if (counter > 365 * 3600) /* big number of seconds. */
{
counter = 0;
service_load_counter = 0;
}
if (smb_read_error == READ_EOF)
{
DEBUG(3,("end of file from client\n"));
return;
}
if (smb_read_error == READ_ERROR)
{
DEBUG(3,("receive_smb error (%s) exiting\n",
strerror(errno)));
return;
}
t = time(NULL);
/* become root again if waiting */
unbecome_user();
/* check for smb.conf reload */
if (counter >= service_load_counter + SMBD_RELOAD_CHECK)
{
service_load_counter = counter;
/* reload services, if files have changed. */
reload_services(True);
}
/*
* If reload_after_sighup == True then we got a SIGHUP
* and are being asked to reload. Fix from <branko.cibej@hermes.si>
*/
if (reload_after_sighup)
{
DEBUG(0,("Reloading services after SIGHUP\n"));
reload_services(False);
reload_after_sighup = False;
/*
* Use this as an excuse to print some stats.
*/
}
/* automatic timeout if all connections are closed */
if (counter >= IDLE_CLOSED_TIMEOUT)
{
DEBUG( 2, ( "Closing idle connection\n" ) );
return;
}
}
if(got_smb)
process_smb(InBuffer, OutBuffer);
}
}

View File

@ -36,6 +36,16 @@ void prs_debug(prs_struct *ps, int depth, char *desc, char *fn_name)
DEBUG(5+depth, ("%s%06x %s %s\n", tab_depth(depth), ps->offset, fn_name, desc));
}
/*******************************************************************
debug a parse structure
********************************************************************/
void prs_debug_out(prs_struct *ps, int level)
{
DEBUG(level,("ps: io %s align %d offset %d err %d data %p len %d\n",
BOOLSTR(ps->io), ps->align, ps->offset, ps->error, ps->data,
ps->data != NULL ? mem_buf_len(ps->data) : 0));
}
/*******************************************************************
initialise a parse structure
********************************************************************/

View File

@ -396,7 +396,69 @@ struct api_cmd
BOOL (*fn) (pipes_struct *, prs_struct *);
};
static struct api_cmd api_fd_commands[] =
static struct api_cmd **api_fd_commands = NULL;
uint32 num_cmds = 0;
static void api_cmd_free(struct api_cmd *item)
{
if (item != NULL)
{
if (item->pipe_clnt_name != NULL)
{
free(item->pipe_clnt_name);
}
if (item->pipe_srv_name != NULL)
{
free(item->pipe_srv_name);
}
free(item);
}
}
static struct api_cmd *api_cmd_dup(const struct api_cmd *from)
{
struct api_cmd *copy = NULL;
if (from == NULL)
{
return NULL;
}
copy = (struct api_cmd *) malloc(sizeof(struct api_cmd));
if (copy != NULL)
{
ZERO_STRUCTP(copy);
if (from->pipe_clnt_name != NULL)
{
copy->pipe_clnt_name = strdup(from->pipe_clnt_name );
}
if (from->pipe_srv_name != NULL)
{
copy->pipe_srv_name = strdup(from->pipe_srv_name);
}
if (from->fn != NULL)
{
copy->fn = from->fn;
}
}
return copy;
}
static void free_api_cmd_array(uint32 num_entries, struct api_cmd **entries)
{
void(*fn)(void*) = (void(*)(void*))&api_cmd_free;
free_void_array(num_entries, (void**)entries, *fn);
}
static struct api_cmd* add_api_cmd_to_array(uint32 *len,
struct api_cmd ***array,
const struct api_cmd *name)
{
void*(*fn)(const void*) = (void*(*)(const void*))&api_cmd_dup;
return (struct api_cmd*)add_copy_to_array(len,
(void***)array, (const void*)name, *fn, False);
}
#if 0
{
{ "lsarpc", "lsass", api_ntlsa_rpc },
{ "samr", "lsass", api_samr_rpc },
@ -409,6 +471,20 @@ static struct api_cmd api_fd_commands[] =
{ "spoolss", "spoolss", api_spoolss_rpc },
{ NULL, NULL, NULL }
};
#endif
void close_msrpc_command_processor(void)
{
free_api_cmd_array(num_cmds, api_fd_commands);
}
void add_msrpc_command_processor(char* pipe_name,
char* process_name,
BOOL (*fn) (pipes_struct *, prs_struct *))
{
struct api_cmd cmd = { pipe_name, process_name, fn };
add_api_cmd_to_array(&num_cmds, &api_fd_commands, &cmd);
}
static BOOL api_pipe_bind_auth_resp(pipes_struct *p, prs_struct *pd)
{
@ -479,20 +555,20 @@ static BOOL api_pipe_bind_and_alt_req(pipes_struct *p, prs_struct *pd, enum RPC_
DEBUG(5,("api_pipe_bind_req: decode request. %d\n", __LINE__));
for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
for (i = 0; i < num_cmds; i++)
{
if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
api_fd_commands[i].fn != NULL)
if (strequal(api_fd_commands[i]->pipe_clnt_name, p->name) &&
api_fd_commands[i]->fn != NULL)
{
DEBUG(3,("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n",
api_fd_commands[i].pipe_clnt_name,
api_fd_commands[i].pipe_srv_name));
fstrcpy(p->pipe_srv_name, api_fd_commands[i].pipe_srv_name);
api_fd_commands[i]->pipe_clnt_name,
api_fd_commands[i]->pipe_srv_name));
fstrcpy(p->pipe_srv_name, api_fd_commands[i]->pipe_srv_name);
break;
}
}
if (api_fd_commands[i].fn == NULL) return False;
if (api_fd_commands[i]->fn == NULL) return False;
/* decode the bind request */
smb_io_rpc_hdr_rb("", &p->hdr_rb, pd, 0);
@ -727,13 +803,13 @@ static BOOL api_pipe_request(pipes_struct *p, prs_struct *pd)
#endif
}
for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
for (i = 0; i < num_cmds; i++)
{
if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
api_fd_commands[i].fn != NULL)
if (strequal(api_fd_commands[i]->pipe_clnt_name, p->name) &&
api_fd_commands[i]->fn != NULL)
{
DEBUG(3,("Doing \\PIPE\\%s\n", api_fd_commands[i].pipe_clnt_name));
return api_fd_commands[i].fn(p, pd);
DEBUG(3,("Doing \\PIPE\\%s\n", api_fd_commands[i]->pipe_clnt_name));
return api_fd_commands[i]->fn(p, pd);
}
}
return False;
@ -744,6 +820,24 @@ BOOL rpc_command(pipes_struct *p, prs_struct *pd)
BOOL reply = False;
DEBUG(10,("rpc_command\n"));
if (p->m != NULL)
{
DEBUG(10,("msrpc redirect\n"));
if (!msrpc_send_prs(p->m, pd))
{
DEBUG(2,("msrpc redirect send failed\n"));
return False;
}
if (!msrpc_receive_prs(p->m, &p->rhdr))
{
DEBUG(2,("msrpc redirect receive failed\n"));
return False;
}
prs_link(NULL, &p->rhdr, NULL);
prs_debug_out(&p->rhdr, 10);
return True;
}
if (pd->data == NULL) return False;
/* process the rpc header */

View File

@ -83,6 +83,7 @@ pipes_struct *open_rpc_pipe_p(char *pipe_name,
int i;
pipes_struct *p;
static int next_pipe;
struct msrpc_state *m = NULL;
DEBUG(4,("Open pipe requested %s (pipes_open=%d)\n",
pipe_name, pipes_open));
@ -108,6 +109,16 @@ pipes_struct *open_rpc_pipe_p(char *pipe_name,
DEBUG(5,("open pipes: name %s pnum=%x\n", p->name, p->pnum));
}
if (strequal(pipe_name, "lsarpc"))
{
m = msrpc_use_add(pipe_name, NULL, False);
if (m == NULL)
{
DEBUG(5,("open pipes: msrpc redirect failed\n"));
return NULL;
}
}
p = (pipes_struct *)malloc(sizeof(*p));
if (!p) return NULL;
@ -120,6 +131,7 @@ pipes_struct *open_rpc_pipe_p(char *pipe_name,
pipes_open++;
p->pnum = i;
p->m = m;
p->open = True;
p->device_state = 0;
@ -359,6 +371,19 @@ BOOL close_rpc_pipe_hnd(pipes_struct *p, connection_struct *conn)
DLIST_REMOVE(Pipes, p);
if (p->m != NULL)
{
DEBUG(4,("closed msrpc redirect: "));
if (msrpc_use_del(p->m->pipe_name, &p->m->usr, False, NULL))
{
DEBUG(4,("OK\n"));
}
else
{
DEBUG(4,("FAILED\n"));
}
}
ZERO_STRUCTP(p);
free(p);

61
source3/smbd/challenge.c Normal file
View File

@ -0,0 +1,61 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
Password and authentication handling
Copyright (C) Andrew Tridgell 1992-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
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;
/* Data to do lanman1/2 password challenge. */
static unsigned char saved_challenge[8];
static BOOL challenge_sent=False;
/*******************************************************************
Get the next challenge value - no repeats.
********************************************************************/
void generate_next_challenge(char *challenge)
{
unsigned char buf[8];
generate_random_buffer(buf,8,False);
memcpy(saved_challenge, buf, 8);
memcpy(challenge,buf,8);
challenge_sent = True;
}
/*******************************************************************
set the last challenge sent, usually from a password server
********************************************************************/
BOOL set_challenge(unsigned char *challenge)
{
memcpy(saved_challenge,challenge,8);
challenge_sent = True;
return(True);
}
/*******************************************************************
get the last challenge sent
********************************************************************/
BOOL last_challenge(unsigned char *challenge)
{
if (!challenge_sent) return False;
memcpy(challenge,saved_challenge,8);
return(True);
}

View File

@ -31,209 +31,6 @@ extern pstring scope;
extern pstring global_myname;
extern fstring global_myworkgroup;
/* Data to do lanman1/2 password challenge. */
static unsigned char saved_challenge[8];
static BOOL challenge_sent=False;
/*******************************************************************
Get the next challenge value - no repeats.
********************************************************************/
void generate_next_challenge(char *challenge)
{
#if 0
/*
* Leave this ifdef'd out while we test
* the new crypto random number generator.
* JRA.
*/
unsigned char buf[16];
static int counter = 0;
struct timeval tval;
int v1,v2;
/* get a sort-of random number */
GetTimeOfDay(&tval);
v1 = (counter++) + getpid() + tval.tv_sec;
v2 = (counter++) * getpid() + tval.tv_usec;
SIVAL(challenge,0,v1);
SIVAL(challenge,4,v2);
/* mash it up with md4 */
mdfour(buf, (unsigned char *)challenge, 8);
#else
unsigned char buf[8];
generate_random_buffer(buf,8,False);
#endif
memcpy(saved_challenge, buf, 8);
memcpy(challenge,buf,8);
challenge_sent = True;
}
/*******************************************************************
set the last challenge sent, usually from a password server
********************************************************************/
BOOL set_challenge(unsigned char *challenge)
{
memcpy(saved_challenge,challenge,8);
challenge_sent = True;
return(True);
}
/*******************************************************************
get the last challenge sent
********************************************************************/
static BOOL last_challenge(unsigned char *challenge)
{
if (!challenge_sent) return False;
memcpy(challenge,saved_challenge,8);
return(True);
}
/* this holds info on user ids that are already validated for this VC */
static user_struct *validated_users = NULL;
static int num_validated_users = 0;
/****************************************************************************
check if a uid has been validated, and return an pointer to the user_struct
if it has. NULL if not. vuid is biased by an offset. This allows us to
tell random client vuid's (normally zero) from valid vuids.
****************************************************************************/
user_struct *get_valid_user_struct(uint16 vuid)
{
if (vuid == UID_FIELD_INVALID)
return NULL;
vuid -= VUID_OFFSET;
if ((vuid >= (uint16)num_validated_users) ||
(validated_users[vuid].uid == (uid_t)-1) || (validated_users[vuid].gid == (gid_t)-1))
return NULL;
return &validated_users[vuid];
}
/****************************************************************************
invalidate a uid
****************************************************************************/
void invalidate_vuid(uint16 vuid)
{
user_struct *vuser = get_valid_user_struct(vuid);
if (vuser == NULL) return;
vuser->uid = (uid_t)-1;
vuser->gid = (gid_t)-1;
vuser->n_sids = 0;
/* same number of igroups as groups */
vuser->n_groups = 0;
if (vuser->groups)
free((char *)vuser->groups);
if (vuser->sids)
free((char *)vuser->sids);
vuser->sids = NULL;
vuser->groups = NULL;
}
/****************************************************************************
return a validated username
****************************************************************************/
char *validated_username(uint16 vuid)
{
user_struct *vuser = get_valid_user_struct(vuid);
if (vuser == NULL)
return 0;
return(vuser->name);
}
/****************************************************************************
register a uid/name pair as being valid and that a valid password
has been given. vuid is biased by an offset. This allows us to
tell random client vuid's (normally zero) from valid vuids.
****************************************************************************/
uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, BOOL guest, uchar user_sess_key[16])
{
user_struct *vuser;
struct passwd *pwfile; /* for getting real name from passwd file */
/* Ensure no vuid gets registered in share level security. */
if(lp_security() == SEC_SHARE)
return UID_FIELD_INVALID;
#if 0
/*
* After observing MS-Exchange services writing to a Samba share
* I belive this code is incorrect. Each service does its own
* sessionsetup_and_X for the same user, and as each service shuts
* down, it does a user_logoff_and_X. As we are consolidating multiple
* sessionsetup_and_X's onto the same vuid here, when the first service
* shuts down, it invalidates all the open files for the other services.
* Hence I am removing this code and forcing each sessionsetup_and_X
* to get a new vuid.
* Jeremy Allison. (jallison@whistle.com).
*/
int i;
for(i = 0; i < num_validated_users; i++) {
vuser = &validated_users[i];
if ( vuser->uid == uid )
return (uint16)(i + VUID_OFFSET); /* User already validated */
}
#endif
validated_users = (user_struct *)Realloc(validated_users,
sizeof(user_struct)*
(num_validated_users+1));
if (!validated_users)
{
DEBUG(0,("Failed to realloc users struct!\n"));
num_validated_users = 0;
return UID_FIELD_INVALID;
}
vuser = &validated_users[num_validated_users];
num_validated_users++;
vuser->uid = uid;
vuser->gid = gid;
vuser->guest = guest;
fstrcpy(vuser->name,unix_name);
fstrcpy(vuser->requested_name,requested_name);
memcpy(vuser->dc.user_sess_key, user_sess_key, sizeof(vuser->dc.user_sess_key));
vuser->n_sids = 0;
vuser->sids = NULL;
vuser->n_groups = 0;
vuser->groups = NULL;
/* Find all the groups this uid is in and store them.
Used by become_user() */
get_unixgroups(unix_name,uid,gid,
&vuser->n_groups,
&vuser->groups);
DEBUG(3,("uid %d registered to name %s\n",(int)uid,unix_name));
DEBUG(3, ("Clearing default real name\n"));
fstrcpy(vuser->real_name, "<Full Name>\0");
if (lp_unix_realname()) {
if ((pwfile=hashed_getpwnam(vuser->name))!= NULL)
{
DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->name,pwfile->pw_gecos));
fstrcpy(vuser->real_name, pwfile->pw_gecos);
}
}
return (uint16)((num_validated_users - 1) + VUID_OFFSET);
}
/****************************************************************************
add a name to the session users list
@ -290,275 +87,6 @@ static BOOL update_smbpassword_file(char *user, char *password)
/****************************************************************************
core of smb password checking routine.
****************************************************************************/
static BOOL smb_pwd_check_ntlmv1(char *password, unsigned char *part_passwd,
unsigned char *c8,
uchar sess_key[16])
{
/* Finish the encryption of part_passwd. */
unsigned char p24[24];
if (part_passwd == NULL)
DEBUG(10,("No password set - allowing access\n"));
/* No password set - always true ! */
if (part_passwd == NULL)
return True;
SMBOWFencrypt(part_passwd, c8, p24);
if (sess_key != NULL)
{
SMBsesskeygen_ntv1(part_passwd, NULL, sess_key);
}
#if DEBUG_PASSWORD
DEBUG(100,("Part password (P16) was |"));
dump_data(100, part_passwd, 16);
DEBUG(100,("Password from client was |"));
dump_data(100, password, 24);
DEBUG(100,("Given challenge was |"));
dump_data(100, c8, 8);
DEBUG(100,("Value from encryption was |"));
dump_data(100, p24, 24);
#endif
return (memcmp(p24, password, 24) == 0);
}
/****************************************************************************
core of smb password checking routine.
****************************************************************************/
static BOOL smb_pwd_check_ntlmv2(char *password, size_t pwd_len,
unsigned char *part_passwd,
unsigned char const *c8,
const char *user, const char *domain,
char *sess_key)
{
/* Finish the encryption of part_passwd. */
unsigned char kr[16];
unsigned char resp[16];
if (part_passwd == NULL)
{
DEBUG(10,("No password set - allowing access\n"));
}
/* No password set - always true ! */
if (part_passwd == NULL)
{
return True;
}
ntv2_owf_gen(part_passwd, user, domain, kr);
SMBOWFencrypt_ntv2(kr, c8, 8, password+16, pwd_len-16, resp);
if (sess_key != NULL)
{
SMBsesskeygen_ntv2(kr, resp, sess_key);
}
#if DEBUG_PASSWORD
DEBUG(100,("Part password (P16) was |"));
dump_data(100, part_passwd, 16);
DEBUG(100,("Password from client was |"));
dump_data(100, password, pwd_len);
DEBUG(100,("Given challenge was |"));
dump_data(100, c8, 8);
DEBUG(100,("Value from encryption was |"));
dump_data(100, resp, 16);
#endif
return (memcmp(resp, password, 16) == 0);
}
/****************************************************************************
Do a specific test for an smb password being correct, given a smb_password and
the lanman and NT responses.
****************************************************************************/
BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar chal[8],
const char *user, const char *domain,
uchar *lm_pass, size_t lm_pwd_len,
uchar *nt_pass, size_t nt_pwd_len,
uchar sess_key[16])
{
uchar challenge[8];
if (smb_pass == NULL)
{
return False;
}
DEBUG(4,("Checking SMB password for user %s\n",
smb_pass->unix_name));
if (smb_pass->acct_ctrl & ACB_DISABLED)
{
DEBUG(3,("account for user %s was disabled.\n",
smb_pass->unix_name));
return False;
}
if (chal == NULL)
{
DEBUG(5,("use last SMBnegprot challenge\n"));
if (!last_challenge(challenge))
{
DEBUG(1,("no challenge done - password failed\n"));
return False;
}
}
else
{
DEBUG(5,("challenge received\n"));
memcpy(challenge, chal, 8);
}
if ((Protocol >= PROTOCOL_NT1) && (smb_pass->smb_nt_passwd != NULL))
{
/* We have the NT MD4 hash challenge available - see if we can
use it (ie. does it exist in the smbpasswd file).
*/
if (lp_server_ntlmv2() != False && nt_pwd_len > 24)
{
DEBUG(4,("smb_password_ok: Check NTLMv2 password\n"));
if (smb_pwd_check_ntlmv2(nt_pass, nt_pwd_len,
(uchar *)smb_pass->smb_nt_passwd,
challenge, user, domain,
sess_key))
{
return True;
}
}
if (lp_server_ntlmv2() != True && nt_pwd_len == 24)
{
DEBUG(4,("smb_password_ok: Check NT MD4 password\n"));
if (smb_pwd_check_ntlmv1((char *)nt_pass,
(uchar *)smb_pass->smb_nt_passwd,
challenge,
sess_key))
{
DEBUG(4,("NT MD4 password check succeeded\n"));
return True;
}
}
DEBUG(4,("NT MD4 password check failed\n"));
}
if (lp_server_ntlmv2() == True)
{
DEBUG(4,("Not checking LM MD4 password\n"));
return False;
}
/* Try against the lanman password. smb_pass->smb_passwd == NULL means
no password, allow access. */
DEBUG(4,("Checking LM MD4 password\n"));
if ((smb_pass->smb_passwd == NULL) &&
(smb_pass->acct_ctrl & ACB_PWNOTREQ))
{
DEBUG(4,("no password required for user %s\n",
smb_pass->unix_name));
return True;
}
if ((smb_pass->smb_passwd != NULL) &&
smb_pwd_check_ntlmv1((char *)lm_pass,
(uchar *)smb_pass->smb_passwd,
challenge, NULL))
{
DEBUG(4,("LM MD4 password check succeeded\n"));
return(True);
}
DEBUG(4,("LM MD4 password check failed\n"));
return False;
}
/****************************************************************************
check if a username/password is OK assuming the password is a 24 byte
SMB hash
return True if the password is correct, False otherwise
****************************************************************************/
BOOL pass_check_smb(struct smb_passwd *smb_pass, char *domain, uchar *chal,
uchar *lm_pwd, size_t lm_pwd_len,
uchar *nt_pwd, size_t nt_pwd_len,
struct passwd *pwd, uchar user_sess_key[16])
{
const struct passwd *pass;
struct passwd pw;
char *user = NULL;
if (smb_pass == NULL)
{
DEBUG(3,("Couldn't find user %s in smb_passwd file.\n", user));
return False;
}
user = smb_pass->unix_name;
if (lm_pwd == NULL || nt_pwd == NULL)
{
return False;
}
if (pwd != NULL && user == NULL)
{
pass = (struct passwd *) pwd;
user = pass->pw_name;
}
else
{
pass = Get_Pwnam(user,True);
if (pass == NULL)
{
DEBUG(3,("Couldn't find user %s\n",user));
return False;
}
memcpy(&pw, pass, sizeof(struct passwd));
pass = &pw;
}
/* Quit if the account was disabled. */
if (smb_pass->acct_ctrl & ACB_DISABLED) {
DEBUG(3,("account for user %s was disabled.\n", user));
return False;
}
/* Ensure the uid's match */
if (smb_pass->unix_uid != pass->pw_uid)
{
DEBUG(3,("Error : UNIX (%d) and SMB (%d) uids in password files do not match !\n", pass->pw_uid, smb_pass->unix_uid));
return False;
}
if (lm_pwd[0] == '\0' && IS_BITS_SET_ALL(smb_pass->acct_ctrl, ACB_PWNOTREQ) && lp_null_passwords())
{
DEBUG(3,("account for user %s has no password and null passwords are allowed.\n", smb_pass->unix_name));
return(True);
}
if (smb_password_ok(smb_pass, chal, user, domain,
lm_pwd, lm_pwd_len,
nt_pwd, nt_pwd_len,
user_sess_key))
{
if (user_sess_key != NULL)
{
#ifdef DEBUG_PASSWORD
DEBUG(100,("user session key: "));
dump_data(100, user_sess_key, 16);
#endif
}
return(True);
}
DEBUG(3,("Error pass_check_smb failed\n"));
return False;
}
/****************************************************************************
check if a username/password pair is OK either via the system password
database or the encrypted SMB password database
@ -589,35 +117,6 @@ BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd,
update_smbpassword_file : NULL);
}
/****************************************************************************
check if a username is valid
****************************************************************************/
BOOL user_ok(char *user,int snum)
{
pstring valid, invalid;
BOOL ret;
StrnCpy(valid, lp_valid_users(snum), sizeof(pstring));
StrnCpy(invalid, lp_invalid_users(snum), sizeof(pstring));
string_sub(valid,"%S",lp_servicename(snum));
string_sub(invalid,"%S",lp_servicename(snum));
ret = !user_in_list(user,invalid);
if (ret && valid && *valid) {
ret = user_in_list(user,valid);
}
if (ret && lp_onlyuser(snum)) {
char *user_list = lp_username(snum);
string_sub(user_list,"%S",lp_servicename(snum));
ret = user_in_list(user,user_list);
}
return(ret);
}

View File

@ -415,6 +415,7 @@ static int session_trust_account(connection_struct *conn, char *inbuf, char *out
char *smb_nt_passwd, int smb_nt_passlen)
{
struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */
uchar last_chal[8];
if (lp_security() == SEC_USER)
{
smb_trust_acct = getsmbpwnam(user);
@ -441,8 +442,8 @@ static int session_trust_account(connection_struct *conn, char *inbuf, char *out
SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
}
if (!smb_password_ok(smb_trust_acct, NULL, NULL, NULL,
if (!last_challenge(last_chal) ||
!smb_password_ok(smb_trust_acct, last_chal, NULL, NULL,
(unsigned char *)smb_passwd, smb_passlen,
(unsigned char *)smb_nt_passwd, smb_nt_passlen, NULL))
{

View File

@ -678,6 +678,18 @@ static void usage(char *pname)
}
#endif /* WITH_SSL */
#if 0
start_msrpc_agent("lsarpc");
#endif
add_msrpc_command_processor( "samr", "lsass", api_samr_rpc );
add_msrpc_command_processor( "srvsvc", "ntsvcs", api_srvsvc_rpc );
add_msrpc_command_processor( "wkssvc", "ntsvcs", api_wkssvc_rpc );
add_msrpc_command_processor( "browser", "ntsvcs", api_brs_rpc );
add_msrpc_command_processor( "svcctl", "ntsvcs", api_svcctl_rpc );
add_msrpc_command_processor( "NETLOGON", "lsass", api_netlog_rpc );
add_msrpc_command_processor( "winreg", "winreg", api_reg_rpc );
add_msrpc_command_processor( "spoolss", "spoolss", api_spoolss_rpc );
codepage_initialise(lp_client_code_page());
if (!pwdb_initialise(True))