mirror of
https://github.com/samba-team/samba.git
synced 2025-08-04 08:22:08 +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))
|
# These can be overridden by command line switches (see smbd(8))
|
||||||
# or in smb.conf (see smb.conf(5))
|
# or in smb.conf (see smb.conf(5))
|
||||||
SMBLOGFILE = $(VARDIR)/log.smb
|
SMBLOGFILE = $(VARDIR)/log.smb
|
||||||
|
LSARPCLOGFILE = $(VARDIR)/log.lsarpc
|
||||||
NMBLOGFILE = $(VARDIR)/log.nmb
|
NMBLOGFILE = $(VARDIR)/log.nmb
|
||||||
CONFIGFILE = $(LIBDIR)/smb.conf
|
CONFIGFILE = $(LIBDIR)/smb.conf
|
||||||
LMHOSTSFILE = $(LIBDIR)/lmhosts
|
LMHOSTSFILE = $(LIBDIR)/lmhosts
|
||||||
@ -77,14 +78,21 @@ PASSWD_FLAGS = \
|
|||||||
-DSMB_PASSGRP_FILE=\"$(SMB_PASSGRP_FILE)\" \
|
-DSMB_PASSGRP_FILE=\"$(SMB_PASSGRP_FILE)\" \
|
||||||
-DSMB_GROUP_FILE=\"$(SMB_GROUP_FILE)\" \
|
-DSMB_GROUP_FILE=\"$(SMB_GROUP_FILE)\" \
|
||||||
-DSMB_ALIAS_FILE=\"$(SMB_ALIAS_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)\"
|
FLAGS2 = -DCONFIGFILE=\"$(CONFIGFILE)\" -DLMHOSTSFILE=\"$(LMHOSTSFILE)\"
|
||||||
FLAGS3 = -DSWATDIR=\"$(SWATDIR)\" -DSBINDIR=\"$(SBINDIR)\" -DLOCKDIR=\"$(LOCKDIR)\" -DSMBRUN=\"$(SMBRUN)\" -DCODEPAGEDIR=\"$(CODEPAGEDIR)\"
|
FLAGS3 = -DSWATDIR=\"$(SWATDIR)\" -DSBINDIR=\"$(SBINDIR)\" -DLOCKDIR=\"$(LOCKDIR)\" -DSMBRUN=\"$(SMBRUN)\" -DCODEPAGEDIR=\"$(CODEPAGEDIR)\"
|
||||||
FLAGS4 = -DDRIVERFILE=\"$(DRIVERFILE)\" -DBINDIR=\"$(BINDIR)\" -DFORMSFILE=\"$(FORMSFILE)\" -DNTDRIVERSDIR=\"$(NTDRIVERSDIR)\"
|
FLAGS4 = -DDRIVERFILE=\"$(DRIVERFILE)\" -DBINDIR=\"$(BINDIR)\" -DFORMSFILE=\"$(FORMSFILE)\" -DNTDRIVERSDIR=\"$(NTDRIVERSDIR)\"
|
||||||
FLAGS5 = $(FLAGS1) $(FLAGS2) $(FLAGS3) $(FLAGS4) -DHAVE_INCLUDES_H
|
FLAGS5 = $(FLAGS1) $(FLAGS2) $(FLAGS3) $(FLAGS4) -DHAVE_INCLUDES_H
|
||||||
FLAGS = $(FLAGS5) $(PASSWD_FLAGS)
|
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
|
PROGS1 = bin/smbclient bin/testparm bin/testprns bin/smbrun bin/smbstatus
|
||||||
PROGS2 = bin/rpcclient bin/smbpasswd bin/make_smbcodepage bin/debug2html
|
PROGS2 = bin/rpcclient bin/smbpasswd bin/make_smbcodepage bin/debug2html
|
||||||
PROGS3 = @WRAP@ @WRAP32@
|
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/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/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/ufc.o lib/util.o lib/genrand.o lib/username.o \
|
||||||
|
lib/vuser.o \
|
||||||
lib/access.o lib/smbrun.o \
|
lib/access.o lib/smbrun.o \
|
||||||
lib/bitmap.o lib/crc32.o lib/util_sid.o lib/snprintf.o \
|
lib/bitmap.o lib/crc32.o lib/util_sid.o lib/snprintf.o \
|
||||||
lib/util_str.o lib/util_unistr.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_sock.o lib/unix_sec_ctxt.o \
|
||||||
lib/util_array.o \
|
lib/util_array.o \
|
||||||
lib/vagent.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_OBJ = ubiqx/ubi_BinTree.o ubiqx/ubi_Cache.o ubiqx/ubi_SplayTree.o \
|
||||||
ubiqx/ubi_dLinkList.o ubiqx/ubi_sLinkList.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/smberr.o libsmb/credentials.o libsmb/pwd_cache.o \
|
||||||
libsmb/passchange.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_lsa.o \
|
||||||
rpc_server/srv_netlog.o \
|
rpc_server/srv_netlog.o \
|
||||||
rpc_server/srv_pipe_hnd.o \
|
|
||||||
rpc_server/srv_reg.o \
|
rpc_server/srv_reg.o \
|
||||||
rpc_server/srv_samr.o \
|
rpc_server/srv_samr.o \
|
||||||
rpc_server/srv_srvsvc.o \
|
rpc_server/srv_srvsvc.o \
|
||||||
rpc_server/srv_svcctl.o \
|
rpc_server/srv_svcctl.o \
|
||||||
rpc_server/srv_pipe.o \
|
|
||||||
rpc_server/srv_lookup.o \
|
|
||||||
rpc_server/srv_wkssvc.o \
|
rpc_server/srv_wkssvc.o \
|
||||||
rpc_server/srv_brs.o \
|
rpc_server/srv_brs.o \
|
||||||
rpc_server/srv_spoolss.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_OBJ1 = rpc_parse/parse_lsa.o \
|
||||||
rpc_parse/parse_net.o \
|
rpc_parse/parse_net.o \
|
||||||
rpc_parse/parse_reg.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/$(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/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/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
|
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) \
|
SMBD_OBJ = $(SMBD_OBJ1) $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) \
|
||||||
$(RPC_SERVER_OBJ) $(RPC_CLIENT_OBJ) $(RPC_PARSE_OBJ) \
|
$(RPC_SERVER_OBJ) $(RPC_CLIENT_OBJ) $(RPC_PARSE_OBJ) \
|
||||||
$(LOCKING_OBJ) $(SAMPASSDB_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
|
$(LOCKING_OBJ) $(SAMPASSDB_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
|
||||||
$(LIBSTATUS_OBJ) $(PRINTING_OBJ) $(PROFILE_OBJ) $(LIB_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_OBJ1 = nmbd/asyncdns.o nmbd/nmbd.o nmbd/nmbd_become_dmb.o \
|
||||||
nmbd/nmbd_become_lmb.o nmbd/nmbd_browserdb.o \
|
nmbd/nmbd_become_lmb.o nmbd/nmbd_browserdb.o \
|
||||||
nmbd/nmbd_browsesync.o nmbd/nmbd_elections.o \
|
nmbd/nmbd_browsesync.o nmbd/nmbd_elections.o \
|
||||||
@ -331,7 +357,7 @@ RPCTORTURE_OBJ = utils/rpctorture.o \
|
|||||||
$(RPC_CLIENT_OBJ) $(RPC_PARSE_OBJ) \
|
$(RPC_CLIENT_OBJ) $(RPC_PARSE_OBJ) \
|
||||||
$(PASSDB_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)
|
$(RPCCLIENT_OBJ) $(SMBWRAPPER_OBJ)
|
||||||
|
|
||||||
PICOBJS = $(SMBWRAPPER_OBJ:.o=.po)
|
PICOBJS = $(SMBWRAPPER_OBJ:.o=.po)
|
||||||
@ -421,6 +447,10 @@ bin/smbd: $(SMBD_OBJ) bin/.dummy
|
|||||||
@echo Linking $@
|
@echo Linking $@
|
||||||
@$(CC) $(FLAGS) -o $@ $(SMBD_OBJ) $(LDFLAGS) $(LIBS)
|
@$(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
|
bin/nmbd: $(NMBD_OBJ) bin/.dummy
|
||||||
@echo Linking $@
|
@echo Linking $@
|
||||||
@$(CC) $(FLAGS) -o $@ $(NMBD_OBJ) $(LDFLAGS) $(LIBS)
|
@$(CC) $(FLAGS) -o $@ $(NMBD_OBJ) $(LDFLAGS) $(LIBS)
|
||||||
|
@ -74,6 +74,8 @@ typedef struct pipes_struct
|
|||||||
fstring name;
|
fstring name;
|
||||||
fstring pipe_srv_name;
|
fstring pipe_srv_name;
|
||||||
|
|
||||||
|
struct msrpc_state *m;
|
||||||
|
|
||||||
prs_struct rhdr; /* output header */
|
prs_struct rhdr; /* output header */
|
||||||
prs_struct rfault; /* fault */
|
prs_struct rfault; /* fault */
|
||||||
prs_struct rdata; /* output data */
|
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 */
|
/*The following definitions come from lib/msrpc-client.c */
|
||||||
|
|
||||||
BOOL msrpc_receive(struct msrpc_state *msrpc);
|
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_send(struct msrpc_state *msrpc, BOOL show);
|
||||||
BOOL msrpc_connect(struct msrpc_state *msrpc, const char *pipe_name);
|
BOOL msrpc_connect(struct msrpc_state *msrpc, const char *pipe_name);
|
||||||
void msrpc_init_creds(struct msrpc_state *msrpc, const struct user_credentials *usr);
|
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);
|
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 */
|
/*The following definitions come from lib/pidfile.c */
|
||||||
|
|
||||||
pid_t pidfile_pid(char *name);
|
pid_t pidfile_pid(char *name);
|
||||||
@ -429,6 +443,7 @@ char *uidtoname(uid_t uid);
|
|||||||
char *get_home_dir(char *user);
|
char *get_home_dir(char *user);
|
||||||
BOOL map_username(char *user);
|
BOOL map_username(char *user);
|
||||||
const struct passwd *Get_Pwnam(char *user,BOOL allow_change);
|
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);
|
BOOL user_in_list(char *user,char *list);
|
||||||
|
|
||||||
/*The following definitions come from lib/util.c */
|
/*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 free_sock_redir(struct vagent_ops*va);
|
||||||
void start_agent(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 */
|
/*The following definitions come from libsmb/clientgen.c */
|
||||||
|
|
||||||
void copy_user_creds(struct user_credentials *to,
|
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);
|
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 */
|
/*The following definitions come from mem_man/mem_man.c */
|
||||||
|
|
||||||
void *smb_mem_malloc(size_t size,char *file,int line);
|
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 */
|
/*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(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,
|
void prs_init(prs_struct *ps, uint32 size,
|
||||||
uint8 align, uint32 margin,
|
uint8 align, uint32 margin,
|
||||||
BOOL io);
|
BOOL io);
|
||||||
@ -3622,6 +3656,10 @@ BOOL api_netlog_rpc(pipes_struct *p, prs_struct *data);
|
|||||||
|
|
||||||
BOOL create_rpc_reply(pipes_struct *p,
|
BOOL create_rpc_reply(pipes_struct *p,
|
||||||
uint32 data_start, uint32 data_end);
|
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 rpc_command(pipes_struct *p, prs_struct *pd);
|
||||||
BOOL api_rpcTNP(pipes_struct *p, char *rpc_name, struct api_struct *api_rpc_cmds,
|
BOOL api_rpcTNP(pipes_struct *p, char *rpc_name, struct api_struct *api_rpc_cmds,
|
||||||
prs_struct *data);
|
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 remove_pending_lock_requests_by_mid(int mid);
|
||||||
void process_blocking_lock_queue(time_t t);
|
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 */
|
/*The following definitions come from smbd/chgpasswd.c */
|
||||||
|
|
||||||
BOOL chgpasswd(char *name,char *oldpass,char *newpass, BOOL as_root);
|
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 */
|
/*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);
|
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,
|
BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd,
|
||||||
uchar user_sess_key[16]);
|
uchar user_sess_key[16]);
|
||||||
BOOL user_ok(char *user,int snum);
|
|
||||||
BOOL authorise_login(int snum,char *user,char *password, int pwlen,
|
BOOL authorise_login(int snum,char *user,char *password, int pwlen,
|
||||||
BOOL *guest,BOOL *force,uint16 vuid);
|
BOOL *guest,BOOL *force,uint16 vuid);
|
||||||
BOOL check_hosts_equiv(char *user);
|
BOOL check_hosts_equiv(char *user);
|
||||||
|
@ -254,8 +254,9 @@ void start_msrpc_agent(char *pipe_name)
|
|||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
CatchChild();
|
if (fork() == 0)
|
||||||
|
{
|
||||||
start_agent(&va);
|
start_agent(&va);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +34,54 @@ BOOL msrpc_receive(struct msrpc_state *msrpc)
|
|||||||
return receive_smb(msrpc->fd,msrpc->inbuf,0);
|
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
|
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;
|
return True;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
open the msrpcent sockets
|
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 char* pipe_name,
|
||||||
const struct user_credentials *usr)
|
const struct user_credentials *usr)
|
||||||
{
|
{
|
||||||
@ -135,7 +181,7 @@ static int msrpc_init_redirect(struct msrpc_state *msrpc,
|
|||||||
|
|
||||||
if (sock < 0)
|
if (sock < 0)
|
||||||
{
|
{
|
||||||
return sock;
|
return False;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZERO_STRUCT(data);
|
ZERO_STRUCT(data);
|
||||||
@ -196,7 +242,7 @@ static int msrpc_init_redirect(struct msrpc_state *msrpc,
|
|||||||
msrpc->fd = sock;
|
msrpc->fd = sock;
|
||||||
msrpc->usr.reuse = False;
|
msrpc->usr.reuse = False;
|
||||||
|
|
||||||
return sock;
|
return True;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL msrpc_connect_auth(struct msrpc_state *msrpc,
|
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;
|
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
|
check if a user is in a user list - can check combinations of UNIX
|
||||||
and netgroup lists.
|
and netgroup lists.
|
||||||
|
@ -901,6 +901,9 @@ int create_pipe_socket(char *dir, int dir_perms,
|
|||||||
int s;
|
int s;
|
||||||
struct sockaddr_un sa;
|
struct sockaddr_un sa;
|
||||||
|
|
||||||
|
DEBUG(10,("create_pipe_socket: %s %d %s %d\n",
|
||||||
|
dir, dir_perms, path, path_perms));
|
||||||
|
|
||||||
mkdir(dir, dir_perms);
|
mkdir(dir, dir_perms);
|
||||||
|
|
||||||
if (chmod(dir, dir_perms) < 0)
|
if (chmod(dir, dir_perms) < 0)
|
||||||
@ -912,7 +915,6 @@ int create_pipe_socket(char *dir, int dir_perms,
|
|||||||
if (!remove(path))
|
if (!remove(path))
|
||||||
{
|
{
|
||||||
DEBUG(0, ("remove on %s failed\n", path));
|
DEBUG(0, ("remove on %s failed\n", path));
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* start listening on unix socket */
|
/* start listening on unix socket */
|
||||||
@ -954,5 +956,7 @@ int create_pipe_socket(char *dir, int dir_perms,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEBUG(5,("unix socket opened: %s\n", path));
|
||||||
|
|
||||||
return s;
|
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(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
|
initialise a parse structure
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
|
@ -396,7 +396,69 @@ struct api_cmd
|
|||||||
BOOL (*fn) (pipes_struct *, prs_struct *);
|
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 },
|
{ "lsarpc", "lsass", api_ntlsa_rpc },
|
||||||
{ "samr", "lsass", api_samr_rpc },
|
{ "samr", "lsass", api_samr_rpc },
|
||||||
@ -409,6 +471,20 @@ static struct api_cmd api_fd_commands[] =
|
|||||||
{ "spoolss", "spoolss", api_spoolss_rpc },
|
{ "spoolss", "spoolss", api_spoolss_rpc },
|
||||||
{ NULL, NULL, NULL }
|
{ 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)
|
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__));
|
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) &&
|
if (strequal(api_fd_commands[i]->pipe_clnt_name, p->name) &&
|
||||||
api_fd_commands[i].fn != NULL)
|
api_fd_commands[i]->fn != NULL)
|
||||||
{
|
{
|
||||||
DEBUG(3,("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n",
|
DEBUG(3,("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n",
|
||||||
api_fd_commands[i].pipe_clnt_name,
|
api_fd_commands[i]->pipe_clnt_name,
|
||||||
api_fd_commands[i].pipe_srv_name));
|
api_fd_commands[i]->pipe_srv_name));
|
||||||
fstrcpy(p->pipe_srv_name, api_fd_commands[i].pipe_srv_name);
|
fstrcpy(p->pipe_srv_name, api_fd_commands[i]->pipe_srv_name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (api_fd_commands[i].fn == NULL) return False;
|
if (api_fd_commands[i]->fn == NULL) return False;
|
||||||
|
|
||||||
/* decode the bind request */
|
/* decode the bind request */
|
||||||
smb_io_rpc_hdr_rb("", &p->hdr_rb, pd, 0);
|
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
|
#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) &&
|
if (strequal(api_fd_commands[i]->pipe_clnt_name, p->name) &&
|
||||||
api_fd_commands[i].fn != NULL)
|
api_fd_commands[i]->fn != NULL)
|
||||||
{
|
{
|
||||||
DEBUG(3,("Doing \\PIPE\\%s\n", api_fd_commands[i].pipe_clnt_name));
|
DEBUG(3,("Doing \\PIPE\\%s\n", api_fd_commands[i]->pipe_clnt_name));
|
||||||
return api_fd_commands[i].fn(p, pd);
|
return api_fd_commands[i]->fn(p, pd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return False;
|
return False;
|
||||||
@ -744,6 +820,24 @@ BOOL rpc_command(pipes_struct *p, prs_struct *pd)
|
|||||||
BOOL reply = False;
|
BOOL reply = False;
|
||||||
DEBUG(10,("rpc_command\n"));
|
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;
|
if (pd->data == NULL) return False;
|
||||||
|
|
||||||
/* process the rpc header */
|
/* process the rpc header */
|
||||||
|
@ -83,6 +83,7 @@ pipes_struct *open_rpc_pipe_p(char *pipe_name,
|
|||||||
int i;
|
int i;
|
||||||
pipes_struct *p;
|
pipes_struct *p;
|
||||||
static int next_pipe;
|
static int next_pipe;
|
||||||
|
struct msrpc_state *m = NULL;
|
||||||
|
|
||||||
DEBUG(4,("Open pipe requested %s (pipes_open=%d)\n",
|
DEBUG(4,("Open pipe requested %s (pipes_open=%d)\n",
|
||||||
pipe_name, pipes_open));
|
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));
|
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));
|
p = (pipes_struct *)malloc(sizeof(*p));
|
||||||
if (!p) return NULL;
|
if (!p) return NULL;
|
||||||
|
|
||||||
@ -120,6 +131,7 @@ pipes_struct *open_rpc_pipe_p(char *pipe_name,
|
|||||||
pipes_open++;
|
pipes_open++;
|
||||||
|
|
||||||
p->pnum = i;
|
p->pnum = i;
|
||||||
|
p->m = m;
|
||||||
|
|
||||||
p->open = True;
|
p->open = True;
|
||||||
p->device_state = 0;
|
p->device_state = 0;
|
||||||
@ -359,6 +371,19 @@ BOOL close_rpc_pipe_hnd(pipes_struct *p, connection_struct *conn)
|
|||||||
|
|
||||||
DLIST_REMOVE(Pipes, p);
|
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);
|
ZERO_STRUCTP(p);
|
||||||
|
|
||||||
free(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 pstring global_myname;
|
||||||
extern fstring global_myworkgroup;
|
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
|
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
|
check if a username/password pair is OK either via the system password
|
||||||
database or the encrypted SMB password database
|
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);
|
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)
|
char *smb_nt_passwd, int smb_nt_passlen)
|
||||||
{
|
{
|
||||||
struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */
|
struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */
|
||||||
|
uchar last_chal[8];
|
||||||
if (lp_security() == SEC_USER)
|
if (lp_security() == SEC_USER)
|
||||||
{
|
{
|
||||||
smb_trust_acct = getsmbpwnam(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);
|
SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
|
||||||
return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
|
return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
|
||||||
}
|
}
|
||||||
|
if (!last_challenge(last_chal) ||
|
||||||
if (!smb_password_ok(smb_trust_acct, NULL, NULL, NULL,
|
!smb_password_ok(smb_trust_acct, last_chal, NULL, NULL,
|
||||||
(unsigned char *)smb_passwd, smb_passlen,
|
(unsigned char *)smb_passwd, smb_passlen,
|
||||||
(unsigned char *)smb_nt_passwd, smb_nt_passlen, NULL))
|
(unsigned char *)smb_nt_passwd, smb_nt_passlen, NULL))
|
||||||
{
|
{
|
||||||
|
@ -678,6 +678,18 @@ static void usage(char *pname)
|
|||||||
}
|
}
|
||||||
#endif /* WITH_SSL */
|
#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());
|
codepage_initialise(lp_client_code_page());
|
||||||
|
|
||||||
if (!pwdb_initialise(True))
|
if (!pwdb_initialise(True))
|
||||||
|
Reference in New Issue
Block a user