summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
authorLuke Leighton <lkcl@samba.org>1999-12-06 00:44:32 +0000
committerLuke Leighton <lkcl@samba.org>1999-12-06 00:44:32 +0000
commita0ba234cf9b40adf6b5390e4e67730163a42883f (patch)
treefea2f70b2ac98de4e2c7fd218e06ea7a38f2d04d /source3
parent7c53f158bab61bca704340ce70f4039a178d0fde (diff)
downloadsamba-a0ba234cf9b40adf6b5390e4e67730163a42883f.tar.gz
samba-a0ba234cf9b40adf6b5390e4e67730163a42883f.tar.bz2
samba-a0ba234cf9b40adf6b5390e4e67730163a42883f.zip
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 2245b0c6d13c7c5886e81f9137b05df883598c26)
Diffstat (limited to 'source3')
-rw-r--r--source3/Makefile.in48
-rw-r--r--source3/include/ntdomain.h2
-rw-r--r--source3/include/proto.h60
-rw-r--r--source3/lib/msrpc-agent.c7
-rw-r--r--source3/lib/msrpc-client.c56
-rw-r--r--source3/lib/passcheck.c289
-rw-r--r--source3/lib/username.c29
-rw-r--r--source3/lib/util_sock.c6
-rw-r--r--source3/lib/vuser.c169
-rw-r--r--source3/lsarpcd/lsarpcd.c653
-rw-r--r--source3/lsarpcd/lsarpcd_process.c401
-rw-r--r--source3/rpc_parse/parse_prs.c10
-rw-r--r--source3/rpc_server/srv_pipe.c120
-rw-r--r--source3/rpc_server/srv_pipe_hnd.c25
-rw-r--r--source3/smbd/challenge.c61
-rw-r--r--source3/smbd/password.c501
-rw-r--r--source3/smbd/reply.c5
-rw-r--r--source3/smbd/server.c12
18 files changed, 1904 insertions, 550 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index 6dac160ffe..2ded87c858 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -37,6 +37,7 @@ INSTALLPERMS = 0755
# These can be overridden by command line switches (see smbd(8))
# or in smb.conf (see smb.conf(5))
SMBLOGFILE = $(VARDIR)/log.smb
+LSARPCLOGFILE = $(VARDIR)/log.lsarpc
NMBLOGFILE = $(VARDIR)/log.nmb
CONFIGFILE = $(LIBDIR)/smb.conf
LMHOSTSFILE = $(LIBDIR)/lmhosts
@@ -77,14 +78,21 @@ PASSWD_FLAGS = \
-DSMB_PASSGRP_FILE=\"$(SMB_PASSGRP_FILE)\" \
-DSMB_GROUP_FILE=\"$(SMB_GROUP_FILE)\" \
-DSMB_ALIAS_FILE=\"$(SMB_ALIAS_FILE)\"
-FLAGS1 = $(CFLAGS) -Iinclude -I$(srcdir)/include -I$(srcdir)/ubiqx -I$(srcdir)/smbwrapper $(CPPFLAGS) -DSMBLOGFILE=\"$(SMBLOGFILE)\" -DNMBLOGFILE=\"$(NMBLOGFILE)\"
+FLAGS1 = $(CFLAGS) \
+ -Iinclude -I$(srcdir)/include \
+ -I$(srcdir)/ubiqx \
+ -I$(srcdir)/smbwrapper \
+ $(CPPFLAGS) \
+ -DLSARPCLOGFILE=\"$(LSARPCLOGFILE)\" \
+ -DSMBLOGFILE=\"$(SMBLOGFILE)\" \
+ -DNMBLOGFILE=\"$(NMBLOGFILE)\"
FLAGS2 = -DCONFIGFILE=\"$(CONFIGFILE)\" -DLMHOSTSFILE=\"$(LMHOSTSFILE)\"
FLAGS3 = -DSWATDIR=\"$(SWATDIR)\" -DSBINDIR=\"$(SBINDIR)\" -DLOCKDIR=\"$(LOCKDIR)\" -DSMBRUN=\"$(SMBRUN)\" -DCODEPAGEDIR=\"$(CODEPAGEDIR)\"
FLAGS4 = -DDRIVERFILE=\"$(DRIVERFILE)\" -DBINDIR=\"$(BINDIR)\" -DFORMSFILE=\"$(FORMSFILE)\" -DNTDRIVERSDIR=\"$(NTDRIVERSDIR)\"
FLAGS5 = $(FLAGS1) $(FLAGS2) $(FLAGS3) $(FLAGS4) -DHAVE_INCLUDES_H
FLAGS = $(FLAGS5) $(PASSWD_FLAGS)
-SPROGS = bin/smbd bin/nmbd bin/swat
+SPROGS = bin/smbd bin/lsarpcd bin/nmbd bin/swat
PROGS1 = bin/smbclient bin/testparm bin/testprns bin/smbrun bin/smbstatus
PROGS2 = bin/rpcclient bin/smbpasswd bin/make_smbcodepage bin/debug2html
PROGS3 = @WRAP@ @WRAP32@
@@ -107,6 +115,7 @@ LIB_OBJ = lib/charcnv.o lib/charset.o lib/debug.o lib/fault.o \
lib/membuffer.o lib/netmask.o lib/pidfile.o lib/replace.o \
lib/signal.o lib/slprintf.o lib/system.o lib/doscalls.o lib/time.o \
lib/ufc.o lib/util.o lib/genrand.o lib/username.o \
+ lib/vuser.o \
lib/access.o lib/smbrun.o \
lib/bitmap.o lib/crc32.o lib/util_sid.o lib/snprintf.o \
lib/util_str.o lib/util_unistr.o \
@@ -114,7 +123,8 @@ LIB_OBJ = lib/charcnv.o lib/charset.o lib/debug.o lib/fault.o \
lib/util_sock.o lib/unix_sec_ctxt.o \
lib/util_array.o \
lib/vagent.o \
- lib/util_hnd.o
+ lib/util_hnd.o \
+ lib/passcheck.o
UBIQX_OBJ = ubiqx/ubi_BinTree.o ubiqx/ubi_Cache.o ubiqx/ubi_SplayTree.o \
ubiqx/ubi_dLinkList.o ubiqx/ubi_sLinkList.o
@@ -126,20 +136,24 @@ LIBSMB_OBJ = libsmb/clientgen.o libsmb/namequery.o libsmb/nmblib.o \
libsmb/smberr.o libsmb/credentials.o libsmb/pwd_cache.o \
libsmb/passchange.o
-RPC_SERVER_OBJ = \
+RPC_SRVUTIL_OBJ = \
+ rpc_server/srv_pipe_hnd.o \
+ rpc_server/srv_lookup.o \
+ rpc_server/srv_pipe.o
+
+RPC_SERVER_OBJ1 = \
rpc_server/srv_lsa.o \
rpc_server/srv_netlog.o \
- rpc_server/srv_pipe_hnd.o \
rpc_server/srv_reg.o \
rpc_server/srv_samr.o \
rpc_server/srv_srvsvc.o \
rpc_server/srv_svcctl.o \
- rpc_server/srv_pipe.o \
- rpc_server/srv_lookup.o \
rpc_server/srv_wkssvc.o \
rpc_server/srv_brs.o \
rpc_server/srv_spoolss.o
+RPC_SERVER_OBJ = $(RPC_SERVER_OBJ1) $(RPC_SRVUTIL_OBJ)
+
RPC_PARSE_OBJ1 = rpc_parse/parse_lsa.o \
rpc_parse/parse_net.o \
rpc_parse/parse_reg.o \
@@ -204,16 +218,28 @@ SMBD_OBJ1 = smbd/server.o smbd/files.o smbd/chgpasswd.o smbd/connection.o \
smbd/$(QUOTAOBJS) smbd/reply.o smbd/ssl.o smbd/trans2.o smbd/uid.o \
smbd/dosmode.o smbd/filename.o smbd/open.o smbd/close.o smbd/blocking.o \
smbd/process.o smbd/oplock.o smbd/service.o smbd/error.o smbd/vfs.o \
- smbd/vfs-wrap.o printing/nt_printing.o smbd/dfs.o
+ smbd/vfs-wrap.o printing/nt_printing.o smbd/dfs.o \
+ smbd/challenge.o
PRINTING_OBJ = printing/pcap.o printing/print_svid.o printing/printing.o
+LSARPCD_OBJ1 = lsarpcd/lsarpcd.o \
+ lsarpcd/lsarpcd_process.o \
+ rpc_server/srv_lsa.o \
+ smbd/uid.o
+
SMBD_OBJ = $(SMBD_OBJ1) $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) \
$(RPC_SERVER_OBJ) $(RPC_CLIENT_OBJ) $(RPC_PARSE_OBJ) \
$(LOCKING_OBJ) $(SAMPASSDB_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
$(LIBSTATUS_OBJ) $(PRINTING_OBJ) $(PROFILE_OBJ) $(LIB_OBJ)
+LSARPCD_OBJ = $(LSARPCD_OBJ1) $(PARAM_OBJ) $(LIBSMB_OBJ) \
+ $(UBIQX_OBJ) \
+ $(RPC_SRVUTIL_OBJ) $(RPC_CLIENT_OBJ) $(RPC_PARSE_OBJ) \
+ $(LOCKING_OBJ) $(SAMPASSDB_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
+ $(LIBSTATUS_OBJ) $(PRINTING_OBJ) $(PROFILE_OBJ) $(LIB_OBJ)
+
NMBD_OBJ1 = nmbd/asyncdns.o nmbd/nmbd.o nmbd/nmbd_become_dmb.o \
nmbd/nmbd_become_lmb.o nmbd/nmbd_browserdb.o \
nmbd/nmbd_browsesync.o nmbd/nmbd_elections.o \
@@ -331,7 +357,7 @@ RPCTORTURE_OBJ = utils/rpctorture.o \
$(RPC_CLIENT_OBJ) $(RPC_PARSE_OBJ) \
$(PASSDB_OBJ)
-PROTO_OBJ = $(SMBD_OBJ) $(NMBD_OBJ) $(SWAT_OBJ) $(CLIENT_OBJ) \
+PROTO_OBJ = $(LSARPCD_OBJ) $(SMBD_OBJ) $(NMBD_OBJ) $(SWAT_OBJ) $(CLIENT_OBJ) \
$(RPCCLIENT_OBJ) $(SMBWRAPPER_OBJ)
PICOBJS = $(SMBWRAPPER_OBJ:.o=.po)
@@ -421,6 +447,10 @@ bin/smbd: $(SMBD_OBJ) bin/.dummy
@echo Linking $@
@$(CC) $(FLAGS) -o $@ $(SMBD_OBJ) $(LDFLAGS) $(LIBS)
+bin/lsarpcd: $(LSARPCD_OBJ) bin/.dummy
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(LSARPCD_OBJ) $(LDFLAGS) $(LIBS)
+
bin/nmbd: $(NMBD_OBJ) bin/.dummy
@echo Linking $@
@$(CC) $(FLAGS) -o $@ $(NMBD_OBJ) $(LDFLAGS) $(LIBS)
diff --git a/source3/include/ntdomain.h b/source3/include/ntdomain.h
index 9dd6c2d3a7..95ba141b10 100644
--- a/source3/include/ntdomain.h
+++ b/source3/include/ntdomain.h
@@ -74,6 +74,8 @@ typedef struct pipes_struct
fstring name;
fstring pipe_srv_name;
+ struct msrpc_state *m;
+
prs_struct rhdr; /* output header */
prs_struct rfault; /* fault */
prs_struct rdata; /* output data */
diff --git a/source3/include/proto.h b/source3/include/proto.h
index ed1f1aef58..b94e13aa0e 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -287,6 +287,8 @@ void start_msrpc_agent(char *pipe_name);
/*The following definitions come from lib/msrpc-client.c */
BOOL msrpc_receive(struct msrpc_state *msrpc);
+BOOL msrpc_send_prs(struct msrpc_state *msrpc, prs_struct *ps);
+BOOL msrpc_receive_prs(struct msrpc_state *msrpc, prs_struct *ps);
BOOL msrpc_send(struct msrpc_state *msrpc, BOOL show);
BOOL msrpc_connect(struct msrpc_state *msrpc, const char *pipe_name);
void msrpc_init_creds(struct msrpc_state *msrpc, const struct user_credentials *usr);
@@ -317,6 +319,18 @@ void msrpc_net_use_enum(uint32 *num_cons, struct use_info ***use);
int get_netmask(struct in_addr *ipaddr, struct in_addr *nmask);
+/*The following definitions come from lib/passcheck.c */
+
+BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar challenge[8],
+ const char *user, const char *domain,
+ uchar *lm_pass, size_t lm_pwd_len,
+ uchar *nt_pass, size_t nt_pwd_len,
+ uchar sess_key[16]);
+BOOL pass_check_smb(struct smb_passwd *smb_pass, char *domain, uchar *chal,
+ uchar *lm_pwd, size_t lm_pwd_len,
+ uchar *nt_pwd, size_t nt_pwd_len,
+ struct passwd *pwd, uchar user_sess_key[16]);
+
/*The following definitions come from lib/pidfile.c */
pid_t pidfile_pid(char *name);
@@ -429,6 +443,7 @@ char *uidtoname(uid_t uid);
char *get_home_dir(char *user);
BOOL map_username(char *user);
const struct passwd *Get_Pwnam(char *user,BOOL allow_change);
+BOOL user_ok(char *user,int snum);
BOOL user_in_list(char *user,char *list);
/*The following definitions come from lib/util.c */
@@ -716,6 +731,13 @@ void init_sock_redir(struct vagent_ops*va);
void free_sock_redir(struct vagent_ops*va);
void start_agent(struct vagent_ops *va);
+/*The following definitions come from lib/vuser.c */
+
+user_struct *get_valid_user_struct(uint16 vuid);
+void invalidate_vuid(uint16 vuid);
+char *validated_username(uint16 vuid);
+uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, BOOL guest, uchar user_sess_key[16]);
+
/*The following definitions come from libsmb/clientgen.c */
void copy_user_creds(struct user_credentials *to,
@@ -1016,6 +1038,17 @@ struct shmem_ops *smb_shm_open(int ronly);
struct shmem_ops *sysv_shm_open(int ronly);
+/*The following definitions come from lsarpcd/lsarpcd.c */
+
+BOOL reload_services(BOOL test);
+void exit_server(char *reason);
+
+/*The following definitions come from lsarpcd/lsarpcd_process.c */
+
+BOOL receive_next_smb(char *inbuf, int bufsize, int timeout);
+void process_smb(char *inbuf, char *outbuf);
+void lsarpcd_process(void);
+
/*The following definitions come from mem_man/mem_man.c */
void *smb_mem_malloc(size_t size,char *file,int line);
@@ -2697,6 +2730,7 @@ BOOL net_io_r_sam_sync(char *desc, uint8 sess_key[16],
/*The following definitions come from rpc_parse/parse_prs.c */
void prs_debug(prs_struct *ps, int depth, char *desc, char *fn_name);
+void prs_debug_out(prs_struct *ps, int level);
void prs_init(prs_struct *ps, uint32 size,
uint8 align, uint32 margin,
BOOL io);
@@ -3622,6 +3656,10 @@ BOOL api_netlog_rpc(pipes_struct *p, prs_struct *data);
BOOL create_rpc_reply(pipes_struct *p,
uint32 data_start, uint32 data_end);
+void close_msrpc_command_processor(void);
+void add_msrpc_command_processor(char* pipe_name,
+ char* process_name,
+ BOOL (*fn) (pipes_struct *, prs_struct *));
BOOL rpc_command(pipes_struct *p, prs_struct *pd);
BOOL api_rpcTNP(pipes_struct *p, char *rpc_name, struct api_struct *api_rpc_cmds,
prs_struct *data);
@@ -3977,6 +4015,12 @@ void remove_pending_lock_requests_by_fid(files_struct *fsp);
void remove_pending_lock_requests_by_mid(int mid);
void process_blocking_lock_queue(time_t t);
+/*The following definitions come from smbd/challenge.c */
+
+void generate_next_challenge(char *challenge);
+BOOL set_challenge(unsigned char *challenge);
+BOOL last_challenge(unsigned char *challenge);
+
/*The following definitions come from smbd/chgpasswd.c */
BOOL chgpasswd(char *name,char *oldpass,char *newpass, BOOL as_root);
@@ -4181,25 +4225,9 @@ void check_kernel_oplocks(void);
/*The following definitions come from smbd/password.c */
-void generate_next_challenge(char *challenge);
-BOOL set_challenge(unsigned char *challenge);
-user_struct *get_valid_user_struct(uint16 vuid);
-void invalidate_vuid(uint16 vuid);
-char *validated_username(uint16 vuid);
-uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, BOOL guest, uchar user_sess_key[16]);
void add_session_user(char *user);
-BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar chal[8],
- const char *user, const char *domain,
- uchar *lm_pass, size_t lm_pwd_len,
- uchar *nt_pass, size_t nt_pwd_len,
- uchar sess_key[16]);
-BOOL pass_check_smb(struct smb_passwd *smb_pass, char *domain, uchar *chal,
- uchar *lm_pwd, size_t lm_pwd_len,
- uchar *nt_pwd, size_t nt_pwd_len,
- struct passwd *pwd, uchar user_sess_key[16]);
BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd,
uchar user_sess_key[16]);
-BOOL user_ok(char *user,int snum);
BOOL authorise_login(int snum,char *user,char *password, int pwlen,
BOOL *guest,BOOL *force,uint16 vuid);
BOOL check_hosts_equiv(char *user);
diff --git a/source3/lib/msrpc-agent.c b/source3/lib/msrpc-agent.c
index 4612aae14f..0bb9429ecb 100644
--- a/source3/lib/msrpc-agent.c
+++ b/source3/lib/msrpc-agent.c
@@ -254,8 +254,9 @@ void start_msrpc_agent(char *pipe_name)
0
};
- CatchChild();
-
- start_agent(&va);
+ if (fork() == 0)
+ {
+ start_agent(&va);
+ }
}
diff --git a/source3/lib/msrpc-client.c b/source3/lib/msrpc-client.c
index eacc25341e..fb82c54700 100644
--- a/source3/lib/msrpc-client.c
+++ b/source3/lib/msrpc-client.c
@@ -37,6 +37,54 @@ BOOL msrpc_receive(struct msrpc_state *msrpc)
/****************************************************************************
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
+****************************************************************************/
BOOL msrpc_send(struct msrpc_state *msrpc, BOOL show)
{
size_t len;
@@ -62,8 +110,6 @@ BOOL msrpc_send(struct msrpc_state *msrpc, BOOL show)
return True;
}
-
-
/****************************************************************************
open the msrpcent sockets
****************************************************************************/
@@ -115,7 +161,7 @@ void msrpc_sockopt(struct msrpc_state *msrpc, char *options)
}
-static int msrpc_init_redirect(struct msrpc_state *msrpc,
+static BOOL msrpc_init_redirect(struct msrpc_state *msrpc,
const char* pipe_name,
const struct user_credentials *usr)
{
@@ -135,7 +181,7 @@ static int msrpc_init_redirect(struct msrpc_state *msrpc,
if (sock < 0)
{
- return sock;
+ return False;
}
ZERO_STRUCT(data);
@@ -196,7 +242,7 @@ static int msrpc_init_redirect(struct msrpc_state *msrpc,
msrpc->fd = sock;
msrpc->usr.reuse = False;
- return sock;
+ return True;
}
BOOL msrpc_connect_auth(struct msrpc_state *msrpc,
diff --git a/source3/lib/passcheck.c b/source3/lib/passcheck.c
new file mode 100644
index 0000000000..195a404ff3
--- /dev/null
+++ b/source3/lib/passcheck.c
@@ -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;
+}
+
diff --git a/source3/lib/username.c b/source3/lib/username.c
index 87fe39466f..9f51d06642 100644
--- a/source3/lib/username.c
+++ b/source3/lib/username.c
@@ -566,6 +566,35 @@ static BOOL user_in_group_list(char *user,char *gname)
}
/****************************************************************************
+check if a username is valid
+****************************************************************************/
+BOOL user_ok(char *user,int snum)
+{
+ pstring valid, invalid;
+ BOOL ret;
+
+ StrnCpy(valid, lp_valid_users(snum), sizeof(pstring));
+ StrnCpy(invalid, lp_invalid_users(snum), sizeof(pstring));
+
+ string_sub(valid,"%S",lp_servicename(snum));
+ string_sub(invalid,"%S",lp_servicename(snum));
+
+ ret = !user_in_list(user,invalid);
+
+ if (ret && valid && *valid) {
+ ret = user_in_list(user,valid);
+ }
+
+ if (ret && lp_onlyuser(snum)) {
+ char *user_list = lp_username(snum);
+ string_sub(user_list,"%S",lp_servicename(snum));
+ ret = user_in_list(user,user_list);
+ }
+
+ return(ret);
+}
+
+/****************************************************************************
check if a user is in a user list - can check combinations of UNIX
and netgroup lists.
****************************************************************************/
diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c
index 71e51d2771..d9b0f97259 100644
--- a/source3/lib/util_sock.c
+++ b/source3/lib/util_sock.c
@@ -901,6 +901,9 @@ int create_pipe_socket(char *dir, int dir_perms,
int s;
struct sockaddr_un sa;
+ DEBUG(10,("create_pipe_socket: %s %d %s %d\n",
+ dir, dir_perms, path, path_perms));
+
mkdir(dir, dir_perms);
if (chmod(dir, dir_perms) < 0)
@@ -912,7 +915,6 @@ int create_pipe_socket(char *dir, int dir_perms,
if (!remove(path))
{
DEBUG(0, ("remove on %s failed\n", path));
- return -1;
}
/* start listening on unix socket */
@@ -954,5 +956,7 @@ int create_pipe_socket(char *dir, int dir_perms,
return -1;
}
+ DEBUG(5,("unix socket opened: %s\n", path));
+
return s;
}
diff --git a/source3/lib/vuser.c b/source3/lib/vuser.c
new file mode 100644
index 0000000000..dfad258152
--- /dev/null
+++ b/source3/lib/vuser.c
@@ -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);
+}
+
diff --git a/source3/lsarpcd/lsarpcd.c b/source3/lsarpcd/lsarpcd.c
new file mode 100644
index 0000000000..3c883029f0
--- /dev/null
+++ b/source3/lsarpcd/lsarpcd.c
@@ -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);
+}
diff --git a/source3/lsarpcd/lsarpcd_process.c b/source3/lsarpcd/lsarpcd_process.c
new file mode 100644
index 0000000000..f54c41bcb4
--- /dev/null
+++ b/source3/lsarpcd/lsarpcd_process.c
@@ -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);
+ }
+}
diff --git a/source3/rpc_parse/parse_prs.c b/source3/rpc_parse/parse_prs.c
index bf4efbe527..f53b2da955 100644
--- a/source3/rpc_parse/parse_prs.c
+++ b/source3/rpc_parse/parse_prs.c
@@ -37,6 +37,16 @@ void prs_debug(prs_struct *ps, int depth, char *desc, char *fn_name)
}
/*******************************************************************
+ 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
********************************************************************/
void prs_init(prs_struct *ps, uint32 size,
diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c
index c4664f7d7b..04fa0955ea 100644
--- a/source3/rpc_server/srv_pipe.c
+++ b/source3/rpc_server/srv_pipe.c
@@ -396,7 +396,69 @@ struct api_cmd
BOOL (*fn) (pipes_struct *, prs_struct *);
};
-static struct api_cmd api_fd_commands[] =
+static struct api_cmd **api_fd_commands = NULL;
+uint32 num_cmds = 0;
+
+static void api_cmd_free(struct api_cmd *item)
+{
+ if (item != NULL)
+ {
+ if (item->pipe_clnt_name != NULL)
+ {
+ free(item->pipe_clnt_name);
+ }
+ if (item->pipe_srv_name != NULL)
+ {
+ free(item->pipe_srv_name);
+ }
+ free(item);
+ }
+}
+
+static struct api_cmd *api_cmd_dup(const struct api_cmd *from)
+{
+ struct api_cmd *copy = NULL;
+ if (from == NULL)
+ {
+ return NULL;
+ }
+ copy = (struct api_cmd *) malloc(sizeof(struct api_cmd));
+ if (copy != NULL)
+ {
+ ZERO_STRUCTP(copy);
+ if (from->pipe_clnt_name != NULL)
+ {
+ copy->pipe_clnt_name = strdup(from->pipe_clnt_name );
+ }
+ if (from->pipe_srv_name != NULL)
+ {
+ copy->pipe_srv_name = strdup(from->pipe_srv_name);
+ }
+ if (from->fn != NULL)
+ {
+ copy->fn = from->fn;
+ }
+ }
+ return copy;
+}
+
+static void free_api_cmd_array(uint32 num_entries, struct api_cmd **entries)
+{
+ void(*fn)(void*) = (void(*)(void*))&api_cmd_free;
+ free_void_array(num_entries, (void**)entries, *fn);
+}
+
+static struct api_cmd* add_api_cmd_to_array(uint32 *len,
+ struct api_cmd ***array,
+ const struct api_cmd *name)
+{
+ void*(*fn)(const void*) = (void*(*)(const void*))&api_cmd_dup;
+ return (struct api_cmd*)add_copy_to_array(len,
+ (void***)array, (const void*)name, *fn, False);
+
+}
+
+#if 0
{
{ "lsarpc", "lsass", api_ntlsa_rpc },
{ "samr", "lsass", api_samr_rpc },
@@ -409,6 +471,20 @@ static struct api_cmd api_fd_commands[] =
{ "spoolss", "spoolss", api_spoolss_rpc },
{ NULL, NULL, NULL }
};
+#endif
+
+void close_msrpc_command_processor(void)
+{
+ free_api_cmd_array(num_cmds, api_fd_commands);
+}
+
+void add_msrpc_command_processor(char* pipe_name,
+ char* process_name,
+ BOOL (*fn) (pipes_struct *, prs_struct *))
+{
+ struct api_cmd cmd = { pipe_name, process_name, fn };
+ add_api_cmd_to_array(&num_cmds, &api_fd_commands, &cmd);
+}
static BOOL api_pipe_bind_auth_resp(pipes_struct *p, prs_struct *pd)
{
@@ -479,20 +555,20 @@ static BOOL api_pipe_bind_and_alt_req(pipes_struct *p, prs_struct *pd, enum RPC_
DEBUG(5,("api_pipe_bind_req: decode request. %d\n", __LINE__));
- for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
+ for (i = 0; i < num_cmds; i++)
{
- if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
- api_fd_commands[i].fn != NULL)
+ if (strequal(api_fd_commands[i]->pipe_clnt_name, p->name) &&
+ api_fd_commands[i]->fn != NULL)
{
DEBUG(3,("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n",
- api_fd_commands[i].pipe_clnt_name,
- api_fd_commands[i].pipe_srv_name));
- fstrcpy(p->pipe_srv_name, api_fd_commands[i].pipe_srv_name);
+ api_fd_commands[i]->pipe_clnt_name,
+ api_fd_commands[i]->pipe_srv_name));
+ fstrcpy(p->pipe_srv_name, api_fd_commands[i]->pipe_srv_name);
break;
}
}
- if (api_fd_commands[i].fn == NULL) return False;
+ if (api_fd_commands[i]->fn == NULL) return False;
/* decode the bind request */
smb_io_rpc_hdr_rb("", &p->hdr_rb, pd, 0);
@@ -727,13 +803,13 @@ static BOOL api_pipe_request(pipes_struct *p, prs_struct *pd)
#endif
}
- for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
+ for (i = 0; i < num_cmds; i++)
{
- if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
- api_fd_commands[i].fn != NULL)
+ if (strequal(api_fd_commands[i]->pipe_clnt_name, p->name) &&
+ api_fd_commands[i]->fn != NULL)
{
- DEBUG(3,("Doing \\PIPE\\%s\n", api_fd_commands[i].pipe_clnt_name));
- return api_fd_commands[i].fn(p, pd);
+ DEBUG(3,("Doing \\PIPE\\%s\n", api_fd_commands[i]->pipe_clnt_name));
+ return api_fd_commands[i]->fn(p, pd);
}
}
return False;
@@ -744,6 +820,24 @@ BOOL rpc_command(pipes_struct *p, prs_struct *pd)
BOOL reply = False;
DEBUG(10,("rpc_command\n"));
+ if (p->m != NULL)
+ {
+ DEBUG(10,("msrpc redirect\n"));
+ if (!msrpc_send_prs(p->m, pd))
+ {
+ DEBUG(2,("msrpc redirect send failed\n"));
+ return False;
+ }
+ if (!msrpc_receive_prs(p->m, &p->rhdr))
+ {
+ DEBUG(2,("msrpc redirect receive failed\n"));
+ return False;
+ }
+ prs_link(NULL, &p->rhdr, NULL);
+ prs_debug_out(&p->rhdr, 10);
+ return True;
+ }
+
if (pd->data == NULL) return False;
/* process the rpc header */
diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c
index bd712a1702..a7e451e6da 100644
--- a/source3/rpc_server/srv_pipe_hnd.c
+++ b/source3/rpc_server/srv_pipe_hnd.c
@@ -83,6 +83,7 @@ pipes_struct *open_rpc_pipe_p(char *pipe_name,
int i;
pipes_struct *p;
static int next_pipe;
+ struct msrpc_state *m = NULL;
DEBUG(4,("Open pipe requested %s (pipes_open=%d)\n",
pipe_name, pipes_open));
@@ -108,6 +109,16 @@ pipes_struct *open_rpc_pipe_p(char *pipe_name,
DEBUG(5,("open pipes: name %s pnum=%x\n", p->name, p->pnum));
}
+ if (strequal(pipe_name, "lsarpc"))
+ {
+ m = msrpc_use_add(pipe_name, NULL, False);
+ if (m == NULL)
+ {
+ DEBUG(5,("open pipes: msrpc redirect failed\n"));
+ return NULL;
+ }
+ }
+
p = (pipes_struct *)malloc(sizeof(*p));
if (!p) return NULL;
@@ -120,6 +131,7 @@ pipes_struct *open_rpc_pipe_p(char *pipe_name,
pipes_open++;
p->pnum = i;
+ p->m = m;
p->open = True;
p->device_state = 0;
@@ -359,6 +371,19 @@ BOOL close_rpc_pipe_hnd(pipes_struct *p, connection_struct *conn)
DLIST_REMOVE(Pipes, p);
+ if (p->m != NULL)
+ {
+ DEBUG(4,("closed msrpc redirect: "));
+ if (msrpc_use_del(p->m->pipe_name, &p->m->usr, False, NULL))
+ {
+ DEBUG(4,("OK\n"));
+ }
+ else
+ {
+ DEBUG(4,("FAILED\n"));
+ }
+ }
+
ZERO_STRUCTP(p);
free(p);
diff --git a/source3/smbd/challenge.c b/source3/smbd/challenge.c
new file mode 100644
index 0000000000..cbb34e6395
--- /dev/null
+++ b/source3/smbd/challenge.c
@@ -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);
+}
+
diff --git a/source3/smbd/password.c b/source3/smbd/password.c
index c14b50d3a6..240ec30c3f 100644
--- a/source3/smbd/password.c
+++ b/source3/smbd/password.c
@@ -31,209 +31,6 @@ extern pstring scope;
extern pstring global_myname;
extern fstring global_myworkgroup;
-/* Data to do lanman1/2 password challenge. */
-static unsigned char saved_challenge[8];
-static BOOL challenge_sent=False;
-
-/*******************************************************************
-Get the next challenge value - no repeats.
-********************************************************************/
-void generate_next_challenge(char *challenge)
-{
-#if 0
- /*
- * Leave this ifdef'd out while we test
- * the new crypto random number generator.
- * JRA.
- */
- unsigned char buf[16];
- static int counter = 0;
- struct timeval tval;
- int v1,v2;
-
- /* get a sort-of random number */
- GetTimeOfDay(&tval);
- v1 = (counter++) + getpid() + tval.tv_sec;
- v2 = (counter++) * getpid() + tval.tv_usec;
- SIVAL(challenge,0,v1);
- SIVAL(challenge,4,v2);
-
- /* mash it up with md4 */
- mdfour(buf, (unsigned char *)challenge, 8);
-#else
- unsigned char buf[8];
-
- generate_random_buffer(buf,8,False);
-#endif
- memcpy(saved_challenge, buf, 8);
- memcpy(challenge,buf,8);
- challenge_sent = True;
-}
-
-/*******************************************************************
-set the last challenge sent, usually from a password server
-********************************************************************/
-BOOL set_challenge(unsigned char *challenge)
-{
- memcpy(saved_challenge,challenge,8);
- challenge_sent = True;
- return(True);
-}
-
-/*******************************************************************
-get the last challenge sent
-********************************************************************/
-static BOOL last_challenge(unsigned char *challenge)
-{
- if (!challenge_sent) return False;
- memcpy(challenge,saved_challenge,8);
- return(True);
-}
-
-/* this holds info on user ids that are already validated for this VC */
-static user_struct *validated_users = NULL;
-static int num_validated_users = 0;
-
-/****************************************************************************
-check if a uid has been validated, and return an pointer to the user_struct
-if it has. NULL if not. vuid is biased by an offset. This allows us to
-tell random client vuid's (normally zero) from valid vuids.
-****************************************************************************/
-user_struct *get_valid_user_struct(uint16 vuid)
-{
- if (vuid == UID_FIELD_INVALID)
- return NULL;
- vuid -= VUID_OFFSET;
- if ((vuid >= (uint16)num_validated_users) ||
- (validated_users[vuid].uid == (uid_t)-1) || (validated_users[vuid].gid == (gid_t)-1))
- return NULL;
- return &validated_users[vuid];
-}
-
-/****************************************************************************
-invalidate a uid
-****************************************************************************/
-void invalidate_vuid(uint16 vuid)
-{
- user_struct *vuser = get_valid_user_struct(vuid);
-
- if (vuser == NULL) return;
-
- vuser->uid = (uid_t)-1;
- vuser->gid = (gid_t)-1;
-
- vuser->n_sids = 0;
-
- /* same number of igroups as groups */
- vuser->n_groups = 0;
-
- if (vuser->groups)
- free((char *)vuser->groups);
-
- if (vuser->sids)
- free((char *)vuser->sids);
-
- vuser->sids = NULL;
- vuser->groups = NULL;
-}
-
-
-/****************************************************************************
-return a validated username
-****************************************************************************/
-char *validated_username(uint16 vuid)
-{
- user_struct *vuser = get_valid_user_struct(vuid);
- if (vuser == NULL)
- return 0;
- return(vuser->name);
-}
-
-
-
-/****************************************************************************
-register a uid/name pair as being valid and that a valid password
-has been given. vuid is biased by an offset. This allows us to
-tell random client vuid's (normally zero) from valid vuids.
-****************************************************************************/
-uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, BOOL guest, uchar user_sess_key[16])
-{
- user_struct *vuser;
- struct passwd *pwfile; /* for getting real name from passwd file */
-
- /* Ensure no vuid gets registered in share level security. */
- if(lp_security() == SEC_SHARE)
- return UID_FIELD_INVALID;
-
-#if 0
- /*
- * After observing MS-Exchange services writing to a Samba share
- * I belive this code is incorrect. Each service does its own
- * sessionsetup_and_X for the same user, and as each service shuts
- * down, it does a user_logoff_and_X. As we are consolidating multiple
- * sessionsetup_and_X's onto the same vuid here, when the first service
- * shuts down, it invalidates all the open files for the other services.
- * Hence I am removing this code and forcing each sessionsetup_and_X
- * to get a new vuid.
- * Jeremy Allison. (jallison@whistle.com).
- */
-
- int i;
- for(i = 0; i < num_validated_users; i++) {
- vuser = &validated_users[i];
- if ( vuser->uid == uid )
- return (uint16)(i + VUID_OFFSET); /* User already validated */
- }
-#endif
-
- validated_users = (user_struct *)Realloc(validated_users,
- sizeof(user_struct)*
- (num_validated_users+1));
-
- if (!validated_users)
- {
- DEBUG(0,("Failed to realloc users struct!\n"));
- num_validated_users = 0;
- return UID_FIELD_INVALID;
- }
-
- vuser = &validated_users[num_validated_users];
- num_validated_users++;
-
- vuser->uid = uid;
- vuser->gid = gid;
- vuser->guest = guest;
- fstrcpy(vuser->name,unix_name);
- fstrcpy(vuser->requested_name,requested_name);
- memcpy(vuser->dc.user_sess_key, user_sess_key, sizeof(vuser->dc.user_sess_key));
-
- vuser->n_sids = 0;
- vuser->sids = NULL;
-
- vuser->n_groups = 0;
- vuser->groups = NULL;
-
- /* Find all the groups this uid is in and store them.
- Used by become_user() */
- get_unixgroups(unix_name,uid,gid,
- &vuser->n_groups,
- &vuser->groups);
-
- DEBUG(3,("uid %d registered to name %s\n",(int)uid,unix_name));
-
- DEBUG(3, ("Clearing default real name\n"));
- fstrcpy(vuser->real_name, "<Full Name>\0");
- if (lp_unix_realname()) {
- if ((pwfile=hashed_getpwnam(vuser->name))!= NULL)
- {
- DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->name,pwfile->pw_gecos));
- fstrcpy(vuser->real_name, pwfile->pw_gecos);
- }
- }
-
- return (uint16)((num_validated_users - 1) + VUID_OFFSET);
-}
-
/****************************************************************************
add a name to the session users list
@@ -291,275 +88,6 @@ static BOOL update_smbpassword_file(char *user, char *password)
/****************************************************************************
-core of smb password checking routine.
-****************************************************************************/
-static BOOL smb_pwd_check_ntlmv1(char *password, unsigned char *part_passwd,
- unsigned char *c8,
- uchar sess_key[16])
-{
- /* Finish the encryption of part_passwd. */
- unsigned char p24[24];
-
- if (part_passwd == NULL)
- DEBUG(10,("No password set - allowing access\n"));
- /* No password set - always true ! */
- if (part_passwd == NULL)
- return True;
-
- SMBOWFencrypt(part_passwd, c8, p24);
- if (sess_key != NULL)
- {
- SMBsesskeygen_ntv1(part_passwd, NULL, sess_key);
- }
-
-#if DEBUG_PASSWORD
- DEBUG(100,("Part password (P16) was |"));
- dump_data(100, part_passwd, 16);
- DEBUG(100,("Password from client was |"));
- dump_data(100, password, 24);
- DEBUG(100,("Given challenge was |"));
- dump_data(100, c8, 8);
- DEBUG(100,("Value from encryption was |"));
- dump_data(100, p24, 24);
-#endif
- return (memcmp(p24, password, 24) == 0);
-}
-
-/****************************************************************************
-core of smb password checking routine.
-****************************************************************************/
-static BOOL smb_pwd_check_ntlmv2(char *password, size_t pwd_len,
- unsigned char *part_passwd,
- unsigned char const *c8,
- const char *user, const char *domain,
- char *sess_key)
-{
- /* Finish the encryption of part_passwd. */
- unsigned char kr[16];
- unsigned char resp[16];
-
- if (part_passwd == NULL)
- {
- DEBUG(10,("No password set - allowing access\n"));
- }
- /* No password set - always true ! */
- if (part_passwd == NULL)
- {
- return True;
- }
-
- ntv2_owf_gen(part_passwd, user, domain, kr);
- SMBOWFencrypt_ntv2(kr, c8, 8, password+16, pwd_len-16, resp);
- if (sess_key != NULL)
- {
- SMBsesskeygen_ntv2(kr, resp, sess_key);
- }
-
-#if DEBUG_PASSWORD
- DEBUG(100,("Part password (P16) was |"));
- dump_data(100, part_passwd, 16);
- DEBUG(100,("Password from client was |"));
- dump_data(100, password, pwd_len);
- DEBUG(100,("Given challenge was |"));
- dump_data(100, c8, 8);
- DEBUG(100,("Value from encryption was |"));
- dump_data(100, resp, 16);
-#endif
-
- return (memcmp(resp, password, 16) == 0);
-}
-
-/****************************************************************************
- Do a specific test for an smb password being correct, given a smb_password and
- the lanman and NT responses.
-****************************************************************************/
-BOOL smb_password_ok(struct smb_passwd *smb_pass, uchar chal[8],
- const char *user, const char *domain,
- uchar *lm_pass, size_t lm_pwd_len,
- uchar *nt_pass, size_t nt_pwd_len,
- uchar sess_key[16])
-{
- uchar challenge[8];
-
- if (smb_pass == NULL)
- {
- return False;
- }
-
- DEBUG(4,("Checking SMB password for user %s\n",
- smb_pass->unix_name));
-
- if (smb_pass->acct_ctrl & ACB_DISABLED)
- {
- DEBUG(3,("account for user %s was disabled.\n",
- smb_pass->unix_name));
- return False;
- }
-
- if (chal == NULL)
- {
- DEBUG(5,("use last SMBnegprot challenge\n"));
- if (!last_challenge(challenge))
- {
- DEBUG(1,("no challenge done - password failed\n"));
- return False;
- }
- }
- else
- {
- DEBUG(5,("challenge received\n"));
- memcpy(challenge, chal, 8);
- }
-
- if ((Protocol >= PROTOCOL_NT1) && (smb_pass->smb_nt_passwd != NULL))
- {
- /* We have the NT MD4 hash challenge available - see if we can
- use it (ie. does it exist in the smbpasswd file).
- */
- if (lp_server_ntlmv2() != False && nt_pwd_len > 24)
- {
- DEBUG(4,("smb_password_ok: Check NTLMv2 password\n"));
- if (smb_pwd_check_ntlmv2(nt_pass, nt_pwd_len,
- (uchar *)smb_pass->smb_nt_passwd,
- challenge, user, domain,
- sess_key))
- {
- return True;
- }
- }
- if (lp_server_ntlmv2() != True && nt_pwd_len == 24)
- {
- DEBUG(4,("smb_password_ok: Check NT MD4 password\n"));
- if (smb_pwd_check_ntlmv1((char *)nt_pass,
- (uchar *)smb_pass->smb_nt_passwd,
- challenge,
- sess_key))
- {
- DEBUG(4,("NT MD4 password check succeeded\n"));
- return True;
- }
- }
- DEBUG(4,("NT MD4 password check failed\n"));
- }
-
- if (lp_server_ntlmv2() == True)
- {
- DEBUG(4,("Not checking LM MD4 password\n"));
- return False;
- }
-
- /* Try against the lanman password. smb_pass->smb_passwd == NULL means
- no password, allow access. */
-
- DEBUG(4,("Checking LM MD4 password\n"));
-
- if ((smb_pass->smb_passwd == NULL) &&
- (smb_pass->acct_ctrl & ACB_PWNOTREQ))
- {
- DEBUG(4,("no password required for user %s\n",
- smb_pass->unix_name));
- return True;
- }
-
- if ((smb_pass->smb_passwd != NULL) &&
- smb_pwd_check_ntlmv1((char *)lm_pass,
- (uchar *)smb_pass->smb_passwd,
- challenge, NULL))
- {
- DEBUG(4,("LM MD4 password check succeeded\n"));
- return(True);
- }
-
- DEBUG(4,("LM MD4 password check failed\n"));
-
- return False;
-}
-
-
-/****************************************************************************
-check if a username/password is OK assuming the password is a 24 byte
-SMB hash
-return True if the password is correct, False otherwise
-****************************************************************************/
-
-BOOL pass_check_smb(struct smb_passwd *smb_pass, char *domain, uchar *chal,
- uchar *lm_pwd, size_t lm_pwd_len,
- uchar *nt_pwd, size_t nt_pwd_len,
- struct passwd *pwd, uchar user_sess_key[16])
-{
- const struct passwd *pass;
- struct passwd pw;
- char *user = NULL;
-
- if (smb_pass == NULL)
- {
- DEBUG(3,("Couldn't find user %s in smb_passwd file.\n", user));
- return False;
- }
-
- user = smb_pass->unix_name;
-
- if (lm_pwd == NULL || nt_pwd == NULL)
- {
- return False;
- }
-
- if (pwd != NULL && user == NULL)
- {
- pass = (struct passwd *) pwd;
- user = pass->pw_name;
- }
- else
- {
- pass = Get_Pwnam(user,True);
- if (pass == NULL)
- {
- DEBUG(3,("Couldn't find user %s\n",user));
- return False;
- }
- memcpy(&pw, pass, sizeof(struct passwd));
- pass = &pw;
- }
-
- /* Quit if the account was disabled. */
- if (smb_pass->acct_ctrl & ACB_DISABLED) {
- DEBUG(3,("account for user %s was disabled.\n", user));
- return False;
- }
-
- /* Ensure the uid's match */
- if (smb_pass->unix_uid != pass->pw_uid)
- {
- DEBUG(3,("Error : UNIX (%d) and SMB (%d) uids in password files do not match !\n", pass->pw_uid, smb_pass->unix_uid));
- return False;
- }
-
- if (lm_pwd[0] == '\0' && IS_BITS_SET_ALL(smb_pass->acct_ctrl, ACB_PWNOTREQ) && lp_null_passwords())
- {
- DEBUG(3,("account for user %s has no password and null passwords are allowed.\n", smb_pass->unix_name));
- return(True);
- }
-
- if (smb_password_ok(smb_pass, chal, user, domain,
- lm_pwd, lm_pwd_len,
- nt_pwd, nt_pwd_len,
- user_sess_key))
- {
- if (user_sess_key != NULL)
- {
-#ifdef DEBUG_PASSWORD
- DEBUG(100,("user session key: "));
- dump_data(100, user_sess_key, 16);
-#endif
- }
- return(True);
- }
-
- DEBUG(3,("Error pass_check_smb failed\n"));
- return False;
-}
-
-/****************************************************************************
check if a username/password pair is OK either via the system password
database or the encrypted SMB password database
return True if the password is correct, False otherwise
@@ -589,35 +117,6 @@ BOOL password_ok(char *user, char *password, int pwlen, struct passwd *pwd,
update_smbpassword_file : NULL);
}
-/****************************************************************************
-check if a username is valid
-****************************************************************************/
-BOOL user_ok(char *user,int snum)
-{
- pstring valid, invalid;
- BOOL ret;
-
- StrnCpy(valid, lp_valid_users(snum), sizeof(pstring));
- StrnCpy(invalid, lp_invalid_users(snum), sizeof(pstring));
-
- string_sub(valid,"%S",lp_servicename(snum));
- string_sub(invalid,"%S",lp_servicename(snum));
-
- ret = !user_in_list(user,invalid);
-
- if (ret && valid && *valid) {
- ret = user_in_list(user,valid);
- }
-
- if (ret && lp_onlyuser(snum)) {
- char *user_list = lp_username(snum);
- string_sub(user_list,"%S",lp_servicename(snum));
- ret = user_in_list(user,user_list);
- }
-
- return(ret);
-}
-
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index a0ad2ca20d..81f2a9beb9 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -415,6 +415,7 @@ static int session_trust_account(connection_struct *conn, char *inbuf, char *out
char *smb_nt_passwd, int smb_nt_passlen)
{
struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */
+ uchar last_chal[8];
if (lp_security() == SEC_USER)
{
smb_trust_acct = getsmbpwnam(user);
@@ -441,8 +442,8 @@ static int session_trust_account(connection_struct *conn, char *inbuf, char *out
SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
}
-
- if (!smb_password_ok(smb_trust_acct, NULL, NULL, NULL,
+ if (!last_challenge(last_chal) ||
+ !smb_password_ok(smb_trust_acct, last_chal, NULL, NULL,
(unsigned char *)smb_passwd, smb_passlen,
(unsigned char *)smb_nt_passwd, smb_nt_passlen, NULL))
{
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index 5512e6e56b..7fde1fc6f6 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -678,6 +678,18 @@ static void usage(char *pname)
}
#endif /* WITH_SSL */
+#if 0
+ start_msrpc_agent("lsarpc");
+#endif
+ add_msrpc_command_processor( "samr", "lsass", api_samr_rpc );
+ add_msrpc_command_processor( "srvsvc", "ntsvcs", api_srvsvc_rpc );
+ add_msrpc_command_processor( "wkssvc", "ntsvcs", api_wkssvc_rpc );
+ add_msrpc_command_processor( "browser", "ntsvcs", api_brs_rpc );
+ add_msrpc_command_processor( "svcctl", "ntsvcs", api_svcctl_rpc );
+ add_msrpc_command_processor( "NETLOGON", "lsass", api_netlog_rpc );
+ add_msrpc_command_processor( "winreg", "winreg", api_reg_rpc );
+ add_msrpc_command_processor( "spoolss", "spoolss", api_spoolss_rpc );
+
codepage_initialise(lp_client_code_page());
if (!pwdb_initialise(True))