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:
@ -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)
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -254,8 +254,9 @@ void start_msrpc_agent(char *pipe_name)
|
||||
0
|
||||
};
|
||||
|
||||
CatchChild();
|
||||
|
||||
start_agent(&va);
|
||||
if (fork() == 0)
|
||||
{
|
||||
start_agent(&va);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
289
source3/lib/passcheck.c
Normal 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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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
169
source3/lib/vuser.c
Normal 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
653
source3/lsarpcd/lsarpcd.c
Normal 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);
|
||||
}
|
401
source3/lsarpcd/lsarpcd_process.c
Normal file
401
source3/lsarpcd/lsarpcd_process.c
Normal 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);
|
||||
}
|
||||
}
|
@ -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
|
||||
********************************************************************/
|
||||
|
@ -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 */
|
||||
|
@ -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
61
source3/smbd/challenge.c
Normal 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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -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))
|
||||
{
|
||||
|
@ -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))
|
||||
|
Reference in New Issue
Block a user