the first independent msrpc daemon - lsarpcd.
authorLuke Leighton <lkcl@samba.org>
Mon, 6 Dec 1999 00:44:32 +0000 (00:44 +0000)
committerLuke Leighton <lkcl@samba.org>
Mon, 6 Dec 1999 00:44:32 +0000 (00:44 +0000)
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)

18 files changed:
source3/Makefile.in
source3/include/ntdomain.h
source3/include/proto.h
source3/lib/msrpc-agent.c
source3/lib/msrpc-client.c
source3/lib/passcheck.c [new file with mode: 0644]
source3/lib/username.c
source3/lib/util_sock.c
source3/lib/vuser.c [new file with mode: 0644]
source3/lsarpcd/lsarpcd.c [new file with mode: 0644]
source3/lsarpcd/lsarpcd_process.c [new file with mode: 0644]
source3/rpc_parse/parse_prs.c
source3/rpc_server/srv_pipe.c
source3/rpc_server/srv_pipe_hnd.c
source3/smbd/challenge.c [new file with mode: 0644]
source3/smbd/password.c
source3/smbd/reply.c
source3/smbd/server.c

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